diff --git a/fnmatch-collating-elements.patch b/fnmatch-collating-elements.patch new file mode 100644 index 0000000..3000d7e --- /dev/null +++ b/fnmatch-collating-elements.patch @@ -0,0 +1,484 @@ +Fix fnmatch handling of collating elements (BZ #17396, BZ #16976) + + [BZ #16976] + [BZ #17396] + * posix/fnmatch_loop.c (internal_fnmatch, internal_fnwmatch): When + looking up collating elements match against (wide) character + sequence instead of name. Correct alignment adjustment. + * posix/fnmatch.c: Don't include "../locale/elem-hash.h". + * posix/Makefile (tests): Add tst-fnmatch4 and tst-fnmatch5. + * posix/tst-fnmatch4.c: New file. + * posix/tst-fnmatch5.c: New file. + + * Makefile (LOCALES): Add es_US.UTF-8 and es_US.ISO-8859-1. + +Index: glibc-2.22/localedata/Makefile +=================================================================== +--- glibc-2.22.orig/localedata/Makefile ++++ glibc-2.22/localedata/Makefile +@@ -106,7 +106,7 @@ LOCALES := de_DE.ISO-8859-1 de_DE.UTF-8 + hr_HR.ISO-8859-2 sv_SE.ISO-8859-1 ja_JP.SJIS fr_FR.ISO-8859-1 \ + nb_NO.ISO-8859-1 nn_NO.ISO-8859-1 tr_TR.UTF-8 cs_CZ.UTF-8 \ + zh_TW.EUC-TW fa_IR.UTF-8 fr_FR.UTF-8 ja_JP.UTF-8 si_LK.UTF-8 \ +- tr_TR.ISO-8859-9 en_GB.UTF-8 uk_UA.UTF-8 ++ tr_TR.ISO-8859-9 en_GB.UTF-8 uk_UA.UTF-8 es_US.UTF-8 es_US.ISO-8859-1 + include ../gen-locales.mk + endif + +Index: glibc-2.22/posix/Makefile +=================================================================== +--- glibc-2.22.orig/posix/Makefile ++++ glibc-2.22/posix/Makefile +@@ -87,7 +87,8 @@ tests := tstgetopt testfnm runtests run + bug-getopt1 bug-getopt2 bug-getopt3 bug-getopt4 \ + bug-getopt5 tst-getopt_long1 bug-regex34 bug-regex35 \ + tst-pathconf tst-getaddrinfo4 tst-rxspencer-no-utf8 \ +- tst-fnmatch3 bug-regex36 tst-getaddrinfo5 ++ tst-fnmatch3 bug-regex36 tst-fnmatch4 tst-fnmatch5 \ ++ tst-getaddrinfo5 + xtests := bug-ga2 + ifeq (yes,$(build-shared)) + test-srcs := globtest +Index: glibc-2.22/posix/fnmatch.c +=================================================================== +--- glibc-2.22.orig/posix/fnmatch.c ++++ glibc-2.22/posix/fnmatch.c +@@ -53,7 +53,6 @@ + we support a correct implementation only in glibc. */ + #ifdef _LIBC + # include "../locale/localeinfo.h" +-# include "../locale/elem-hash.h" + # include "../locale/coll-lookup.h" + # include + +Index: glibc-2.22/posix/fnmatch_loop.c +=================================================================== +--- glibc-2.22.orig/posix/fnmatch_loop.c ++++ glibc-2.22/posix/fnmatch_loop.c +@@ -503,26 +503,12 @@ FCT (pattern, string, string_end, no_lea + { + int32_t table_size; + const int32_t *symb_table; +-# if WIDE_CHAR_VERSION +- char str[c1]; +- unsigned int strcnt; +-# else +-# define str (startp + 1) +-# endif + const unsigned char *extra; + int32_t idx; + int32_t elem; +- int32_t second; +- int32_t hash; +- + # if WIDE_CHAR_VERSION +- /* We have to convert the name to a single-byte +- string. This is possible since the names +- consist of ASCII characters and the internal +- representation is UCS4. */ +- for (strcnt = 0; strcnt < c1; ++strcnt) +- str[strcnt] = startp[1 + strcnt]; +-#endif ++ int32_t *wextra; ++# endif + + table_size = + _NL_CURRENT_WORD (LC_COLLATE, +@@ -534,71 +520,55 @@ FCT (pattern, string, string_end, no_lea + _NL_CURRENT (LC_COLLATE, + _NL_COLLATE_SYMB_EXTRAMB); + +- /* Locate the character in the hashing table. */ +- hash = elem_hash (str, c1); +- +- idx = 0; +- elem = hash % table_size; +- if (symb_table[2 * elem] != 0) +- { +- second = hash % (table_size - 2) + 1; +- +- do +- { +- /* First compare the hashing value. */ +- if (symb_table[2 * elem] == hash +- && (c1 +- == extra[symb_table[2 * elem + 1]]) +- && memcmp (str, +- &extra[symb_table[2 * elem +- + 1] +- + 1], c1) == 0) +- { +- /* Yep, this is the entry. */ +- idx = symb_table[2 * elem + 1]; +- idx += 1 + extra[idx]; +- break; +- } +- +- /* Next entry. */ +- elem += second; +- } +- while (symb_table[2 * elem] != 0); +- } ++ for (elem = 0; elem < table_size; elem++) ++ if (symb_table[2 * elem] != 0) ++ { ++ idx = symb_table[2 * elem + 1]; ++ /* Skip the name of collating element. */ ++ idx += 1 + extra[idx]; ++# if WIDE_CHAR_VERSION ++ /* Skip the byte sequence of the ++ collating element. */ ++ idx += 1 + extra[idx]; ++ /* Adjust for the alignment. */ ++ idx = (idx + 3) & ~3; ++ ++ wextra = (int32_t *) &extra[idx + 4]; ++ ++ if (/* Compare the length of the sequence. */ ++ c1 == wextra[0] ++ /* Compare the wide char sequence. */ ++ && memcmp (startp + 1, &wextra[1], ++ c1 * sizeof (UCHAR)) == 0) ++ /* Yep, this is the entry. */ ++ break; ++# else ++ if (/* Compare the length of the sequence. */ ++ c1 == extra[idx] ++ /* Compare the byte sequence. */ ++ && memcmp (startp + 1, ++ &extra[idx + 1], c1) == 0) ++ /* Yep, this is the entry. */ ++ break; ++# endif ++ } + +- if (symb_table[2 * elem] != 0) ++ if (elem < table_size) + { + /* Compare the byte sequence but only if + this is not part of a range. */ +-# if WIDE_CHAR_VERSION +- int32_t *wextra; ++ if (! is_range + +- idx += 1 + extra[idx]; +- /* Adjust for the alignment. */ +- idx = (idx + 3) & ~3; +- +- wextra = (int32_t *) &extra[idx + 4]; +-# endif +- +- if (! is_range) +- { + # if WIDE_CHAR_VERSION +- for (c1 = 0; +- (int32_t) c1 < wextra[idx]; +- ++c1) +- if (n[c1] != wextra[1 + c1]) +- break; +- +- if ((int32_t) c1 == wextra[idx]) +- goto matched; ++ && memcmp (n, &wextra[1], ++ c1 * sizeof (UCHAR)) == 0 + # else +- for (c1 = 0; c1 < extra[idx]; ++c1) +- if (n[c1] != extra[1 + c1]) +- break; +- +- if (c1 == extra[idx]) +- goto matched; ++ && memcmp (n, &extra[idx + 1], c1) == 0 + # endif ++ ) ++ { ++ n += c1 - 1; ++ goto matched; + } + + /* Get the collation sequence value. */ +@@ -606,9 +576,9 @@ FCT (pattern, string, string_end, no_lea + # if WIDE_CHAR_VERSION + cold = wextra[1 + wextra[idx]]; + # else +- /* Adjust for the alignment. */ + idx += 1 + extra[idx]; +- idx = (idx + 3) & ~4; ++ /* Adjust for the alignment. */ ++ idx = (idx + 3) & ~3; + cold = *((int32_t *) &extra[idx]); + # endif + +@@ -618,10 +588,10 @@ FCT (pattern, string, string_end, no_lea + { + /* No valid character. Match it as a + single byte. */ +- if (!is_range && *n == str[0]) ++ if (!is_range && *n == startp[1]) + goto matched; + +- cold = str[0]; ++ cold = startp[1]; + c = *p++; + } + else +@@ -629,7 +599,6 @@ FCT (pattern, string, string_end, no_lea + } + } + else +-# undef str + #endif + { + c = FOLD (c); +@@ -721,25 +690,11 @@ FCT (pattern, string, string_end, no_lea + { + int32_t table_size; + const int32_t *symb_table; +-# if WIDE_CHAR_VERSION +- char str[c1]; +- unsigned int strcnt; +-# else +-# define str (startp + 1) +-# endif + const unsigned char *extra; + int32_t idx; + int32_t elem; +- int32_t second; +- int32_t hash; +- + # if WIDE_CHAR_VERSION +- /* We have to convert the name to a single-byte +- string. This is possible since the names +- consist of ASCII characters and the internal +- representation is UCS4. */ +- for (strcnt = 0; strcnt < c1; ++strcnt) +- str[strcnt] = startp[1 + strcnt]; ++ int32_t *wextra; + # endif + + table_size = +@@ -752,51 +707,44 @@ FCT (pattern, string, string_end, no_lea + _NL_CURRENT (LC_COLLATE, + _NL_COLLATE_SYMB_EXTRAMB); + +- /* Locate the character in the hashing +- table. */ +- hash = elem_hash (str, c1); +- +- idx = 0; +- elem = hash % table_size; +- if (symb_table[2 * elem] != 0) +- { +- second = hash % (table_size - 2) + 1; +- +- do +- { +- /* First compare the hashing value. */ +- if (symb_table[2 * elem] == hash +- && (c1 +- == extra[symb_table[2 * elem + 1]]) +- && memcmp (str, +- &extra[symb_table[2 * elem + 1] +- + 1], c1) == 0) +- { +- /* Yep, this is the entry. */ +- idx = symb_table[2 * elem + 1]; +- idx += 1 + extra[idx]; +- break; +- } +- +- /* Next entry. */ +- elem += second; +- } +- while (symb_table[2 * elem] != 0); +- } +- +- if (symb_table[2 * elem] != 0) +- { +- /* Compare the byte sequence but only if +- this is not part of a range. */ ++ for (elem = 0; elem < table_size; elem++) ++ if (symb_table[2 * elem] != 0) ++ { ++ idx = symb_table[2 * elem + 1]; ++ /* Skip the name of collating ++ element. */ ++ idx += 1 + extra[idx]; + # if WIDE_CHAR_VERSION +- int32_t *wextra; +- +- idx += 1 + extra[idx]; +- /* Adjust for the alignment. */ +- idx = (idx + 3) & ~4; +- +- wextra = (int32_t *) &extra[idx + 4]; ++ /* Skip the byte sequence of the ++ collating element. */ ++ idx += 1 + extra[idx]; ++ /* Adjust for the alignment. */ ++ idx = (idx + 3) & ~3; ++ ++ wextra = (int32_t *) &extra[idx + 4]; ++ ++ if (/* Compare the length of the ++ sequence. */ ++ c1 == wextra[0] ++ /* Compare the wide char sequence. */ ++ && memcmp (startp + 1, &wextra[1], ++ c1 * sizeof (int32_t)) == 0) ++ /* Yep, this is the entry. */ ++ break; ++# else ++ if (/* Compare the length of the ++ sequence. */ ++ c1 == extra[idx] ++ /* Compare the byte sequence. */ ++ && memcmp (startp + 1, ++ &extra[idx + 1], c1) == 0) ++ /* Yep, this is the entry. */ ++ break; + # endif ++ } ++ ++ if (elem < table_size) ++ { + /* Get the collation sequence value. */ + is_seqval = 1; + # if WIDE_CHAR_VERSION +@@ -804,19 +752,18 @@ FCT (pattern, string, string_end, no_lea + # else + /* Adjust for the alignment. */ + idx += 1 + extra[idx]; +- idx = (idx + 3) & ~4; ++ idx = (idx + 3) & ~3; + cend = *((int32_t *) &extra[idx]); + # endif + } +- else if (symb_table[2 * elem] != 0 && c1 == 1) ++ else if (c1 == 1) + { +- cend = str[0]; ++ cend = startp[1]; + c = *p++; + } + else + return FNM_NOMATCH; + } +-# undef str + } + else + { +Index: glibc-2.22/posix/tst-fnmatch4.c +=================================================================== +--- /dev/null ++++ glibc-2.22/posix/tst-fnmatch4.c +@@ -0,0 +1,51 @@ ++/* Test for fnmatch handling of collating elements ++ Copyright (C) 2015 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++#include ++ ++static int ++do_test_locale (const char *locale) ++{ ++ const char *pattern = "[[.ll.]]"; ++ ++ if (setlocale (LC_ALL, locale) == NULL) ++ { ++ printf ("could not set locale %s\n", locale); ++ return 1; ++ } ++ ++ if (fnmatch (pattern, "ll", 0) != 0) ++ { ++ printf ("%s didn't match in locale %s\n", pattern, locale); ++ return 1; ++ } ++ ++ return 0; ++} ++ ++static int ++do_test (void) ++{ ++ return (do_test_locale ("es_US.ISO-8859-1") ++ || do_test_locale ("es_US.UTF-8")); ++} ++ ++#define TEST_FUNCTION do_test () ++#include "../test-skeleton.c" +Index: glibc-2.22/posix/tst-fnmatch5.c +=================================================================== +--- /dev/null ++++ glibc-2.22/posix/tst-fnmatch5.c +@@ -0,0 +1,53 @@ ++/* Test for fnmatch handling of collating elements ++ Copyright (C) 2015 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++#include ++#include ++ ++#define LENGTH 20000000 ++ ++char pattern[LENGTH + 7]; ++ ++static int ++do_test (void) ++{ ++ if (setlocale (LC_ALL, "en_US.UTF-8") == NULL) ++ { ++ puts ("could not set locale"); ++ return 1; ++ } ++ pattern[0] = '['; ++ pattern[1] = '['; ++ pattern[2] = '.'; ++ memset (pattern + 3, 'a', LENGTH); ++ pattern[LENGTH + 3] = '.'; ++ pattern[LENGTH + 4] = ']'; ++ pattern[LENGTH + 5] = ']'; ++ int ret = fnmatch (pattern, "a", 0); ++ if (ret == 0) ++ { ++ puts ("fnmatch returned 0 for invalid pattern"); ++ return 1; ++ } ++ return 0; ++} ++ ++#define TEST_FUNCTION do_test () ++#include "../test-skeleton.c" diff --git a/glibc-testsuite.changes b/glibc-testsuite.changes index 6b4d233..dbdb2f6 100644 --- a/glibc-testsuite.changes +++ b/glibc-testsuite.changes @@ -1,3 +1,9 @@ +------------------------------------------------------------------- +Wed Sep 16 10:21:43 UTC 2015 - schwab@suse.de + +- fnmatch-collating-elements.patch: Fix fnmatch handling of collating + elements (BZ #17396, BZ #16976) + ------------------------------------------------------------------- Mon Sep 7 13:27:58 UTC 2015 - schwab@suse.de diff --git a/glibc-testsuite.spec b/glibc-testsuite.spec index 68a89ba..2226f2e 100644 --- a/glibc-testsuite.spec +++ b/glibc-testsuite.spec @@ -254,6 +254,8 @@ Patch2005: glibc-memset-nontemporal.diff Patch2006: ibm93x-redundant-shift-si.patch # PATCH-FIX-UPSTREAM Static dlopen default library search path fix (BZ #17250) Patch2007: static-dlopen.patch +# PATCH-FIX-UPSTREAM Fix fnmatch handling of collating elements (BZ #17396, BZ #16976) +Patch2008: fnmatch-collating-elements.patch # Non-glibc patches # PATCH-FIX-OPENSUSE Remove debianisms from manpages @@ -464,6 +466,7 @@ rm nscd/s-stamp %patch2005 -p1 %patch2006 -p1 %patch2007 -p1 +%patch2008 -p1 %patch3000 diff --git a/glibc-utils.changes b/glibc-utils.changes index 6b4d233..dbdb2f6 100644 --- a/glibc-utils.changes +++ b/glibc-utils.changes @@ -1,3 +1,9 @@ +------------------------------------------------------------------- +Wed Sep 16 10:21:43 UTC 2015 - schwab@suse.de + +- fnmatch-collating-elements.patch: Fix fnmatch handling of collating + elements (BZ #17396, BZ #16976) + ------------------------------------------------------------------- Mon Sep 7 13:27:58 UTC 2015 - schwab@suse.de diff --git a/glibc-utils.spec b/glibc-utils.spec index b89b3a2..a158a06 100644 --- a/glibc-utils.spec +++ b/glibc-utils.spec @@ -253,6 +253,8 @@ Patch2005: glibc-memset-nontemporal.diff Patch2006: ibm93x-redundant-shift-si.patch # PATCH-FIX-UPSTREAM Static dlopen default library search path fix (BZ #17250) Patch2007: static-dlopen.patch +# PATCH-FIX-UPSTREAM Fix fnmatch handling of collating elements (BZ #17396, BZ #16976) +Patch2008: fnmatch-collating-elements.patch # Non-glibc patches # PATCH-FIX-OPENSUSE Remove debianisms from manpages @@ -464,6 +466,7 @@ rm nscd/s-stamp %patch2005 -p1 %patch2006 -p1 %patch2007 -p1 +%patch2008 -p1 %patch3000 diff --git a/glibc.changes b/glibc.changes index 6b4d233..dbdb2f6 100644 --- a/glibc.changes +++ b/glibc.changes @@ -1,3 +1,9 @@ +------------------------------------------------------------------- +Wed Sep 16 10:21:43 UTC 2015 - schwab@suse.de + +- fnmatch-collating-elements.patch: Fix fnmatch handling of collating + elements (BZ #17396, BZ #16976) + ------------------------------------------------------------------- Mon Sep 7 13:27:58 UTC 2015 - schwab@suse.de diff --git a/glibc.spec b/glibc.spec index e544dbb..9db3c18 100644 --- a/glibc.spec +++ b/glibc.spec @@ -254,6 +254,8 @@ Patch2005: glibc-memset-nontemporal.diff Patch2006: ibm93x-redundant-shift-si.patch # PATCH-FIX-UPSTREAM Static dlopen default library search path fix (BZ #17250) Patch2007: static-dlopen.patch +# PATCH-FIX-UPSTREAM Fix fnmatch handling of collating elements (BZ #17396, BZ #16976) +Patch2008: fnmatch-collating-elements.patch # Non-glibc patches # PATCH-FIX-OPENSUSE Remove debianisms from manpages @@ -464,6 +466,7 @@ rm nscd/s-stamp %patch2005 -p1 %patch2006 -p1 %patch2007 -p1 +%patch2008 -p1 %patch3000