sort: fix multibyte incompabilities (#821264)

This commit is contained in:
Ondrej Oprala 2013-08-14 19:01:16 +02:00
parent bce5991c5f
commit 0dcc5a0d5e
2 changed files with 128 additions and 100 deletions

View File

@ -2419,8 +2419,8 @@ diff -urNp coreutils-8.21-orig/src/pr.c coreutils-8.21/src/pr.c
looking for more options and printing the next batch of files. looking for more options and printing the next batch of files.
diff -urNp coreutils-8.21-orig/src/sort.c coreutils-8.21/src/sort.c diff -urNp coreutils-8.21-orig/src/sort.c coreutils-8.21/src/sort.c
--- coreutils-8.21-orig/src/sort.c 2013-01-31 01:46:24.000000000 +0100 --- coreutils-8.21-orig/src/sort.c 2013-08-14 18:14:06.172216606 +0200
+++ coreutils-8.21/src/sort.c 2013-02-15 14:25:07.828467769 +0100 +++ coreutils-8.21/src/sort.c 2013-08-14 18:13:30.295247905 +0200
@@ -29,6 +29,14 @@ @@ -29,6 +29,14 @@
#include <sys/wait.h> #include <sys/wait.h>
#include <signal.h> #include <signal.h>
@ -2440,8 +2440,8 @@ diff -urNp coreutils-8.21-orig/src/sort.c coreutils-8.21/src/sort.c
/* Nonzero if the corresponding locales are hard. */ /* Nonzero if the corresponding locales are hard. */
static bool hard_LC_COLLATE; static bool hard_LC_COLLATE;
-#if HAVE_NL_LANGINFO
+#if HAVE_LANGINFO_CODESET +#if HAVE_LANGINFO_CODESET
-#if HAVE_NL_LANGINFO
static bool hard_LC_TIME; static bool hard_LC_TIME;
#endif #endif
@ -2476,16 +2476,16 @@ diff -urNp coreutils-8.21-orig/src/sort.c coreutils-8.21/src/sort.c
they were read if all keys compare equal. */ they were read if all keys compare equal. */
static bool stable; static bool stable;
+/* Tab character separating fields. If tab_length is 0, then fields are
-/* If TAB has this value, blanks separate fields. */ -/* If TAB has this value, blanks separate fields. */
-enum { TAB_DEFAULT = CHAR_MAX + 1 }; -enum { TAB_DEFAULT = CHAR_MAX + 1 };
- -
-/* Tab character separating fields. If TAB_DEFAULT, then fields are -/* Tab character separating fields. If TAB_DEFAULT, then fields are
+/* Tab character separating fields. If tab_length is 0, then fields are
separated by the empty string between a non-blank character and a blank separated by the empty string between a non-blank character and a blank
character. */ character. */
-static int tab = TAB_DEFAULT;
+static char tab[MB_LEN_MAX + 1]; +static char tab[MB_LEN_MAX + 1];
+static size_t tab_length = 0; +static size_t tab_length = 0;
-static int tab = TAB_DEFAULT;
/* Flag to remove consecutive duplicate lines from the output. /* Flag to remove consecutive duplicate lines from the output.
Only the last of a sequence of equal lines will be output. */ Only the last of a sequence of equal lines will be output. */
@ -2540,8 +2540,8 @@ diff -urNp coreutils-8.21-orig/src/sort.c coreutils-8.21/src/sort.c
free (node); free (node);
} }
-#if HAVE_NL_LANGINFO
+#if HAVE_LANGINFO_CODESET +#if HAVE_LANGINFO_CODESET
-#if HAVE_NL_LANGINFO
static int static int
struct_month_cmp (void const *m1, void const *m2) struct_month_cmp (void const *m1, void const *m2)
@ -2549,17 +2549,17 @@ diff -urNp coreutils-8.21-orig/src/sort.c coreutils-8.21/src/sort.c
/* Initialize the character class tables. */ /* Initialize the character class tables. */
static void static void
-inittables (void)
+inittables_uni (void) +inittables_uni (void)
-inittables (void)
{ {
size_t i; size_t i;
@@ -1250,7 +1318,7 @@ inittables (void) @@ -1250,7 +1318,7 @@ inittables_uni (void)
fold_toupper[i] = toupper (i); fold_toupper[i] = toupper (i);
} }
-#if HAVE_NL_LANGINFO
+#if HAVE_LANGINFO_CODESET +#if HAVE_LANGINFO_CODESET
-#if HAVE_NL_LANGINFO
/* If we're not in the "C" locale, read different names for months. */ /* If we're not in the "C" locale, read different names for months. */
if (hard_LC_TIME) if (hard_LC_TIME)
{ {
@ -2652,25 +2652,25 @@ diff -urNp coreutils-8.21-orig/src/sort.c coreutils-8.21/src/sort.c
by KEY in LINE. */ by KEY in LINE. */
static char * static char *
-begfield (struct line const *line, struct keyfield const *key)
+begfield_uni (const struct line *line, const struct keyfield *key) +begfield_uni (const struct line *line, const struct keyfield *key)
-begfield (struct line const *line, struct keyfield const *key)
{ {
char *ptr = line->text, *lim = ptr + line->length - 1; char *ptr = line->text, *lim = ptr + line->length - 1;
size_t sword = key->sword; size_t sword = key->sword;
@@ -1573,10 +1719,10 @@ begfield (struct line const *line, struc @@ -1573,10 +1719,10 @@ begfield_uni (const struct line *line, c
/* The leading field separator itself is included in a field when -t /* The leading field separator itself is included in a field when -t
is absent. */ is absent. */
- if (tab != TAB_DEFAULT)
+ if (tab_length) + if (tab_length)
- if (tab != TAB_DEFAULT)
while (ptr < lim && sword--) while (ptr < lim && sword--)
{ {
- while (ptr < lim && *ptr != tab)
+ while (ptr < lim && *ptr != tab[0]) + while (ptr < lim && *ptr != tab[0])
- while (ptr < lim && *ptr != tab)
++ptr; ++ptr;
if (ptr < lim) if (ptr < lim)
++ptr; ++ptr;
@@ -1602,11 +1748,70 @@ begfield (struct line const *line, struc @@ -1602,11 +1748,70 @@ begfield_uni (const struct line *line, c
return ptr; return ptr;
} }
@ -2737,38 +2737,38 @@ diff -urNp coreutils-8.21-orig/src/sort.c coreutils-8.21/src/sort.c
in LINE specified by KEY. */ in LINE specified by KEY. */
static char * static char *
-limfield (struct line const *line, struct keyfield const *key)
+limfield_uni (const struct line *line, const struct keyfield *key) +limfield_uni (const struct line *line, const struct keyfield *key)
-limfield (struct line const *line, struct keyfield const *key)
{ {
char *ptr = line->text, *lim = ptr + line->length - 1; char *ptr = line->text, *lim = ptr + line->length - 1;
size_t eword = key->eword, echar = key->echar; size_t eword = key->eword, echar = key->echar;
@@ -1621,10 +1826,10 @@ limfield (struct line const *line, struc @@ -1621,10 +1826,10 @@ limfield_uni (const struct line *line, c
'beginning' is the first character following the delimiting TAB. 'beginning' is the first character following the delimiting TAB.
Otherwise, leave PTR pointing at the first 'blank' character after Otherwise, leave PTR pointing at the first 'blank' character after
the preceding field. */ the preceding field. */
- if (tab != TAB_DEFAULT)
+ if (tab_length) + if (tab_length)
- if (tab != TAB_DEFAULT)
while (ptr < lim && eword--) while (ptr < lim && eword--)
{ {
- while (ptr < lim && *ptr != tab)
+ while (ptr < lim && *ptr != tab[0]) + while (ptr < lim && *ptr != tab[0])
- while (ptr < lim && *ptr != tab)
++ptr; ++ptr;
if (ptr < lim && (eword || echar)) if (ptr < lim && (eword || echar))
++ptr; ++ptr;
@@ -1670,10 +1875,10 @@ limfield (struct line const *line, struc @@ -1670,10 +1875,10 @@ limfield_uni (const struct line *line, c
*/ */
/* Make LIM point to the end of (one byte past) the current field. */ /* Make LIM point to the end of (one byte past) the current field. */
- if (tab != TAB_DEFAULT)
+ if (tab_length) + if (tab_length)
- if (tab != TAB_DEFAULT)
{ {
char *newlim; char *newlim;
- newlim = memchr (ptr, tab, lim - ptr);
+ newlim = memchr (ptr, tab[0], lim - ptr); + newlim = memchr (ptr, tab[0], lim - ptr);
- newlim = memchr (ptr, tab, lim - ptr);
if (newlim) if (newlim)
lim = newlim; lim = newlim;
} }
@@ -1704,6 +1909,130 @@ limfield (struct line const *line, struc @@ -1704,6 +1909,130 @@ limfield_uni (const struct line *line, c
return ptr; return ptr;
} }
@ -2857,7 +2857,7 @@ diff -urNp coreutils-8.21-orig/src/sort.c coreutils-8.21/src/sort.c
+ { + {
+ /* If we're skipping leading blanks, don't start counting characters + /* If we're skipping leading blanks, don't start counting characters
+ * until after skipping past any leading blanks. */ + * until after skipping past any leading blanks. */
+ if (key->skipsblanks) + if (key->skipeblanks)
+ while (ptr < lim && ismbblank (ptr, lim - ptr, &mblength)) + while (ptr < lim && ismbblank (ptr, lim - ptr, &mblength))
+ ptr += mblength; + ptr += mblength;
+ +
@ -2903,8 +2903,6 @@ diff -urNp coreutils-8.21-orig/src/sort.c coreutils-8.21/src/sort.c
else else
{ {
if (key->skipsblanks) if (key->skipsblanks)
- while (blanks[to_uchar (*line_start)])
- line_start++;
+ { + {
+#if HAVE_MBRTOWC +#if HAVE_MBRTOWC
+ if (MB_CUR_MAX > 1) + if (MB_CUR_MAX > 1)
@ -2921,6 +2919,8 @@ diff -urNp coreutils-8.21-orig/src/sort.c coreutils-8.21/src/sort.c
+ while (blanks[to_uchar (*line_start)]) + while (blanks[to_uchar (*line_start)])
+ line_start++; + line_start++;
+ } + }
- while (blanks[to_uchar (*line_start)])
- line_start++;
line->keybeg = line_start; line->keybeg = line_start;
} }
} }
@ -2928,12 +2928,12 @@ diff -urNp coreutils-8.21-orig/src/sort.c coreutils-8.21/src/sort.c
hideously fast. */ hideously fast. */
static int static int
-numcompare (char const *a, char const *b)
+numcompare_uni (const char *a, const char *b) +numcompare_uni (const char *a, const char *b)
-numcompare (char const *a, char const *b)
{ {
while (blanks[to_uchar (*a)]) while (blanks[to_uchar (*a)])
a++; a++;
@@ -1922,6 +2265,25 @@ numcompare (char const *a, char const *b @@ -1922,6 +2265,25 @@ numcompare_uni (const char *a, const cha
return strnumcmp (a, b, decimal_point, thousands_sep); return strnumcmp (a, b, decimal_point, thousands_sep);
} }
@ -2963,8 +2963,8 @@ diff -urNp coreutils-8.21-orig/src/sort.c coreutils-8.21/src/sort.c
Return 0 if the name in S is not recognized. */ Return 0 if the name in S is not recognized. */
static int static int
-getmonth (char const *month, char **ea)
+getmonth_uni (char const *month, size_t len, char **ea) +getmonth_uni (char const *month, size_t len, char **ea)
-getmonth (char const *month, char **ea)
{ {
size_t lo = 0; size_t lo = 0;
size_t hi = MONTHS_PER_YEAR; size_t hi = MONTHS_PER_YEAR;
@ -2972,17 +2972,17 @@ diff -urNp coreutils-8.21-orig/src/sort.c coreutils-8.21/src/sort.c
char saved = *lim; char saved = *lim;
*lim = '\0'; *lim = '\0';
+ skipblanks (&beg, lim);
- while (blanks[to_uchar (*beg)]) - while (blanks[to_uchar (*beg)])
- beg++; - beg++;
+ skipblanks (&beg, lim);
char *tighter_lim = beg; char *tighter_lim = beg;
if (lim < beg) if (lim < beg)
tighter_lim = lim; tighter_lim = lim;
else if (key->month) else if (key->month)
- getmonth (beg, &tighter_lim);
+ getmonth (beg, lim-beg, &tighter_lim); + getmonth (beg, lim-beg, &tighter_lim);
- getmonth (beg, &tighter_lim);
else if (key->general_numeric) else if (key->general_numeric)
ignore_value (strtold (beg, &tighter_lim)); ignore_value (strtold (beg, &tighter_lim));
else if (key->numeric || key->human_numeric) else if (key->numeric || key->human_numeric)
@ -2990,8 +2990,8 @@ diff -urNp coreutils-8.21-orig/src/sort.c coreutils-8.21/src/sort.c
bool maybe_space_aligned = !hard_LC_COLLATE && default_key_compare (key) bool maybe_space_aligned = !hard_LC_COLLATE && default_key_compare (key)
&& !(key->schar || key->echar); && !(key->schar || key->echar);
bool line_offset = key->eword == 0 && key->echar != 0; /* -k1.x,1.y */ bool line_offset = key->eword == 0 && key->echar != 0; /* -k1.x,1.y */
- if (!gkey_only && tab == TAB_DEFAULT && !line_offset
+ if (!gkey_only && !tab_length && !line_offset + if (!gkey_only && !tab_length && !line_offset
- if (!gkey_only && tab == TAB_DEFAULT && !line_offset
&& ((!key->skipsblanks && !(implicit_skip || maybe_space_aligned)) && ((!key->skipsblanks && !(implicit_skip || maybe_space_aligned))
|| (!key->skipsblanks && key->schar) || (!key->skipsblanks && key->schar)
|| (!key->skipeblanks && key->echar))) || (!key->skipeblanks && key->echar)))
@ -3079,21 +3079,21 @@ diff -urNp coreutils-8.21-orig/src/sort.c coreutils-8.21/src/sort.c
are no more keys or a difference is found. */ are no more keys or a difference is found. */
static int static int
-keycompare (struct line const *a, struct line const *b)
+keycompare_uni (const struct line *a, const struct line *b) +keycompare_uni (const struct line *a, const struct line *b)
-keycompare (struct line const *a, struct line const *b)
{ {
struct keyfield *key = keylist; struct keyfield *key = keylist;
@@ -2546,7 +2983,7 @@ keycompare (struct line const *a, struct @@ -2546,7 +2983,7 @@ keycompare_uni (const struct line *a, co
else if (key->human_numeric) else if (key->human_numeric)
diff = human_numcompare (ta, tb); diff = human_numcompare (ta, tb);
else if (key->month) else if (key->month)
- diff = getmonth (ta, NULL) - getmonth (tb, NULL);
+ diff = getmonth (ta, tlena, NULL) - getmonth (tb, tlenb, NULL); + diff = getmonth (ta, tlena, NULL) - getmonth (tb, tlenb, NULL);
- diff = getmonth (ta, NULL) - getmonth (tb, NULL);
else if (key->random) else if (key->random)
diff = compare_random (ta, tlena, tb, tlenb); diff = compare_random (ta, tlena, tb, tlenb);
else if (key->version) else if (key->version)
@@ -2662,6 +3099,181 @@ keycompare (struct line const *a, struct @@ -2662,6 +3099,191 @@ keycompare_uni (const struct line *a, co
return key->reverse ? -diff : diff; return key->reverse ? -diff : diff;
} }
@ -3114,45 +3114,14 @@ diff -urNp coreutils-8.21-orig/src/sort.c coreutils-8.21/src/sort.c
+ wchar_t wc_a, wc_b; + wchar_t wc_a, wc_b;
+ mbstate_t state_a, state_b; + mbstate_t state_a, state_b;
+ +
+ int diff; + int diff = 0;
+ +
+ memset (&state_a, '\0', sizeof(mbstate_t)); + memset (&state_a, '\0', sizeof(mbstate_t));
+ memset (&state_b, '\0', sizeof(mbstate_t)); + memset (&state_b, '\0', sizeof(mbstate_t));
+ /* Ignore keys with start after end. */
+ if (a->keybeg - a->keylim > 0)
+ return 0;
+ +
+ for (;;)
+ {
+ char const *translate = key->translate;
+ bool const *ignore = key->ignore;
+
+ /* Find the lengths. */
+ size_t lena = lima <= texta ? 0 : lima - texta;
+ size_t lenb = limb <= textb ? 0 : limb - textb;
+
+ /* Actually compare the fields. */
+ if (key->random)
+ diff = compare_random (texta, lena, textb, lenb);
+ else if (key->numeric | key->general_numeric | key->human_numeric)
+ {
+ char savea = *lima, saveb = *limb;
+
+ *lima = *limb = '\0';
+ diff = (key->numeric ? numcompare (texta, textb)
+ : key->general_numeric ? general_numcompare (texta, textb)
+ : human_numcompare (texta, textb));
+ *lima = savea, *limb = saveb;
+ }
+ else if (key->version)
+ diff = filevercmp (texta, textb);
+ else if (key->month)
+ diff = getmonth (texta, lena, NULL) - getmonth (textb, lenb, NULL);
+ else
+ {
+ if (ignore || translate)
+ {
+ char *copy_a = (char *) xmalloc (lena + 1 + lenb + 1);
+ char *copy_b = copy_a + lena + 1;
+ size_t new_len_a, new_len_b;
+ size_t i, j;
+ +
+ /* Ignore and/or translate chars before comparing. */ + /* Ignore and/or translate chars before comparing. */
+# define IGNORE_CHARS(NEW_LEN, LEN, TEXT, COPY, WC, MBLENGTH, STATE) \ +# define IGNORE_CHARS(NEW_LEN, LEN, TEXT, COPY, WC, MBLENGTH, STATE) \
@ -3220,21 +3189,63 @@ diff -urNp coreutils-8.21-orig/src/sort.c coreutils-8.21/src/sort.c
+ COPY[NEW_LEN] = '\0'; \ + COPY[NEW_LEN] = '\0'; \
+ } \ + } \
+ while (0) + while (0)
+ IGNORE_CHARS (new_len_a, lena, texta, copy_a, +
+ wc_a, mblength_a, state_a); + /* Actually compare the fields. */
+ IGNORE_CHARS (new_len_b, lenb, textb, copy_b, +
+ wc_b, mblength_b, state_b); + for (;;)
+ diff = xmemcoll (copy_a, new_len_a, copy_b, new_len_b); + {
+ free(copy_a); + /* Find the lengths. */
+ } + size_t lena = lima <= texta ? 0 : lima - texta;
+ else if (lena == 0) + size_t lenb = limb <= textb ? 0 : limb - textb;
+ diff = - NONZERO (lenb); +
+ else if (lenb == 0) + char const *translate = key->translate;
+ goto greater; + bool const *ignore = key->ignore;
+ else +
+ diff = xmemcoll (texta, lena, textb, lenb); + if (ignore || translate)
+ {
+ char *copy_a = (char *) xmalloc (lena + 1 + lenb + 1);
+ char *copy_b = copy_a + lena + 1;
+ size_t new_len_a, new_len_b;
+ size_t i, j;
+
+ IGNORE_CHARS (new_len_a, lena, texta, copy_a,
+ wc_a, mblength_a, state_a);
+ IGNORE_CHARS (new_len_b, lenb, textb, copy_b,
+ wc_b, mblength_b, state_b);
+ texta = copy_a; textb = copy_b;
+ lena = new_len_a; lenb = new_len_b;
+ } + }
+ +
+ if (key->random)
+ diff = compare_random (texta, lena, textb, lenb);
+ else if (key->numeric | key->general_numeric | key->human_numeric)
+ {
+ char savea = *lima, saveb = *limb;
+
+ *lima = *limb = '\0';
+ diff = (key->numeric ? numcompare (texta, textb)
+ : key->general_numeric ? general_numcompare (texta, textb)
+ : human_numcompare (texta, textb));
+ *lima = savea, *limb = saveb;
+ }
+ else if (key->version)
+ diff = filevercmp (texta, textb);
+ else if (key->month)
+ diff = getmonth (texta, lena, NULL) - getmonth (textb, lenb, NULL);
+ else if (lena == 0)
+ diff = - NONZERO (lenb);
+ else if (lenb == 0)
+ diff = 1;
+ else
+ {
+ diff = memcmp (texta, textb, MIN (lena,lenb));
+ if (!diff)
+ diff = xmemcoll (texta, lena, textb, lenb);
+ }
+
+ if (ignore || translate)
+ free (texta);
+
+ if (diff) + if (diff)
+ goto not_equal; + goto not_equal;
+ +
@ -3263,28 +3274,42 @@ diff -urNp coreutils-8.21-orig/src/sort.c coreutils-8.21/src/sort.c
+ } + }
+ } + }
+ +
+ return 0;
+
+greater:
+ diff = 1;
+not_equal: +not_equal:
+ return key->reverse ? -diff : diff; + if (key && key->reverse)
+ return -diff;
+ else
+ return diff;
+} +}
+#endif +#endif
+ +
/* Compare two lines A and B, returning negative, zero, or positive /* Compare two lines A and B, returning negative, zero, or positive
depending on whether A compares less than, equal to, or greater than B. */ depending on whether A compares less than, equal to, or greater than B. */
@@ -4157,7 +4769,7 @@ main (int argc, char **argv) @@ -2689,14 +3311,6 @@ compare (struct line const *a, struct li
diff = - NONZERO (blen);
else if (blen == 0)
diff = 1;
- else if (hard_LC_COLLATE)
- {
- /* Note xmemcoll0 is a performance enhancement as
- it will not unconditionally write '\0' after the
- passed in buffers, which was seen to give around
- a 3% increase in performance for short lines. */
- diff = xmemcoll0 (a->text, alen + 1, b->text, blen + 1);
- }
else if (! (diff = memcmp (a->text, b->text, MIN (alen, blen))))
diff = alen < blen ? -1 : alen != blen;
@@ -4157,7 +4771,7 @@ main (int argc, char **argv)
initialize_exit_failure (SORT_FAILURE); initialize_exit_failure (SORT_FAILURE);
hard_LC_COLLATE = hard_locale (LC_COLLATE); hard_LC_COLLATE = hard_locale (LC_COLLATE);
-#if HAVE_NL_LANGINFO
+#if HAVE_LANGINFO_CODESET +#if HAVE_LANGINFO_CODESET
-#if HAVE_NL_LANGINFO
hard_LC_TIME = hard_locale (LC_TIME); hard_LC_TIME = hard_locale (LC_TIME);
#endif #endif
@@ -4178,6 +4790,29 @@ main (int argc, char **argv) @@ -4178,6 +4792,29 @@ main (int argc, char **argv)
thousands_sep = -1; thousands_sep = -1;
} }
@ -3314,18 +3339,17 @@ diff -urNp coreutils-8.21-orig/src/sort.c coreutils-8.21/src/sort.c
have_read_stdin = false; have_read_stdin = false;
inittables (); inittables ();
@@ -4452,13 +5087,34 @@ main (int argc, char **argv) @@ -4452,13 +5089,34 @@ main (int argc, char **argv)
case 't': case 't':
{ {
- char newtab = optarg[0];
- if (! newtab)
+ char newtab[MB_LEN_MAX + 1]; + char newtab[MB_LEN_MAX + 1];
+ size_t newtab_length = 1; + size_t newtab_length = 1;
+ strncpy (newtab, optarg, MB_LEN_MAX); + strncpy (newtab, optarg, MB_LEN_MAX);
+ if (! newtab[0]) + if (! newtab[0])
- char newtab = optarg[0];
- if (! newtab)
error (SORT_FAILURE, 0, _("empty tab")); error (SORT_FAILURE, 0, _("empty tab"));
- if (optarg[1])
+#if HAVE_MBRTOWC +#if HAVE_MBRTOWC
+ if (MB_CUR_MAX > 1) + if (MB_CUR_MAX > 1)
+ { + {
@ -3346,25 +3370,26 @@ diff -urNp coreutils-8.21-orig/src/sort.c coreutils-8.21/src/sort.c
+ } + }
+#endif +#endif
+ if (newtab_length == 1 && optarg[1]) + if (newtab_length == 1 && optarg[1])
- if (optarg[1])
{ {
if (STREQ (optarg, "\\0")) if (STREQ (optarg, "\\0"))
- newtab = '\0';
+ newtab[0] = '\0'; + newtab[0] = '\0';
- newtab = '\0';
else else
{ {
/* Provoke with 'sort -txx'. Complain about /* Provoke with 'sort -txx'. Complain about
@@ -4469,9 +5125,12 @@ main (int argc, char **argv) @@ -4469,9 +5127,12 @@ main (int argc, char **argv)
quote (optarg)); quote (optarg));
} }
} }
- if (tab != TAB_DEFAULT && tab != newtab)
+ if (tab_length + if (tab_length
+ && (tab_length != newtab_length + && (tab_length != newtab_length
+ || memcmp (tab, newtab, tab_length) != 0)) + || memcmp (tab, newtab, tab_length) != 0))
- if (tab != TAB_DEFAULT && tab != newtab)
error (SORT_FAILURE, 0, _("incompatible tabs")); error (SORT_FAILURE, 0, _("incompatible tabs"));
- tab = newtab;
+ memcpy (tab, newtab, newtab_length); + memcpy (tab, newtab, newtab_length);
+ tab_length = newtab_length; + tab_length = newtab_length;
- tab = newtab;
} }
break; break;

View File

@ -1,7 +1,7 @@
Summary: A set of basic GNU tools commonly used in shell scripts Summary: A set of basic GNU tools commonly used in shell scripts
Name: coreutils Name: coreutils
Version: 8.21 Version: 8.21
Release: 16%{?dist} Release: 17%{?dist}
License: GPLv3+ License: GPLv3+
Group: System Environment/Base Group: System Environment/Base
Url: http://www.gnu.org/software/coreutils/ Url: http://www.gnu.org/software/coreutils/
@ -375,6 +375,9 @@ fi
%{_sbindir}/chroot %{_sbindir}/chroot
%changelog %changelog
* Wed Aug 14 2013 Ondrej Oprala <ooprala@redhat.com> 8.21-17
- Fix sort multibyte incompatibilities
* Sat Aug 03 2013 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 8.21-16 * Sat Aug 03 2013 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 8.21-16
- Rebuilt for https://fedoraproject.org/wiki/Fedora_20_Mass_Rebuild - Rebuilt for https://fedoraproject.org/wiki/Fedora_20_Mass_Rebuild