diff options
author | joseph <joseph@7b3dc134-2b1b-0410-93df-9e9f96275f8d> | 2013-08-20 16:36:45 +0000 |
---|---|---|
committer | joseph <joseph@7b3dc134-2b1b-0410-93df-9e9f96275f8d> | 2013-08-20 16:36:45 +0000 |
commit | b4a4c38b54ec1734893153adba657bcd443a0175 (patch) | |
tree | 456b07473799d98ec0603448475b59b9e279091c /libc | |
parent | 80635627ed68eee72bfe1873816a92d7af5caac2 (diff) | |
download | eglibc2-b4a4c38b54ec1734893153adba657bcd443a0175.tar.gz |
Merge changes between r23715 and r23795 from /fsf/trunk.
git-svn-id: svn://svn.eglibc.org/trunk@23796 7b3dc134-2b1b-0410-93df-9e9f96275f8d
Diffstat (limited to 'libc')
-rw-r--r-- | libc/ChangeLog | 54 | ||||
-rw-r--r-- | libc/NEWS | 11 | ||||
-rw-r--r-- | libc/elf/setup-vdso.h | 2 | ||||
-rw-r--r-- | libc/manual/conf.texi | 9 | ||||
-rw-r--r-- | libc/manual/filesys.texi | 73 | ||||
-rw-r--r-- | libc/math/libm-test.inc | 5 | ||||
-rw-r--r-- | libc/ports/ChangeLog.powerpc | 9 | ||||
-rw-r--r-- | libc/ports/sysdeps/powerpc/nofpu/sim-full.c | 5 | ||||
-rw-r--r-- | libc/ports/sysdeps/powerpc/nofpu/soft-supp.h | 5 | ||||
-rw-r--r-- | libc/ports/sysdeps/powerpc/soft-fp/sfp-machine.h | 5 | ||||
-rw-r--r-- | libc/string/strcoll_l.c | 701 | ||||
-rw-r--r-- | libc/sysdeps/ieee754/ldbl-96/s_cbrtl.c | 2 | ||||
-rw-r--r-- | libc/sysdeps/posix/dirstream.h | 2 | ||||
-rw-r--r-- | libc/sysdeps/posix/opendir.c | 1 | ||||
-rw-r--r-- | libc/sysdeps/posix/readdir_r.c | 42 | ||||
-rw-r--r-- | libc/sysdeps/posix/rewinddir.c | 1 | ||||
-rw-r--r-- | libc/sysdeps/unix/sysv/linux/i386/readdir64_r.c | 1 | ||||
-rw-r--r-- | libc/sysdeps/unix/sysv/linux/s390/sys/procfs.h | 3 | ||||
-rw-r--r-- | libc/sysdeps/unix/sysv/linux/wordsize-64/readdir_r.c | 1 | ||||
-rw-r--r-- | libc/version.h | 4 |
20 files changed, 491 insertions, 445 deletions
diff --git a/libc/ChangeLog b/libc/ChangeLog index fa588c9f9..18fd09a55 100644 --- a/libc/ChangeLog +++ b/libc/ChangeLog @@ -1,3 +1,57 @@ +2013-08-20 Andreas Krebbel <Andreas.Krebbel@de.ibm.com> + + * sysdeps/unix/sysv/linux/s390/sys/procfs.h (struct elf_prstatus): + Align 32 bit compat elf_greg to 8 bytes. + +2013-08-20 Andreas Arnez <arnez@linux.vnet.ibm.com> + + * elf/setup-vdso.h (setup_vdso): Fix missing string termination. + +2013-08-20 Siddhesh Poyarekar <siddhesh@redhat.com> + + * string/strcoll_l.c (coll_seq): New structure. + (get_next_seq_cached): New function. + (get_next_seq): New function. + (do_compare): New function. + (STRCOLL): Use GNU style definition. Simplify implementation + by using get_next_seq, get_next_seq_cached and do_compare. + +2013-08-16 Florian Weimer <fweimer@redhat.com> + + [BZ #14699] + CVE-2013-4237 + * 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. + +2013-08-13 Andreas Schwab <schwab@suse.de> + + [BZ #15749] + * sysdeps/ieee754/ldbl-96/s_cbrtl.c (__cbrtl): Use fabsl instead + of fabs. + * math/libm-test.inc (cbrt_test_data) [TEST_LDOUBLE && + LDBL_MAX_EXP >= 16384]: Add tests for it. + +2013-08-12 David S. Miller <davem@davemloft.net> + + * version.h (RELEASE): Set to "development". + (VERSION): Set to "2.18.90". + * NEWS: Add 2.19 section. + 2013-08-03 David S. Miller <davem@davemloft.net> * po/ko.po: Update Korean translation from translation project. @@ -5,6 +5,17 @@ See the end for copying conditions. Please send GNU C library bug reports via <http://sourceware.org/bugzilla/> using `glibc' in the "product" field. +Version 2.19 + +* The following bugs are resolved with this release: + + 14699, 15749 + +* CVE-2013-4237 The readdir_r function could write more than NAME_MAX bytes + to the d_name member of struct dirent, or omit the terminating NUL + character. (Bugzilla #14699). + + Version 2.18 * The following bugs are resolved with this release: diff --git a/libc/elf/setup-vdso.h b/libc/elf/setup-vdso.h index a98dfeca3..056d885bd 100644 --- a/libc/elf/setup-vdso.h +++ b/libc/elf/setup-vdso.h @@ -89,7 +89,7 @@ setup_vdso (struct link_map *main_map __attribute__ ((unused)), addresses in the vsyscall DSO pages in writev() calls. */ const char *dsoname = ((char *) D_PTR (l, l_info[DT_STRTAB]) + l->l_info[DT_SONAME]->d_un.d_val); - size_t len = strlen (dsoname); + size_t len = strlen (dsoname) + 1; char *copy = malloc (len); if (copy == NULL) _dl_fatal_printf ("out of memory\n"); diff --git a/libc/manual/conf.texi b/libc/manual/conf.texi index 7eb8b3625..c720063b8 100644 --- a/libc/manual/conf.texi +++ b/libc/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/libc/manual/filesys.texi b/libc/manual/filesys.texi index 1df9cf2b3..814c210a9 100644 --- a/libc/manual/filesys.texi +++ b/libc/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/libc/math/libm-test.inc b/libc/math/libm-test.inc index 2324d4fd5..851f1beaf 100644 --- a/libc/math/libm-test.inc +++ b/libc/math/libm-test.inc @@ -5845,6 +5845,11 @@ static const struct test_f_f_data cbrt_test_data[] = TEST_f_f (cbrt, -27.0, -3.0), TEST_f_f (cbrt, 0.9921875L, 0.997389022060725270579075195353955217L), TEST_f_f (cbrt, 0.75L, 0.908560296416069829445605878163630251L), + +#if defined TEST_LDOUBLE && LDBL_MAX_EXP >= 16384 + TEST_f_f (cbrt, 0x1p16383L, 0x1p5461L), + TEST_f_f (cbrt, 0x1p-16383L, 0x1p-5461L), +#endif }; static void diff --git a/libc/ports/ChangeLog.powerpc b/libc/ports/ChangeLog.powerpc index 8272ef3a9..e503682ce 100644 --- a/libc/ports/ChangeLog.powerpc +++ b/libc/ports/ChangeLog.powerpc @@ -1,3 +1,12 @@ +2013-08-17 Alexandre Oliva <aoliva@redhat.com> + + PR 15483 + * sysdeps/powerpc/nofpu/sim-full.c: Add FIXME note about + the need for thread-specific variables preserved across signal + handlers. + * sysdeps/powerpc/nofpu/soft-supp.h: Likewise. + * sysdeps/powerpc/soft-fp/sfp-machine.h: Likewise. + 2013-07-03 Joseph Myers <joseph@codesourcery.com> * sysdeps/powerpc/nofpu/libm-test-ulps: Regenerated. diff --git a/libc/ports/sysdeps/powerpc/nofpu/sim-full.c b/libc/ports/sysdeps/powerpc/nofpu/sim-full.c index fc061d0c0..e16703323 100644 --- a/libc/ports/sysdeps/powerpc/nofpu/sim-full.c +++ b/libc/ports/sysdeps/powerpc/nofpu/sim-full.c @@ -21,6 +21,11 @@ #include "soft-fp.h" #include "soft-supp.h" +/* FIXME: these variables should be thread specific (see bugzilla bug + 15483) and ideally preserved across signal handlers, like hardware + FP status words, but the latter is quite difficult to accomplish in + userland. */ + /* Global to store sticky exceptions. */ int __sim_exceptions __attribute__ ((nocommon)); libc_hidden_data_def (__sim_exceptions); diff --git a/libc/ports/sysdeps/powerpc/nofpu/soft-supp.h b/libc/ports/sysdeps/powerpc/nofpu/soft-supp.h index b9638bbba..64a3d2a1d 100644 --- a/libc/ports/sysdeps/powerpc/nofpu/soft-supp.h +++ b/libc/ports/sysdeps/powerpc/nofpu/soft-supp.h @@ -26,6 +26,11 @@ typedef union } fenv_union_t; +/* FIXME: these variables should be thread specific (see bugzilla bug + 15483) and ideally preserved across signal handlers, like hardware + FP status words, but the latter is quite difficult to accomplish in + userland. */ + extern int __sim_exceptions; libc_hidden_proto (__sim_exceptions); extern int __sim_disabled_exceptions; diff --git a/libc/ports/sysdeps/powerpc/soft-fp/sfp-machine.h b/libc/ports/sysdeps/powerpc/soft-fp/sfp-machine.h index c2a190e7e..508d8698d 100644 --- a/libc/ports/sysdeps/powerpc/soft-fp/sfp-machine.h +++ b/libc/ports/sysdeps/powerpc/soft-fp/sfp-machine.h @@ -54,6 +54,11 @@ #define FP_ROUNDMODE __sim_round_mode #define FP_TRAPPING_EXCEPTIONS (~__sim_disabled_exceptions & 0x3e000000) +/* FIXME: these variables should be thread specific (see bugzilla bug + 15483) and ideally preserved across signal handlers, like hardware + FP status words, but the latter is quite difficult to accomplish in + userland. */ + extern int __sim_exceptions; libc_hidden_proto (__sim_exceptions); extern int __sim_disabled_exceptions; diff --git a/libc/string/strcoll_l.c b/libc/string/strcoll_l.c index 8759a05cc..bfe11c458 100644 --- a/libc/string/strcoll_l.c +++ b/libc/string/strcoll_l.c @@ -42,11 +42,244 @@ #include "../locale/localeinfo.h" +/* Track status while looking for sequences in a string. */ +typedef struct +{ + int len; /* Length of the current sequence. */ + int 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. */ +} 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) +{ + int 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 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) + { + /* The 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; +} + +/* Compare two sequences. */ +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; + 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) + { + result = val1 - val2; + 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]; #if __OPTION_EGLIBC_LOCALE_CODE @@ -61,34 +294,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 if (nrules == 0) return STRCMP (s1, s2); @@ -103,7 +308,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); @@ -111,18 +315,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); - /* 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 @@ -132,411 +331,101 @@ STRCOLL (s1, s2, l) Please note that the localedef programs makes sure that `position' is not used at the first level. */ + + coll_seq seq1, seq2; + bool use_malloc = false; + int result = 0; + + memset (&seq1, 0, sizeof (seq1)); + seq2 = seq1; + + /* We need the elements of the strings as unsigned values since they + are used as indices. */ + seq1.us = (const USTRING_TYPE *) s1; + seq2.us = (const USTRING_TYPE *) s2; + 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]; + 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; + use_malloc = true; } 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); + 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); } - 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; - } - - /* 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]; + seq1.rulearr[0] = 0; - --seq1len; - --seq2len; - } - while (seq1len > 0 && seq2len > 0); - - if (position && seq1len != seq2len) - { - result = seq1len - seq2len; - goto free_and_return; - } - } - - /* Now the remaining passes over the weights. We now use the - indeces we found before. */ - for (pass = 1; pass < nrules; ++pass) + /* 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.backw_stop = ~0ul; + seq1.backw = ~0ul; + seq2.idxcnt = 0; + seq2.backw_stop = ~0ul; + seq2.backw = ~0ul; + /* 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; 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) + { + 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; 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 (result != 0) + goto free_and_return; } } /* Free the memory if needed. */ free_and_return: if (use_malloc) - free (idx1arr); + free (seq1.idxarr); return result; } diff --git a/libc/sysdeps/ieee754/ldbl-96/s_cbrtl.c b/libc/sysdeps/ieee754/ldbl-96/s_cbrtl.c index b481c84eb..e6b2f2540 100644 --- a/libc/sysdeps/ieee754/ldbl-96/s_cbrtl.c +++ b/libc/sysdeps/ieee754/ldbl-96/s_cbrtl.c @@ -45,7 +45,7 @@ __cbrtl (long double x) int xe; /* Reduce X. XM now is an range 1.0 to 0.5. */ - xm = __frexpl (fabs (x), &xe); + xm = __frexpl (fabsl (x), &xe); /* If X is not finite or is null return it (with raising exceptions if necessary. diff --git a/libc/sysdeps/posix/dirstream.h b/libc/sysdeps/posix/dirstream.h index a7a074d35..8e8570dd4 100644 --- a/libc/sysdeps/posix/dirstream.h +++ b/libc/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/libc/sysdeps/posix/opendir.c b/libc/sysdeps/posix/opendir.c index ddfc3a751..fc05b0f9d 100644 --- a/libc/sysdeps/posix/opendir.c +++ b/libc/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/libc/sysdeps/posix/readdir_r.c b/libc/sysdeps/posix/readdir_r.c index b5a8e2ede..8ed5c3fc9 100644 --- a/libc/sysdeps/posix/readdir_r.c +++ b/libc/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/libc/sysdeps/posix/rewinddir.c b/libc/sysdeps/posix/rewinddir.c index 2935a8e5a..d4991ad43 100644 --- a/libc/sysdeps/posix/rewinddir.c +++ b/libc/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/libc/sysdeps/unix/sysv/linux/i386/readdir64_r.c b/libc/sysdeps/unix/sysv/linux/i386/readdir64_r.c index 8ebbcfda1..a7d114ee9 100644 --- a/libc/sysdeps/unix/sysv/linux/i386/readdir64_r.c +++ b/libc/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 <sysdeps/posix/readdir_r.c> diff --git a/libc/sysdeps/unix/sysv/linux/s390/sys/procfs.h b/libc/sysdeps/unix/sysv/linux/s390/sys/procfs.h index 36088f162..c27c660a9 100644 --- a/libc/sysdeps/unix/sysv/linux/s390/sys/procfs.h +++ b/libc/sysdeps/unix/sysv/linux/s390/sys/procfs.h @@ -123,7 +123,8 @@ typedef struct elf_prpsinfo prpsinfo_t; core files. */ #define ELF_NGREG32 36 typedef unsigned int elf_greg_t32; -typedef elf_greg_t32 elf_gregset_t32[ELF_NGREG32]; +typedef elf_greg_t32 + elf_gregset_t32[ELF_NGREG32] __attribute__ ((__aligned__ (8))); typedef elf_fpregset_t elf_fpregset_t32; struct elf_prstatus32 diff --git a/libc/sysdeps/unix/sysv/linux/wordsize-64/readdir_r.c b/libc/sysdeps/unix/sysv/linux/wordsize-64/readdir_r.c index 5ed8e955e..290f2c8f6 100644 --- a/libc/sysdeps/unix/sysv/linux/wordsize-64/readdir_r.c +++ b/libc/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 <sysdeps/posix/readdir_r.c> #undef readdir64_r weak_alias (__readdir_r, readdir64_r) diff --git a/libc/version.h b/libc/version.h index 7485c9e2c..c88ab1cfb 100644 --- a/libc/version.h +++ b/libc/version.h @@ -1,4 +1,4 @@ /* This file just defines the current version number of libc. */ -#define RELEASE "stable" -#define VERSION "2.18" +#define RELEASE "development" +#define VERSION "2.18.90" |