From 35b7508499170e8a9e9466499e4ccb82e51e353b Mon Sep 17 00:00:00 2001 From: Siddhesh Poyarekar Date: Thu, 5 Sep 2013 17:37:40 +0530 Subject: [PATCH] Resync with upstream master --- glibc-rh1000924.patch | 24 - glibc-rh800224.patch | 78 ---- glibc-rh985342.patch | 23 - glibc-rh995841.patch | 302 ------------- glibc-strcoll-cve.patch | 942 +++++++++------------------------------- glibc.spec | 26 +- sources | 2 +- 7 files changed, 207 insertions(+), 1190 deletions(-) delete mode 100644 glibc-rh1000924.patch delete mode 100644 glibc-rh800224.patch delete mode 100644 glibc-rh985342.patch delete mode 100644 glibc-rh995841.patch diff --git a/glibc-rh1000924.patch b/glibc-rh1000924.patch deleted file mode 100644 index 6010624..0000000 --- a/glibc-rh1000924.patch +++ /dev/null @@ -1,24 +0,0 @@ -diff -pruN glibc-2.18/nscd/aicache.c glibc-2.18.new/nscd/aicache.c ---- glibc-2.18/nscd/aicache.c 2013-08-11 04:22:55.000000000 +0530 -+++ glibc-2.18.new/nscd/aicache.c 2013-08-26 11:10:25.843470413 +0530 -@@ -25,6 +25,7 @@ - #include - #include - #include -+#include - - #include "dbg_log.h" - #include "nscd.h" -@@ -100,8 +101,11 @@ addhstaiX (struct database_dyn *db, int - no_more = __nss_database_lookup ("hosts", NULL, - "dns [!UNAVAIL=return] files", &nip); - -+ /* Initialize configurations. */ -+ if (__builtin_expect (!_res_hconf.initialized, 0)) -+ _res_hconf_init (); - if (__res_maybe_init (&_res, 0) == -1) -- no_more = 1; -+ no_more = 1; - - /* If we are looking for both IPv4 and IPv6 address we don't want - the lookup functions to automatically promote IPv4 addresses to diff --git a/glibc-rh800224.patch b/glibc-rh800224.patch deleted file mode 100644 index ce8234c..0000000 --- a/glibc-rh800224.patch +++ /dev/null @@ -1,78 +0,0 @@ - -2012-03-07 Jeff Law - - * elf/dl-reloc.c (_dl_relocate_object): Move code to allocate - l_reloc_result prior to calling ELF_DYNAMIC_RELOCATE. - -diff -rup a/elf/dl-reloc.c b/elf/dl-reloc.c ---- a/elf/dl-reloc.c 2012-01-01 05:16:32.000000000 -0700 -+++ b/elf/dl-reloc.c 2012-03-06 15:41:56.486242640 -0700 -@@ -238,32 +238,9 @@ _dl_relocate_object (struct link_map *l, - /* String table object symbols. */ - const char *strtab = (const void *) D_PTR (l, l_info[DT_STRTAB]); - -- /* This macro is used as a callback from the ELF_DYNAMIC_RELOCATE code. */ --#define RESOLVE_MAP(ref, version, r_type) \ -- (ELFW(ST_BIND) ((*ref)->st_info) != STB_LOCAL \ -- ? ((__builtin_expect ((*ref) == l->l_lookup_cache.sym, 0) \ -- && elf_machine_type_class (r_type) == l->l_lookup_cache.type_class) \ -- ? (bump_num_cache_relocations (), \ -- (*ref) = l->l_lookup_cache.ret, \ -- l->l_lookup_cache.value) \ -- : ({ lookup_t _lr; \ -- int _tc = elf_machine_type_class (r_type); \ -- l->l_lookup_cache.type_class = _tc; \ -- l->l_lookup_cache.sym = (*ref); \ -- const struct r_found_version *v = NULL; \ -- if ((version) != NULL && (version)->hash != 0) \ -- v = (version); \ -- _lr = _dl_lookup_symbol_x (strtab + (*ref)->st_name, l, (ref), \ -- scope, v, _tc, \ -- DL_LOOKUP_ADD_DEPENDENCY, NULL); \ -- l->l_lookup_cache.ret = (*ref); \ -- l->l_lookup_cache.value = _lr; })) \ -- : l) -- --#include "dynamic-link.h" -- -- ELF_DYNAMIC_RELOCATE (l, lazy, consider_profiling, skip_ifunc); -- -+ /* ELF_DYNAMIC_RELOCATE may need to examine l_reloc_result -+ when handling MACHINE_IRELATIVE relocs. So we must -+ allocate l_reloc_result prior to calling ELF_DYNAMIC_RELOCATE. */ - #ifndef PROF - if (__builtin_expect (consider_profiling, 0)) - { -@@ -290,6 +267,32 @@ _dl_relocate_object (struct link_map *l, - } - } - #endif -+ -+ /* This macro is used as a callback from the ELF_DYNAMIC_RELOCATE code. */ -+#define RESOLVE_MAP(ref, version, r_type) \ -+ (ELFW(ST_BIND) ((*ref)->st_info) != STB_LOCAL \ -+ ? ((__builtin_expect ((*ref) == l->l_lookup_cache.sym, 0) \ -+ && elf_machine_type_class (r_type) == l->l_lookup_cache.type_class) \ -+ ? (bump_num_cache_relocations (), \ -+ (*ref) = l->l_lookup_cache.ret, \ -+ l->l_lookup_cache.value) \ -+ : ({ lookup_t _lr; \ -+ int _tc = elf_machine_type_class (r_type); \ -+ l->l_lookup_cache.type_class = _tc; \ -+ l->l_lookup_cache.sym = (*ref); \ -+ const struct r_found_version *v = NULL; \ -+ if ((version) != NULL && (version)->hash != 0) \ -+ v = (version); \ -+ _lr = _dl_lookup_symbol_x (strtab + (*ref)->st_name, l, (ref), \ -+ scope, v, _tc, \ -+ DL_LOOKUP_ADD_DEPENDENCY, NULL); \ -+ l->l_lookup_cache.ret = (*ref); \ -+ l->l_lookup_cache.value = _lr; })) \ -+ : l) -+ -+#include "dynamic-link.h" -+ -+ ELF_DYNAMIC_RELOCATE (l, lazy, consider_profiling, skip_ifunc); - } - - /* Mark the object so we know this work has been done. */ diff --git a/glibc-rh985342.patch b/glibc-rh985342.patch deleted file mode 100644 index ce2463b..0000000 --- a/glibc-rh985342.patch +++ /dev/null @@ -1,23 +0,0 @@ -# -# Posted upstream: -# http://sourceware.org/ml/libc-ports/2013-08/msg00053.html -# -# 2013-08-28 Kyle McMartin -# Carlos O'Donell -# -# * sysdeps/arm/dl-machine [!RTLD_BOOTSTRAP] (elf_machine_rel): -# Pass GLRO(dl_hwcap) to the IFUNC resolver. -# -diff --git a/ports/sysdeps/arm/dl-machine.h b/ports/sysdeps/arm/dl-machine.h -index d251527..85dba67 100644 ---- a/ports/sysdeps/arm/dl-machine.h -+++ b/ports/sysdeps/arm/dl-machine.h -@@ -503,7 +503,7 @@ elf_machine_rel (struct link_map *map, const Elf32_Rel *reloc, - break; - case R_ARM_IRELATIVE: - value = map->l_addr + *reloc_addr; -- value = ((Elf32_Addr (*) (void)) value) (); -+ value = ((Elf32_Addr (*) (int)) value) (GLRO(dl_hwcap)); - *reloc_addr = value; - break; - #endif diff --git a/glibc-rh995841.patch b/glibc-rh995841.patch deleted file mode 100644 index f745cb0..0000000 --- a/glibc-rh995841.patch +++ /dev/null @@ -1,302 +0,0 @@ -commit 91ce40854d0b7f865cf5024ef95a8026b76096f3 -Author: Florian Weimer -Date: Fri Aug 16 09:38:52 2013 +0200 - - CVE-2013-4237, BZ #14699: Buffer overflow in readdir_r - - * sysdeps/posix/dirstream.h (struct __dirstream): Add errcode - member. - * sysdeps/posix/opendir.c (__alloc_dir): Initialize errcode - member. - * sysdeps/posix/rewinddir.c (rewinddir): Reset errcode member. - * sysdeps/posix/readdir_r.c (__READDIR_R): Enforce NAME_MAX limit. - Return delayed error code. Remove GETDENTS_64BIT_ALIGNED - conditional. - * sysdeps/unix/sysv/linux/wordsize-64/readdir_r.c: Do not define - GETDENTS_64BIT_ALIGNED. - * sysdeps/unix/sysv/linux/i386/readdir64_r.c: Likewise. - * manual/filesys.texi (Reading/Closing Directory): Document - ENAMETOOLONG return value of readdir_r. Recommend readdir more - strongly. - * manual/conf.texi (Limits for Files): Add portability note to - NAME_MAX, PATH_MAX. - (Pathconf): Add portability note for _PC_NAME_MAX, _PC_PATH_MAX. - -diff --git a/manual/conf.texi b/manual/conf.texi -index 7eb8b36..c720063 100644 ---- a/manual/conf.texi -+++ b/manual/conf.texi -@@ -1149,6 +1149,9 @@ typed ahead as input. @xref{I/O Queues}. - @deftypevr Macro int NAME_MAX - The uniform system limit (if any) for the length of a file name component, not - including the terminating null character. -+ -+@strong{Portability Note:} On some systems, @theglibc{} defines -+@code{NAME_MAX}, but does not actually enforce this limit. - @end deftypevr - - @comment limits.h -@@ -1157,6 +1160,9 @@ including the terminating null character. - The uniform system limit (if any) for the length of an entire file name (that - is, the argument given to system calls such as @code{open}), including the - terminating null character. -+ -+@strong{Portability Note:} @Theglibc{} does not enforce this limit -+even if @code{PATH_MAX} is defined. - @end deftypevr - - @cindex limits, pipe buffer size -@@ -1476,6 +1482,9 @@ Inquire about the value of @code{POSIX_REC_MIN_XFER_SIZE}. - Inquire about the value of @code{POSIX_REC_XFER_ALIGN}. - @end table - -+@strong{Portability Note:} On some systems, @theglibc{} does not -+enforce @code{_PC_NAME_MAX} or @code{_PC_PATH_MAX} limits. -+ - @node Utility Limits - @section Utility Program Capacity Limits - -diff --git a/manual/filesys.texi b/manual/filesys.texi -index 1df9cf2..814c210 100644 ---- a/manual/filesys.texi -+++ b/manual/filesys.texi -@@ -444,9 +444,9 @@ symbols are declared in the header file @file{dirent.h}. - @comment POSIX.1 - @deftypefun {struct dirent *} readdir (DIR *@var{dirstream}) - This function reads the next entry from the directory. It normally --returns a pointer to a structure containing information about the file. --This structure is statically allocated and can be rewritten by a --subsequent call. -+returns a pointer to a structure containing information about the -+file. This structure is associated with the @var{dirstream} handle -+and can be rewritten by a subsequent call. - - @strong{Portability Note:} On some systems @code{readdir} may not - return entries for @file{.} and @file{..}, even though these are always -@@ -461,19 +461,61 @@ conditions are defined for this function: - The @var{dirstream} argument is not valid. - @end table - --@code{readdir} is not thread safe. Multiple threads using --@code{readdir} on the same @var{dirstream} may overwrite the return --value. Use @code{readdir_r} when this is critical. -+To distinguish between an end-of-directory condition or an error, you -+must set @code{errno} to zero before calling @code{readdir}. To avoid -+entering an infinite loop, you should stop reading from the directory -+after the first error. -+ -+In POSIX.1-2008, @code{readdir} is not thread-safe. In @theglibc{} -+implementation, it is safe to call @code{readdir} concurrently on -+different @var{dirstream}s, but multiple threads accessing the same -+@var{dirstream} result in undefined behavior. @code{readdir_r} is a -+fully thread-safe alternative, but suffers from poor portability (see -+below). It is recommended that you use @code{readdir}, with external -+locking if multiple threads access the same @var{dirstream}. - @end deftypefun - - @comment dirent.h - @comment GNU - @deftypefun int readdir_r (DIR *@var{dirstream}, struct dirent *@var{entry}, struct dirent **@var{result}) --This function is the reentrant version of @code{readdir}. Like --@code{readdir} it returns the next entry from the directory. But to --prevent conflicts between simultaneously running threads the result is --not stored in statically allocated memory. Instead the argument --@var{entry} points to a place to store the result. -+This function is a version of @code{readdir} which performs internal -+locking. Like @code{readdir} it returns the next entry from the -+directory. To prevent conflicts between simultaneously running -+threads the result is stored inside the @var{entry} object. -+ -+@strong{Portability Note:} It is recommended to use @code{readdir} -+instead of @code{readdir_r} for the following reasons: -+ -+@itemize @bullet -+@item -+On systems which do not define @code{NAME_MAX}, it may not be possible -+to use @code{readdir_r} safely because the caller does not specify the -+length of the buffer for the directory entry. -+ -+@item -+On some systems, @code{readdir_r} cannot read directory entries with -+very long names. If such a name is encountered, @theglibc{} -+implementation of @code{readdir_r} returns with an error code of -+@code{ENAMETOOLONG} after the final directory entry has been read. On -+other systems, @code{readdir_r} may return successfully, but the -+@code{d_name} member may not be NUL-terminated or may be truncated. -+ -+@item -+POSIX-1.2008 does not guarantee that @code{readdir} is thread-safe, -+even when access to the same @var{dirstream} is serialized. But in -+current implementations (including @theglibc{}), it is safe to call -+@code{readdir} concurrently on different @var{dirstream}s, so there is -+no need to use @code{readdir_r} in most multi-threaded programs. In -+the rare case that multiple threads need to read from the same -+@var{dirstream}, it is still better to use @code{readdir} and external -+synchronization. -+ -+@item -+It is expected that future versions of POSIX will obsolete -+@code{readdir_r} and mandate the level of thread safety for -+@code{readdir} which is provided by @theglibc{} and other -+implementations today. -+@end itemize - - Normally @code{readdir_r} returns zero and sets @code{*@var{result}} - to @var{entry}. If there are no more entries in the directory or an -@@ -481,15 +523,6 @@ error is detected, @code{readdir_r} sets @code{*@var{result}} to a - null pointer and returns a nonzero error code, also stored in - @code{errno}, as described for @code{readdir}. - --@strong{Portability Note:} On some systems @code{readdir_r} may not --return a NUL terminated string for the file name, even when there is no --@code{d_reclen} field in @code{struct dirent} and the file --name is the maximum allowed size. Modern systems all have the --@code{d_reclen} field, and on old systems multi-threading is not --critical. In any case there is no such problem with the @code{readdir} --function, so that even on systems without the @code{d_reclen} member one --could use multiple threads by using external locking. -- - It is also important to look at the definition of the @code{struct - dirent} type. Simply passing a pointer to an object of this type for - the second parameter of @code{readdir_r} might not be enough. Some -diff --git a/sysdeps/posix/dirstream.h b/sysdeps/posix/dirstream.h -index a7a074d..8e8570d 100644 ---- a/sysdeps/posix/dirstream.h -+++ b/sysdeps/posix/dirstream.h -@@ -39,6 +39,8 @@ struct __dirstream - - off_t filepos; /* Position of next entry to read. */ - -+ int errcode; /* Delayed error code. */ -+ - /* Directory block. */ - char data[0] __attribute__ ((aligned (__alignof__ (void*)))); - }; -diff --git a/sysdeps/posix/opendir.c b/sysdeps/posix/opendir.c -index ddfc3a7..fc05b0f 100644 ---- a/sysdeps/posix/opendir.c -+++ b/sysdeps/posix/opendir.c -@@ -231,6 +231,7 @@ __alloc_dir (int fd, bool close_fd, int flags, const struct stat64 *statp) - dirp->size = 0; - dirp->offset = 0; - dirp->filepos = 0; -+ dirp->errcode = 0; - - return dirp; - } -diff --git a/sysdeps/posix/readdir_r.c b/sysdeps/posix/readdir_r.c -index b5a8e2e..8ed5c3f 100644 ---- a/sysdeps/posix/readdir_r.c -+++ b/sysdeps/posix/readdir_r.c -@@ -40,6 +40,7 @@ __READDIR_R (DIR *dirp, DIRENT_TYPE *entry, DIRENT_TYPE **result) - DIRENT_TYPE *dp; - size_t reclen; - const int saved_errno = errno; -+ int ret; - - __libc_lock_lock (dirp->lock); - -@@ -70,10 +71,10 @@ __READDIR_R (DIR *dirp, DIRENT_TYPE *entry, DIRENT_TYPE **result) - bytes = 0; - __set_errno (saved_errno); - } -+ if (bytes < 0) -+ dirp->errcode = errno; - - dp = NULL; -- /* Reclen != 0 signals that an error occurred. */ -- reclen = bytes != 0; - break; - } - dirp->size = (size_t) bytes; -@@ -106,29 +107,46 @@ __READDIR_R (DIR *dirp, DIRENT_TYPE *entry, DIRENT_TYPE **result) - dirp->filepos += reclen; - #endif - -- /* Skip deleted files. */ -+#ifdef NAME_MAX -+ if (reclen > offsetof (DIRENT_TYPE, d_name) + NAME_MAX + 1) -+ { -+ /* The record is very long. It could still fit into the -+ caller-supplied buffer if we can skip padding at the -+ end. */ -+ size_t namelen = _D_EXACT_NAMLEN (dp); -+ if (namelen <= NAME_MAX) -+ reclen = offsetof (DIRENT_TYPE, d_name) + namelen + 1; -+ else -+ { -+ /* The name is too long. Ignore this file. */ -+ dirp->errcode = ENAMETOOLONG; -+ dp->d_ino = 0; -+ continue; -+ } -+ } -+#endif -+ -+ /* Skip deleted and ignored files. */ - } - while (dp->d_ino == 0); - - if (dp != NULL) - { --#ifdef GETDENTS_64BIT_ALIGNED -- /* The d_reclen value might include padding which is not part of -- the DIRENT_TYPE data structure. */ -- reclen = MIN (reclen, -- offsetof (DIRENT_TYPE, d_name) + sizeof (dp->d_name)); --#endif - *result = memcpy (entry, dp, reclen); --#ifdef GETDENTS_64BIT_ALIGNED -+#ifdef _DIRENT_HAVE_D_RECLEN - entry->d_reclen = reclen; - #endif -+ ret = 0; - } - else -- *result = NULL; -+ { -+ *result = NULL; -+ ret = dirp->errcode; -+ } - - __libc_lock_unlock (dirp->lock); - -- return dp != NULL ? 0 : reclen ? errno : 0; -+ return ret; - } - - #ifdef __READDIR_R_ALIAS -diff --git a/sysdeps/posix/rewinddir.c b/sysdeps/posix/rewinddir.c -index 2935a8e..d4991ad 100644 ---- a/sysdeps/posix/rewinddir.c -+++ b/sysdeps/posix/rewinddir.c -@@ -33,6 +33,7 @@ rewinddir (dirp) - dirp->filepos = 0; - dirp->offset = 0; - dirp->size = 0; -+ dirp->errcode = 0; - #ifndef NOT_IN_libc - __libc_lock_unlock (dirp->lock); - #endif -diff --git a/sysdeps/unix/sysv/linux/i386/readdir64_r.c b/sysdeps/unix/sysv/linux/i386/readdir64_r.c -index 8ebbcfd..a7d114e 100644 ---- a/sysdeps/unix/sysv/linux/i386/readdir64_r.c -+++ b/sysdeps/unix/sysv/linux/i386/readdir64_r.c -@@ -18,7 +18,6 @@ - #define __READDIR_R __readdir64_r - #define __GETDENTS __getdents64 - #define DIRENT_TYPE struct dirent64 --#define GETDENTS_64BIT_ALIGNED 1 - - #include - -diff --git a/sysdeps/unix/sysv/linux/wordsize-64/readdir_r.c b/sysdeps/unix/sysv/linux/wordsize-64/readdir_r.c -index 5ed8e95..290f2c8 100644 ---- a/sysdeps/unix/sysv/linux/wordsize-64/readdir_r.c -+++ b/sysdeps/unix/sysv/linux/wordsize-64/readdir_r.c -@@ -1,5 +1,4 @@ - #define readdir64_r __no_readdir64_r_decl --#define GETDENTS_64BIT_ALIGNED 1 - #include - #undef readdir64_r - weak_alias (__readdir_r, readdir64_r) diff --git a/glibc-strcoll-cve.patch b/glibc-strcoll-cve.patch index 5558c1f..7c220f4 100644 --- a/glibc-strcoll-cve.patch +++ b/glibc-strcoll-cve.patch @@ -1,203 +1,74 @@ +diff --git a/string/Makefile b/string/Makefile +index aaad743..f70dc7a 100644 +--- a/string/Makefile ++++ b/string/Makefile +@@ -57,6 +57,8 @@ tests := tester inl-tester noinl-tester testcopy test-ffs \ + tests-ifunc := $(strop-tests:%=test-%-ifunc) + tests += $(tests-ifunc) + ++xtests = tst-strcoll-overflow ++ + include ../Rules + + tester-ENV = LANGUAGE=C diff --git a/string/strcoll_l.c b/string/strcoll_l.c -index ecda08f..bb34a72 100644 +index 50ed84d..4ee101a 100644 --- a/string/strcoll_l.c +++ b/string/strcoll_l.c -@@ -41,11 +41,434 @@ - - #include "../locale/localeinfo.h" - -+/* Track status while looking for sequences in a string. */ -+typedef struct -+{ -+ int len; /* Length of the current sequence. */ +@@ -45,7 +45,7 @@ + typedef struct + { + int len; /* Length of the current sequence. */ +- int val; /* Position of the sequence relative to the + size_t val; /* Position of the sequence relative to the -+ previous non-ignored sequence. */ -+ size_t idxnow; /* Current index in sequences. */ -+ size_t idxmax; /* Maximum index in sequences. */ -+ size_t idxcnt; /* Current count of indices. */ -+ size_t backw; /* Current Backward sequence index. */ -+ size_t backw_stop; /* Index where the backward sequences stop. */ -+ const USTRING_TYPE *us; /* The string. */ -+ int32_t *idxarr; /* Array to cache weight indices. */ -+ unsigned char *rulearr; /* Array to cache rules. */ + previous non-ignored sequence. */ + size_t idxnow; /* Current index in sequences. */ + size_t idxmax; /* Maximum index in sequences. */ +@@ -55,6 +55,12 @@ typedef struct + const USTRING_TYPE *us; /* The string. */ + int32_t *idxarr; /* Array to cache weight indices. */ + unsigned char *rulearr; /* Array to cache rules. */ + unsigned char rule; /* Saved rule for the first sequence. */ + int32_t idx; /* Index to weight of the current sequence. */ + int32_t save_idx; /* Save looked up index of a forward + sequence after the last backward + sequence. */ + const USTRING_TYPE *back_us; /* Beginning of the backward sequence. */ -+} coll_seq; -+ -+/* Get next sequence. The weight indices are cached, so we don't need to -+ traverse the string. */ -+static void -+get_next_seq_cached (coll_seq *seq, int nrules, int pass, -+ const unsigned char *rulesets, -+ const USTRING_TYPE *weights) -+{ + } coll_seq; + + /* Get next sequence. The weight indices are cached, so we don't need to +@@ -64,7 +70,7 @@ get_next_seq_cached (coll_seq *seq, int nrules, int pass, + const unsigned char *rulesets, + const USTRING_TYPE *weights) + { +- int val = seq->val = 0; + size_t val = seq->val = 0; -+ int len = seq->len; -+ size_t backw_stop = seq->backw_stop; -+ size_t backw = seq->backw; -+ size_t idxcnt = seq->idxcnt; -+ size_t idxmax = seq->idxmax; -+ size_t idxnow = seq->idxnow; -+ unsigned char *rulearr = seq->rulearr; -+ int32_t *idxarr = seq->idxarr; -+ -+ while (len == 0) -+ { -+ ++val; -+ if (backw_stop != ~0ul) -+ { -+ /* There is something pushed. */ -+ if (backw == backw_stop) -+ { -+ /* The last pushed character was handled. Continue -+ with forward characters. */ -+ if (idxcnt < idxmax) -+ { -+ idxnow = idxcnt; -+ backw_stop = ~0ul; -+ } -+ else -+ { -+ /* Nothing any more. The backward sequence -+ ended with the last sequence in the string. */ -+ idxnow = ~0ul; -+ break; -+ } -+ } -+ else -+ idxnow = --backw; -+ } -+ else -+ { -+ backw_stop = idxcnt; -+ -+ while (idxcnt < idxmax) -+ { -+ if ((rulesets[rulearr[idxcnt] * nrules + pass] -+ & sort_backward) == 0) -+ /* No more backward characters to push. */ -+ break; -+ ++idxcnt; -+ } -+ -+ if (backw_stop == idxcnt) -+ { -+ /* No sequence at all or just one. */ -+ if (idxcnt == idxmax) -+ /* Note that LEN is still zero. */ -+ break; -+ -+ backw_stop = ~0ul; -+ idxnow = idxcnt++; -+ } -+ else -+ /* We pushed backward sequences. */ -+ idxnow = backw = idxcnt - 1; -+ } -+ len = weights[idxarr[idxnow]++]; -+ } -+ -+ /* Update the structure. */ -+ seq->val = val; -+ seq->len = len; -+ seq->backw_stop = backw_stop; -+ seq->backw = backw; -+ seq->idxcnt = idxcnt; -+ seq->idxnow = idxnow; -+} -+ -+/* Get next sequence. Traverse the string as required. */ -+static void -+get_next_seq (coll_seq *seq, int nrules, const unsigned char *rulesets, -+ const USTRING_TYPE *weights, const int32_t *table, -+ const USTRING_TYPE *extra, const int32_t *indirect) -+{ -+#include WEIGHT_H + int len = seq->len; + size_t backw_stop = seq->backw_stop; + size_t backw = seq->backw; +@@ -146,7 +152,7 @@ get_next_seq (coll_seq *seq, int nrules, const unsigned char *rulesets, + const USTRING_TYPE *extra, const int32_t *indirect) + { + #include WEIGHT_H +- int val = seq->val = 0; + size_t val = seq->val = 0; -+ int len = seq->len; -+ size_t backw_stop = seq->backw_stop; -+ size_t backw = seq->backw; -+ size_t idxcnt = seq->idxcnt; -+ size_t idxmax = seq->idxmax; -+ size_t idxnow = seq->idxnow; -+ unsigned char *rulearr = seq->rulearr; -+ int32_t *idxarr = seq->idxarr; -+ const USTRING_TYPE *us = seq->us; -+ -+ while (len == 0) -+ { -+ ++val; -+ if (backw_stop != ~0ul) -+ { + int len = seq->len; + size_t backw_stop = seq->backw_stop; + size_t backw = seq->backw; +@@ -162,7 +168,7 @@ get_next_seq (coll_seq *seq, int nrules, const unsigned char *rulesets, + ++val; + if (backw_stop != ~0ul) + { +- /* The is something pushed. */ + /* There is something pushed. */ -+ if (backw == backw_stop) -+ { -+ /* The last pushed character was handled. Continue -+ with forward characters. */ -+ if (idxcnt < idxmax) -+ { -+ idxnow = idxcnt; -+ backw_stop = ~0ul; -+ } -+ else -+ /* Nothing any more. The backward sequence ended with -+ the last sequence in the string. Note that LEN -+ is still zero. */ -+ break; -+ } -+ else -+ idxnow = --backw; -+ } -+ else -+ { -+ backw_stop = idxmax; -+ -+ while (*us != L('\0')) -+ { -+ int32_t tmp = findidx (&us, -1); -+ rulearr[idxmax] = tmp >> 24; -+ idxarr[idxmax] = tmp & 0xffffff; -+ idxcnt = idxmax++; -+ -+ if ((rulesets[rulearr[idxcnt] * nrules] -+ & sort_backward) == 0) -+ /* No more backward characters to push. */ -+ break; -+ ++idxcnt; -+ } -+ -+ if (backw_stop >= idxcnt) -+ { -+ /* No sequence at all or just one. */ -+ if (idxcnt == idxmax || backw_stop > idxcnt) -+ /* Note that LEN is still zero. */ -+ break; -+ -+ backw_stop = ~0ul; -+ idxnow = idxcnt; -+ } -+ else -+ /* We pushed backward sequences. */ -+ idxnow = backw = idxcnt - 1; -+ } -+ len = weights[idxarr[idxnow]++]; -+ } -+ -+ /* Update the structure. */ -+ seq->val = val; -+ seq->len = len; -+ seq->backw_stop = backw_stop; -+ seq->backw = backw; -+ seq->idxcnt = idxcnt; -+ seq->idxmax = idxmax; -+ seq->idxnow = idxnow; -+ seq->us = us; -+} -+ + if (backw == backw_stop) + { + /* The last pushed character was handled. Continue +@@ -227,15 +233,199 @@ get_next_seq (coll_seq *seq, int nrules, const unsigned char *rulesets, + seq->us = us; + } + +-/* Compare two sequences. */ +/* Get next sequence. Traverse the string as required. This function does not + set or use any index or rule cache. */ +static void @@ -383,396 +254,97 @@ index ecda08f..bb34a72 100644 +} + +/* Compare two sequences using the index cache. */ -+static int -+do_compare (coll_seq *seq1, coll_seq *seq2, int position, -+ const USTRING_TYPE *weights) -+{ -+ int seq1len = seq1->len; -+ int seq2len = seq2->len; + static int + do_compare (coll_seq *seq1, coll_seq *seq2, int position, + const USTRING_TYPE *weights) + { + int seq1len = seq1->len; + int seq2len = seq2->len; +- int val1 = seq1->val; +- int val2 = seq2->val; + size_t val1 = seq1->val; + size_t val2 = seq2->val; -+ int32_t *idx1arr = seq1->idxarr; -+ int32_t *idx2arr = seq2->idxarr; -+ int idx1now = seq1->idxnow; -+ int idx2now = seq2->idxnow; -+ int result = 0; -+ -+ /* Test for position if necessary. */ -+ if (position && val1 != val2) -+ { + int32_t *idx1arr = seq1->idxarr; + int32_t *idx2arr = seq2->idxarr; + int idx1now = seq1->idxnow; +@@ -245,7 +435,7 @@ do_compare (coll_seq *seq1, coll_seq *seq2, int position, + /* Test for position if necessary. */ + if (position && val1 != val2) + { +- result = val1 - val2; + result = val1 > val2 ? 1 : -1; -+ goto out; -+ } -+ -+ /* Compare the two sequences. */ -+ do -+ { -+ if (weights[idx1arr[idx1now]] != weights[idx2arr[idx2now]]) -+ { -+ /* The sequences differ. */ -+ result = weights[idx1arr[idx1now]] - weights[idx2arr[idx2now]]; -+ goto out; -+ } -+ -+ /* Increment the offsets. */ -+ ++idx1arr[idx1now]; -+ ++idx2arr[idx2now]; -+ -+ --seq1len; -+ --seq2len; -+ } -+ while (seq1len > 0 && seq2len > 0); -+ -+ if (position && seq1len != seq2len) -+ result = seq1len - seq2len; -+ -+out: -+ seq1->len = seq1len; -+ seq2->len = seq2len; -+ return result; -+} -+ - int --STRCOLL (s1, s2, l) -- const STRING_TYPE *s1; -- const STRING_TYPE *s2; -- __locale_t l; -+STRCOLL (const STRING_TYPE *s1, const STRING_TYPE *s2, __locale_t l) - { - struct __locale_data *current = l->__locales[LC_COLLATE]; - uint_fast32_t nrules = current->values[_NL_ITEM_INDEX (_NL_COLLATE_NRULES)].word; -@@ -56,34 +479,6 @@ STRCOLL (s1, s2, l) - const USTRING_TYPE *weights; - const USTRING_TYPE *extra; - const int32_t *indirect; -- uint_fast32_t pass; -- int result = 0; -- const USTRING_TYPE *us1; -- const USTRING_TYPE *us2; -- size_t s1len; -- size_t s2len; -- int32_t *idx1arr; -- int32_t *idx2arr; -- unsigned char *rule1arr; -- unsigned char *rule2arr; -- size_t idx1max; -- size_t idx2max; -- size_t idx1cnt; -- size_t idx2cnt; -- size_t idx1now; -- size_t idx2now; -- size_t backw1_stop; -- size_t backw2_stop; -- size_t backw1; -- size_t backw2; -- int val1; -- int val2; -- int position; -- int seq1len; -- int seq2len; -- int use_malloc; -- --#include WEIGHT_H + goto out; + } - if (nrules == 0) - return STRCMP (s1, s2); -@@ -98,7 +493,6 @@ STRCOLL (s1, s2, l) - current->values[_NL_ITEM_INDEX (CONCAT(_NL_COLLATE_EXTRA,SUFFIX))].string; - indirect = (const int32_t *) - current->values[_NL_ITEM_INDEX (CONCAT(_NL_COLLATE_INDIRECT,SUFFIX))].string; -- use_malloc = 0; - - assert (((uintptr_t) table) % __alignof__ (table[0]) == 0); - assert (((uintptr_t) weights) % __alignof__ (weights[0]) == 0); -@@ -106,18 +500,13 @@ STRCOLL (s1, s2, l) - assert (((uintptr_t) indirect) % __alignof__ (indirect[0]) == 0); - - /* We need this a few times. */ -- s1len = STRLEN (s1); -- s2len = STRLEN (s2); -+ size_t s1len = STRLEN (s1); -+ size_t s2len = STRLEN (s2); - - /* Catch empty strings. */ -- if (__builtin_expect (s1len == 0, 0) || __builtin_expect (s2len == 0, 0)) -+ if (__glibc_unlikely (s1len == 0) || __glibc_unlikely (s2len == 0)) - return (s1len != 0) - (s2len != 0); +@@ -334,57 +524,70 @@ STRCOLL (const STRING_TYPE *s1, const STRING_TYPE *s2, __locale_t l) + memset (&seq1, 0, sizeof (seq1)); + seq2 = seq1; - /* We need the elements of the strings as unsigned values since they -- are used as indeces. */ -- us1 = (const USTRING_TYPE *) s1; -- us2 = (const USTRING_TYPE *) s2; -- - /* Perform the first pass over the string and while doing this find - and store the weights for each character. Since we want this to - be as fast as possible we are using `alloca' to store the temporary -@@ -127,411 +516,124 @@ STRCOLL (s1, s2, l) +- are used as indices. */ +- seq1.us = (const USTRING_TYPE *) s1; +- seq2.us = (const USTRING_TYPE *) s2; ++ size_t size_max = SIZE_MAX / (sizeof (int32_t) + 1); - Please note that the localedef programs makes sure that `position' - is not used at the first level. */ - if (! __libc_use_alloca ((s1len + s2len) * (sizeof (int32_t) + 1))) -- { -- idx1arr = (int32_t *) malloc ((s1len + s2len) * (sizeof (int32_t) + 1)); -- idx2arr = &idx1arr[s1len]; -- rule1arr = (unsigned char *) &idx2arr[s2len]; -- rule2arr = &rule1arr[s1len]; ++ if (MIN (s1len, s2len) > size_max ++ || MAX (s1len, s2len) > size_max - MIN (s1len, s2len)) ++ { ++ /* If the strings are long enough to cause overflow in the size request, ++ then skip the allocation and proceed with the non-cached routines. */ ++ } ++ else if (! __libc_use_alloca ((s1len + s2len) * (sizeof (int32_t) + 1))) + { + seq1.idxarr = (int32_t *) malloc ((s1len + s2len) * (sizeof (int32_t) + 1)); +- seq2.idxarr = &seq1.idxarr[s1len]; +- seq1.rulearr = (unsigned char *) &seq2.idxarr[s2len]; +- seq2.rulearr = &seq1.rulearr[s1len]; - -- if (idx1arr == NULL) +- if (seq1.idxarr == NULL) - /* No memory. Well, go with the stack then. - - XXX Once this implementation is stable we will handle this -- differently. Instead of precomputing the indeces we will +- differently. Instead of precomputing the indices we will - do this in time. This means, though, that this happens for - every pass again. */ - goto try_stack; -- use_malloc = 1; -- } -- else -- { -- try_stack: -- idx1arr = (int32_t *) alloca (s1len * sizeof (int32_t)); -- idx2arr = (int32_t *) alloca (s2len * sizeof (int32_t)); -- rule1arr = (unsigned char *) alloca (s1len); -- rule2arr = (unsigned char *) alloca (s2len); -- } - -- idx1cnt = 0; -- idx2cnt = 0; -- idx1max = 0; -- idx2max = 0; -- idx1now = 0; -- idx2now = 0; -- backw1_stop = ~0ul; -- backw2_stop = ~0ul; -- backw1 = ~0ul; -- backw2 = ~0ul; -- seq1len = 0; -- seq2len = 0; -- position = rulesets[0] & sort_position; -- while (1) -- { -- val1 = 0; -- val2 = 0; -- -- /* Get the next non-IGNOREd element for string `s1'. */ -- if (seq1len == 0) -- do -- { -- ++val1; -- -- if (backw1_stop != ~0ul) -- { -- /* The is something pushed. */ -- if (backw1 == backw1_stop) -- { -- /* The last pushed character was handled. Continue -- with forward characters. */ -- if (idx1cnt < idx1max) -- { -- idx1now = idx1cnt; -- backw1_stop = ~0ul; -- } -- else -- /* Nothing anymore. The backward sequence ended with -- the last sequence in the string. Note that seq1len -- is still zero. */ -- break; -- } -- else -- idx1now = --backw1; -- } -- else -- { -- backw1_stop = idx1max; -- -- while (*us1 != L('\0')) -- { -- int32_t tmp = findidx (&us1, -1); -- rule1arr[idx1max] = tmp >> 24; -- idx1arr[idx1max] = tmp & 0xffffff; -- idx1cnt = idx1max++; -- -- if ((rulesets[rule1arr[idx1cnt] * nrules] -- & sort_backward) == 0) -- /* No more backward characters to push. */ -- break; -- ++idx1cnt; -- } -- -- if (backw1_stop >= idx1cnt) -- { -- /* No sequence at all or just one. */ -- if (idx1cnt == idx1max || backw1_stop > idx1cnt) -- /* Note that seq1len is still zero. */ -- break; -- -- backw1_stop = ~0ul; -- idx1now = idx1cnt; -- } -- else -- /* We pushed backward sequences. */ -- idx1now = backw1 = idx1cnt - 1; -- } -- } -- while ((seq1len = weights[idx1arr[idx1now]++]) == 0); -- -- /* And the same for string `s2'. */ -- if (seq2len == 0) -- do -- { -- ++val2; -- -- if (backw2_stop != ~0ul) -- { -- /* The is something pushed. */ -- if (backw2 == backw2_stop) -- { -- /* The last pushed character was handled. Continue -- with forward characters. */ -- if (idx2cnt < idx2max) -- { -- idx2now = idx2cnt; -- backw2_stop = ~0ul; -- } -- else -- /* Nothing anymore. The backward sequence ended with -- the last sequence in the string. Note that seq2len -- is still zero. */ -- break; -- } -- else -- idx2now = --backw2; -- } -- else -- { -- backw2_stop = idx2max; -- -- while (*us2 != L('\0')) -- { -- int32_t tmp = findidx (&us2, -1); -- rule2arr[idx2max] = tmp >> 24; -- idx2arr[idx2max] = tmp & 0xffffff; -- idx2cnt = idx2max++; -- -- if ((rulesets[rule2arr[idx2cnt] * nrules] -- & sort_backward) == 0) -- /* No more backward characters to push. */ -- break; -- ++idx2cnt; -- } -- -- if (backw2_stop >= idx2cnt) -- { -- /* No sequence at all or just one. */ -- if (idx2cnt == idx2max || backw2_stop > idx2cnt) -- /* Note that seq1len is still zero. */ -- break; -- -- backw2_stop = ~0ul; -- idx2now = idx2cnt; -- } -- else -- /* We pushed backward sequences. */ -- idx2now = backw2 = idx2cnt - 1; -- } -- } -- while ((seq2len = weights[idx2arr[idx2now]++]) == 0); -- -- /* See whether any or both strings are empty. */ -- if (seq1len == 0 || seq2len == 0) -- { -- if (seq1len == seq2len) -- /* Both ended. So far so good, both strings are equal at the -- first level. */ -- break; -- -- /* This means one string is shorter than the other. Find out -- which one and return an appropriate value. */ -- result = seq1len == 0 ? -1 : 1; -- goto free_and_return; -- } -+ coll_seq seq1, seq2; -+ bool use_malloc = false; -+ int result = 0; - -- /* Test for position if necessary. */ -- if (position && val1 != val2) -- { -- result = val1 - val2; -- goto free_and_return; -- } -+ memset (&seq1, 0, sizeof (seq1)); -+ seq2 = seq1; - -- /* Compare the two sequences. */ -- do -- { -- if (weights[idx1arr[idx1now]] != weights[idx2arr[idx2now]]) -- { -- /* The sequences differ. */ -- result = weights[idx1arr[idx1now]] - weights[idx2arr[idx2now]]; -- goto free_and_return; -- } -+ size_t size_max = SIZE_MAX / (sizeof (int32_t) + 1); - -- /* Increment the offsets. */ -- ++idx1arr[idx1now]; -- ++idx2arr[idx2now]; -+ /* If the strings are long enough to cause overflow in the size request, then -+ skip the allocation and proceed with the non-cached routines. */ -+ if (MIN (s1len, s2len) > size_max -+ || MAX (s1len, s2len) > size_max - MIN (s1len, s2len)) -+ goto begin_collate; - -- --seq1len; -- --seq2len; -- } -- while (seq1len > 0 && seq2len > 0); -+ if (! __libc_use_alloca ((s1len + s2len) * (sizeof (int32_t) + 1))) -+ { -+ seq1.idxarr = (int32_t *) malloc ((s1len + s2len) * (sizeof (int32_t) + 1)); - -- if (position && seq1len != seq2len) +- use_malloc = true; ++ + /* If we failed to allocate memory, we leave everything as NULL so that + we use the nocache version of traversal and comparison functions. */ + if (seq1.idxarr != NULL) - { -- result = seq1len - seq2len; -- goto free_and_return; ++ { + seq2.idxarr = &seq1.idxarr[s1len]; + seq1.rulearr = (unsigned char *) &seq2.idxarr[s2len]; + seq2.rulearr = &seq1.rulearr[s1len]; + use_malloc = true; - } ++ } } -+ else -+ { -+ seq1.idxarr = (int32_t *) alloca (s1len * sizeof (int32_t)); -+ seq2.idxarr = (int32_t *) alloca (s2len * sizeof (int32_t)); -+ seq1.rulearr = (unsigned char *) alloca (s1len); -+ seq2.rulearr = (unsigned char *) alloca (s2len); -+ } - -- /* Now the remaining passes over the weights. We now use the -- indeces we found before. */ -- for (pass = 1; pass < nrules; ++pass) -+ int rule; -+ -+ begin_collate: -+ rule = 0; -+ /* Cache values in the first pass and if needed, use them in subsequent -+ passes. */ -+ for (int pass = 0; pass < nrules; ++pass) + else { -+ seq1.idxcnt = 0; +- try_stack: + seq1.idxarr = (int32_t *) alloca (s1len * sizeof (int32_t)); + seq2.idxarr = (int32_t *) alloca (s2len * sizeof (int32_t)); + seq1.rulearr = (unsigned char *) alloca (s1len); + seq2.rulearr = (unsigned char *) alloca (s2len); + } + +- seq1.rulearr[0] = 0; ++ int rule = 0; + + /* Cache values in the first pass and if needed, use them in subsequent + passes. */ + for (int pass = 0; pass < nrules; ++pass) + { + seq1.idxcnt = 0; + seq1.idx = 0; + seq2.idx = 0; -+ seq1.backw_stop = ~0ul; -+ seq1.backw = ~0ul; -+ seq2.idxcnt = 0; -+ seq2.backw_stop = ~0ul; -+ seq2.backw = ~0ul; -+ + seq1.backw_stop = ~0ul; + seq1.backw = ~0ul; + seq2.idxcnt = 0; + seq2.backw_stop = ~0ul; + seq2.backw = ~0ul; + + /* We need the elements of the strings as unsigned values since they + are used as indices. */ + seq1.us = (const USTRING_TYPE *) s1; @@ -780,137 +352,12 @@ index ecda08f..bb34a72 100644 + /* We assume that if a rule has defined `position' in one section this is true for all of them. */ -- idx1cnt = 0; -- idx2cnt = 0; -- backw1_stop = ~0ul; -- backw2_stop = ~0ul; -- backw1 = ~0ul; -- backw2 = ~0ul; -- position = rulesets[rule1arr[0] * nrules + pass] & sort_position; +- int position = rulesets[seq1.rulearr[0] * nrules + pass] & sort_position; + int position = rulesets[rule * nrules + pass] & sort_position; while (1) { -- val1 = 0; -- val2 = 0; -- -- /* Get the next non-IGNOREd element for string `s1'. */ -- if (seq1len == 0) -- do -- { -- ++val1; -- -- if (backw1_stop != ~0ul) -- { -- /* The is something pushed. */ -- if (backw1 == backw1_stop) -- { -- /* The last pushed character was handled. Continue -- with forward characters. */ -- if (idx1cnt < idx1max) -- { -- idx1now = idx1cnt; -- backw1_stop = ~0ul; -- } -- else -- { -- /* Nothing anymore. The backward sequence -- ended with the last sequence in the string. */ -- idx1now = ~0ul; -- break; -- } -- } -- else -- idx1now = --backw1; -- } -- else -- { -- backw1_stop = idx1cnt; -- -- while (idx1cnt < idx1max) -- { -- if ((rulesets[rule1arr[idx1cnt] * nrules + pass] -- & sort_backward) == 0) -- /* No more backward characters to push. */ -- break; -- ++idx1cnt; -- } -- -- if (backw1_stop == idx1cnt) -- { -- /* No sequence at all or just one. */ -- if (idx1cnt == idx1max) -- /* Note that seq1len is still zero. */ -- break; -- -- backw1_stop = ~0ul; -- idx1now = idx1cnt++; -- } -- else -- /* We pushed backward sequences. */ -- idx1now = backw1 = idx1cnt - 1; -- } -- } -- while ((seq1len = weights[idx1arr[idx1now]++]) == 0); -- -- /* And the same for string `s2'. */ -- if (seq2len == 0) -- do -- { -- ++val2; -- -- if (backw2_stop != ~0ul) -- { -- /* The is something pushed. */ -- if (backw2 == backw2_stop) -- { -- /* The last pushed character was handled. Continue -- with forward characters. */ -- if (idx2cnt < idx2max) -- { -- idx2now = idx2cnt; -- backw2_stop = ~0ul; -- } -- else -- { -- /* Nothing anymore. The backward sequence -- ended with the last sequence in the string. */ -- idx2now = ~0ul; -- break; -- } -- } -- else -- idx2now = --backw2; -- } -- else -- { -- backw2_stop = idx2cnt; -- -- while (idx2cnt < idx2max) -- { -- if ((rulesets[rule2arr[idx2cnt] * nrules + pass] -- & sort_backward) == 0) -- /* No more backward characters to push. */ -- break; -- ++idx2cnt; -- } -- -- if (backw2_stop == idx2cnt) -- { -- /* No sequence at all or just one. */ -- if (idx2cnt == idx2max) -- /* Note that seq2len is still zero. */ -- break; -- -- backw2_stop = ~0ul; -- idx2now = idx2cnt++; -- } -- else -- /* We pushed backward sequences. */ -- idx2now = backw2 = idx2cnt - 1; -- } -- } -- while ((seq2len = weights[idx2arr[idx2now]++]) == 0); +- if (pass == 0) + if (__glibc_unlikely (seq1.idxarr == NULL)) + { + get_next_seq_nocache (&seq1, nrules, rulesets, weights, table, @@ -919,73 +366,20 @@ index ecda08f..bb34a72 100644 + extra, indirect, pass); + } + else if (pass == 0) -+ { -+ get_next_seq (&seq1, nrules, rulesets, weights, table, extra, -+ indirect); -+ get_next_seq (&seq2, nrules, rulesets, weights, table, extra, -+ indirect); -+ } -+ else -+ { -+ get_next_seq_cached (&seq1, nrules, pass, rulesets, weights); -+ get_next_seq_cached (&seq2, nrules, pass, rulesets, weights); -+ } - - /* See whether any or both strings are empty. */ -- if (seq1len == 0 || seq2len == 0) -+ if (seq1.len == 0 || seq2.len == 0) { -- if (seq1len == seq2len) -+ if (seq1.len == seq2.len) - /* Both ended. So far so good, both strings are equal - at this level. */ - break; - - /* This means one string is shorter than the other. Find out - which one and return an appropriate value. */ -- result = seq1len == 0 ? -1 : 1; -+ result = seq1.len == 0 ? -1 : 1; + get_next_seq (&seq1, nrules, rulesets, weights, table, extra, + indirect); +@@ -411,10 +614,18 @@ STRCOLL (const STRING_TYPE *s1, const STRING_TYPE *s2, __locale_t l) goto free_and_return; } -- /* Test for position if necessary. */ -- if (position && val1 != val2) -- { -- result = val1 - val2; -- goto free_and_return; -- } -- -- /* Compare the two sequences. */ -- do -- { -- if (weights[idx1arr[idx1now]] != weights[idx2arr[idx2now]]) -- { -- /* The sequences differ. */ -- result = (weights[idx1arr[idx1now]] -- - weights[idx2arr[idx2now]]); -- goto free_and_return; -- } -- -- /* Increment the offsets. */ -- ++idx1arr[idx1now]; -- ++idx2arr[idx2now]; -- -- --seq1len; -- --seq2len; -- } -- while (seq1len > 0 && seq2len > 0); -- -- if (position && seq1len != seq2len) -- { -- result = seq1len - seq2len; -- goto free_and_return; -- } +- result = do_compare (&seq1, &seq2, position, weights); + if (__glibc_unlikely (seq1.idxarr == NULL)) + result = do_compare_nocache (&seq1, &seq2, position, weights); + else + result = do_compare (&seq1, &seq2, position, weights); -+ if (result != 0) -+ goto free_and_return; + if (result != 0) + goto free_and_return; } + + if (__glibc_likely (seq1.rulearr != NULL)) @@ -995,10 +389,70 @@ index ecda08f..bb34a72 100644 } /* Free the memory if needed. */ - free_and_return: - if (use_malloc) -- free (idx1arr); -+ free (seq1.idxarr); - - return result; - } +diff --git a/string/tst-strcoll-overflow.c b/string/tst-strcoll-overflow.c +new file mode 100644 +index 0000000..bb665ac +--- /dev/null ++++ b/string/tst-strcoll-overflow.c +@@ -0,0 +1,61 @@ ++/* Copyright (C) 2013 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 ++#include ++ ++/* Verify that strcoll does not crash for large strings for which it cannot ++ cache weight lookup results. The size is large enough to cause integer ++ overflows on 32-bit as well as buffer overflows on 64-bit. The test should ++ work reasonably reliably when overcommit is disabled, but it obviously ++ depends on how much memory the system has. There's a limitation to this ++ test in that it does not run to completion. Actually collating such a ++ large string can take days and we can't have xcheck running that long. For ++ that reason, we run the test for about 5 minutes and then assume that ++ everything is fine if there are no crashes. */ ++#define SIZE 0x40000000ul ++ ++int ++do_test (void) ++{ ++ if (setlocale (LC_COLLATE, "en_GB.UTF-8") == NULL) ++ { ++ puts ("setlocale failed, cannot test for overflow"); ++ return 0; ++ } ++ ++ char *p = malloc (SIZE); ++ ++ if (p == NULL) ++ { ++ puts ("could not allocate memory"); ++ return 1; ++ } ++ ++ memset (p, 'x', SIZE - 1); ++ p[SIZE - 1] = 0; ++ printf ("%d\n", strcoll (p, p)); ++ return 0; ++} ++ ++#define TIMEOUT 300 ++#define EXPECTED_SIGNAL SIGALRM ++#define TEST_FUNCTION do_test () ++#include "../test-skeleton.c" diff --git a/glibc.spec b/glibc.spec index f639c07..1d6a829 100644 --- a/glibc.spec +++ b/glibc.spec @@ -1,6 +1,6 @@ -%define glibcsrcdir glibc-2.18 -%define glibcversion 2.18 -%define glibcrelease 6%{?dist} +%define glibcsrcdir glibc-2.18-79-gbb8ea71 +%define glibcversion 2.18.90 +%define glibcrelease 1%{?dist} # Pre-release tarballs are pulled in from git using a command that is # effectively: # @@ -9,7 +9,7 @@ # gzip -9 $(git describe --match 'glibc-*').tar # # glibc_release_url is only defined when we have a release tarball. -%define glibc_release_url http://ftp.gnu.org/gnu/glibc/ +# % define glibc_release_url http://ftp.gnu.org/gnu/glibc/ ############################################################################## # If run_glibc_tests is zero then tests are not run for the build. # You must always set run_glibc_tests to one for production builds. @@ -183,7 +183,6 @@ Patch0042: %{name}-rh970865.patch # # Patches from upstream # -Patch1001: %{name}-rh995841.patch # # Patches submitted, but not yet approved upstream. @@ -200,9 +199,6 @@ Patch2013: %{name}-rh741105.patch # Upstream BZ 9954 Patch2021: %{name}-rh739743.patch -# Upstream BZ 13818 -Patch2022: %{name}-rh800224.patch - # Upstream BZ 14247 Patch2023: %{name}-rh827510.patch @@ -215,12 +211,6 @@ Patch2027: %{name}-rh819430.patch #Upstream BZ 14547 Patch2028: %{name}-strcoll-cve.patch -# Initialize res_hconf in nscd -Patch2029: %{name}-rh1000924.patch - -# Pass dl_hwcap to IFUNC resolver on 32-bit ARM. -Patch2030: %{name}-rh985342.patch - ############################################################################## # End of glibc patches. ############################################################################## @@ -521,7 +511,6 @@ package or when debugging this package. %patch0019 -p1 %patch0020 -p1 %patch2021 -p1 -%patch2022 -p1 %patch2023 -p1 %patch0024 -p1 %patch0025 -p1 @@ -537,12 +526,9 @@ package or when debugging this package. %patch0035 -p1 %patch0037 -p1 %patch2028 -p1 -%patch1001 -p1 %patch0040 -p1 %patch0041 -p1 %patch0042 -p1 -%patch2029 -p1 -%patch2030 -p1 ############################################################################## # %%prep - Additional prep required... @@ -1628,6 +1614,10 @@ rm -f *.filelist* %endif %changelog +* Thu Sep 5 2013 Siddhesh Poyarekar - 2.18.90-1 +- Resync with upstream master. +- Drop patch for #800224. + * Thu Aug 29 2013 Carlos O'Donell - 2.18-6 - Fix Power build (#997531). diff --git a/sources b/sources index 56c580f..087cb40 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -b67b22b428ed183148d1344da6d22ea9 glibc-2.18.tar.gz +411eba8ccda9743d2e2a49ef9379e860 glibc-2.18-79-gbb8ea71.tar.gz