Compare commits

...

55 Commits
master ... f23

Author SHA1 Message Date
Florian Weimer 60b8a73579 argp: Do not override GCC keywords with macros (#1366830) 2016-08-18 16:20:17 +02:00
Florian Weimer 80acfa27b0 fopencookie: Mangle function pointers stored on the heap (swbz#20222) 2016-08-18 16:17:58 +02:00
Florian Weimer fe01d7c362 nss_db: Fix initialization of iteration position (#1344480) 2016-08-18 16:12:58 +02:00
Florian Weimer 18df09c331 Return proper status from _nss_nis_initgroups_dyn (#1294574) 2016-08-18 16:10:25 +02:00
Florian Weimer 371b5ecb70 CVE-2016-6323: Backtraces can hang on ARM EABI (32-bit) (swbz#20435) 2016-08-18 16:06:54 +02:00
Florian Weimer b256ca9b8a malloc: Avoid premature fallback to mmap (#1348620) 2016-08-18 16:03:18 +02:00
Florian Weimer 37bc92a77f Avoid duplicating object files already in libc.a (#1352625) 2016-08-18 16:00:56 +02:00
Florian Weimer b9da92483d Backport: nptl/tst-once5: Reduce time to expected failure 2016-08-18 15:58:41 +02:00
Florian Weimer 9b47092236 Resolves: #1337291
struct sockaddr_storage GCC 6 enablement
2016-06-02 12:54:47 +02:00
Florian Weimer 7a43147883 Resolves: #1326903
Fix fork redirection in libpthread
2016-06-02 12:51:54 +02:00
Florian Weimer 2d5168f40a Resolves: #1337140
CVE-2016-4429: stack overflow in Sun RPC clntudp_call
2016-06-02 12:47:32 +02:00
Florian Weimer 0b01e9c2eb Add missing patch description 2016-05-11 12:14:52 +02:00
Florian Weimer 6edf83c63d Resolves: #1282011
Fix first day of week of the hr_HR locale
2016-05-11 10:45:45 +02:00
Florian Weimer 76672943a2 Resolves: #1204521
Fix first day of week of the fr_CH, it_CH locales
2016-05-11 10:39:53 +02:00
Florian Weimer d7fc7c363e Resolves: #1330888
CVE-2016-3706: stack overflow in getaddrinfo hostent conversion
2016-05-11 10:32:50 +02:00
Florian Weimer 10fdc4382b Resolves: #1335011
Back out glibc-rh1333945.patch, glibc-rh1333945-2.patch because they
cause a regression in ASAN.
2016-05-11 10:28:44 +02:00
Florian Weimer 55dbe293ce Resolves: #1288740
Fix tst-makecontext on armhfp
2016-05-07 16:51:51 +02:00
Florian Weimer 0ad6e19e8d Resolves: #1307234
Fix strfmon_l to use the locale object for grouping
2016-05-07 16:48:42 +02:00
Florian Weimer a5d8db31b4 Resolves: #1300304
CVE-2015-8778: integer overflow in hcreate and hcreate_r
2016-05-07 16:43:31 +02:00
Florian Weimer 9f4a81eb45 Resolves: #1300300
CVE-2015-8776: crash with invalid data in strftime
2016-05-07 16:41:04 +02:00
Florian Weimer 15f7423992 Resolves: #1293139
Fix invalid memory access in getmntent_r
2016-05-07 16:39:26 +02:00
Florian Weimer 421842aad7 Resolves: #1300311
CVE-2014-9761: unbounded stack allocation in nan* functions
2016-05-07 15:37:01 +02:00
Florian Weimer 327133fe22 Resolves: #1300314
CVE-2015-8779: unbounded stack allocation in catopen
2016-05-07 11:38:02 +02:00
Florian Weimer e97f134cc1 Resolves: #1321372
Change first day of the week for es_CL to Monday
2016-05-07 09:35:20 +02:00
Florian Weimer c3f1918b6c Resolves: #1332917
Fix deadlock between between fflush, getdelim, and fork
2016-05-06 21:07:01 +02:00
Florian Weimer 53d6baa069 Resolves: #1333945
Set dlerror after dlsym (RTLD_NEXT) failure
2016-05-06 20:43:59 +02:00
Florian Weimer 6ca2fbefbe Resolves: #1315648
CVE-2016-1234: buffer overflow in glob with GLOB_ALTDIRFUNC
2016-05-06 20:12:40 +02:00
Florian Weimer 4c57cf5cfa Resolves: #1333901
Fix getnameinfo memory leak and incorrect truncation
2016-05-06 20:08:00 +02:00
Florian Weimer 8ef83de907 Resolves: #1333940
Avoid build failure in TZ tests
2016-05-06 20:01:07 +02:00
Florian Weimer d277a9bbcd Resolves: #1316972
resolv: Fix NULL pointer dereference with unconnectable address
2016-05-06 17:23:21 +02:00
Florian Weimer 84517e1bc0 Resolves: #1321861
nss_db: Fix handling of long entries
2016-05-06 17:19:09 +02:00
Florian Weimer 79cd021451 Resolves: #1313404
Fix elf/tst-audit10 and elf/tst-audit4 failures
2016-05-06 17:13:11 +02:00
Florian Weimer 217d136f41 Resolves: #1332914
April 2016 nss_dns hardening
2016-05-06 17:02:34 +02:00
Florian Weimer 116e17a138 Resolves: #1321954
CVE-2016-3075: Stack overflow in _nss_dns_getnetbyname_r
2016-05-06 16:35:32 +02:00
Florian Weimer 6702e0c88e Remove unapplied patches 2016-05-06 16:22:10 +02:00
Florian Weimer bea7fc560d Remove the series file
It causes unnecessary conflicts when switching between branches.
2016-05-06 14:26:47 +02:00
Florian Weimer 62f2d369c8 Resolves: #1332912
Fix heap-based buffer overflow in get_txt_records
2016-05-06 14:22:22 +02:00
Mike FABIAN dd028df7c1 Add the C.UTF-8 locale 2016-03-02 10:07:01 +01:00
Florian Weimer 431c99df4c Resolves: #1114591
Remove stray newline from Serbian locales.
2016-02-19 21:39:18 +01:00
Florian Weimer 6136c09c1e glibc.spec: Fix typo in comment 2016-02-19 21:18:48 +01:00
Florian Weimer e8497bf411 Resolves: 1310168
Fix socket system call selection on s390x.
2016-02-19 21:14:18 +01:00
Florian Weimer 9f1734eb6c Resolves: #1308943
CVE-2015-7547: Stack-based buffer overflow in getaddrinfo
2016-02-16 15:19:52 +01:00
Florian Weimer 73fbe412ea Resolves: #1252570
Revert upstream commit 2212c1420c92a33b0e0bd9a34938c9814a56c0f7.
2016-02-15 11:42:18 +01:00
Florian Weimer 74847c75cc Resolves: #1295189
Update glibc-rh1276112.patch to include backports to fix
upstream bugs 19243 and 19182.
2016-01-04 10:03:45 +01:00
Florian Weimer 67d13737ec Resolves: #1276761
Apply additional pointer guard hardening.
2015-12-05 15:06:23 +01:00
Florian Weimer e8f4ba5ab2 Resolves: #1288662
Re-enable large file support in openat.
2015-12-05 14:50:06 +01:00
Jaromir Capik 6f2d4738ab Adding BUILD_CC to the STAGE1 bootstrap recipes 2015-12-03 15:33:54 +01:00
Carlos O'Donell 7a808bcd62 Resolves: #1276711
- Remove invalid strcoll optimization (#1276711).
2015-11-09 21:06:48 -05:00
Jaromir Capik 37137eb3e4 Fix for early stage2 SIGSEGV + 32-bit TARGET rework 2015-11-05 17:56:36 +01:00
Florian Weimer 6fbf955dad Resolves: #1276112
Prevent malloc arena free list from becoming cyclic.
2015-10-30 13:12:53 +01:00
Mike FABIAN 26f4d28240 build-locale-archive sometimes created empty archives
(fixed by David Shea) (#1262040)
2015-09-17 08:23:43 +02:00
Siddhesh Poyarekar a0be169239 Remove initgroups from default nsswitch.conf (#751450) 2015-08-14 13:40:59 +05:30
Siddhesh Poyarekar 07e6287dc2 Update for glibc-2.22 release 2015-08-05 17:29:28 +05:30
Siddhesh Poyarekar 9af85e62a6 Sync with upstream master
- glibc-bench-compare.patch: Merged upstream
- glibc-rh757881.patch: Fixed differently upstream
- glibc-revert-arena-threshold-fix.patch: Additional fixes on top of this
- glibc-rh841787.patch: Fixed differently upstream
- Set MODULE_NAME=librt for rtkaio
- Fix up glibc-rh741105.patch to continue to work with latest master
2015-07-28 10:38:07 +05:30
Siddhesh Poyarekar c2535df93e Back out the new condvar implementation
Back out the new condvar implementation from F23 since it is not yet
ready for primetime.  The change is still there in rawhide, so it
could use some testing there.
2015-07-27 22:26:30 +05:30
87 changed files with 11306 additions and 10790 deletions

View File

@ -31,31 +31,28 @@ mcd $BUILDDIR/glibc
# prefill glibc cache
echo libc_cv_forced_unwind=yes > config.cache
echo libc_cv_c_cleanup=yes >> config.cache
echo libc_cv_ctors_header=yes >> config.cache
#echo libc_cv_ctors_header=yes >> config.cache
echo ac_cv_header_cpuid_h=yes >> config.cache
echo libc_cv_gcc_builtin_expect=yes >> config.cache
$SRC/$GV/configure $GLIBCARGS
notparallel
make $J ARCH=${KARCH} cross-compiling=yes
make DESTDIR=$ROOTFS $J ARCH=${KARCH} cross-compiling=yes install
make $J ARCH=${KARCH} BUILD_CC=gcc cross-compiling=yes
make DESTDIR=$ROOTFS $J ARCH=${KARCH} BUILD_CC=gcc cross-compiling=yes install
( cd $ROOTFS/usr/include/bits
sed '/ifndef.*NO_LONG_DOUBLE/,/#endif/d' < mathdef.h > mathdef.h.new
mv mathdef.h.new mathdef.h
)
# If we are building x86_64, then the 32-bit multilib libgcc
# will also need 32-bit headers.
if [ "$TARGET" = "x86_64-linux-gnu" ]; then
# 32-bit multilib libgcc needs 32-bit headers
if [ ! "$TARGET32" = "" ]; then
old_CC=$CC
old_CXX=$CC
export CC="$TARGET-gcc -m32"
export CXX="$TARGET-g++ -m32"
TARGET32=i686-pc-linux-gnu
GLIBCARGS="--prefix=/usr
--with-headers=$ROOTFS/usr/include
--enable-kernel=2.6.32
@ -84,8 +81,8 @@ if [ "$TARGET" = "x86_64-linux-gnu" ]; then
$SRC/$GV/configure $GLIBCARGS
notparallel
make $J ARCH=${KARCH} cross-compiling=yes
make DESTDIR=$ROOTFS $J ARCH=${KARCH} cross-compiling=yes install
make $J ARCH=${KARCH} BUILD_CC=gcc cross-compiling=yes
make DESTDIR=$ROOTFS $J ARCH=${KARCH} BUILD_CC=gcc cross-compiling=yes install
( cd $ROOTFS/usr/include/bits
sed '/ifndef.*NO_LONG_DOUBLE/,/#endif/d' < mathdef.h > mathdef.h.new

View File

@ -26,13 +26,13 @@ mcd $BUILDDIR/glibc-stage1
# prefill glibc cache
echo libc_cv_forced_unwind=yes > config.cache
echo libc_cv_c_cleanup=yes >> config.cache
echo libc_cv_ctors_header=yes >> config.cache
#echo libc_cv_ctors_header=yes >> config.cache
echo ac_cv_header_cpuid_h=yes >> config.cache
echo libc_cv_gcc_builtin_expect=yes >> config.cache
$SRC/$GV/configure $GLIBCARGS
notparallel
make DESTDIR=$ROOTFS $J ARCH=${KARCH} cross-compiling=yes install-headers
make DESTDIR=$ROOTFS $J ARCH=${KARCH} BUILD_CC=gcc cross-compiling=yes install-headers
touch $ROOTFS/usr/include/gnu/stubs.h
touch $ROOTFS/usr/include/bits/stdio_lim.h
@ -43,7 +43,7 @@ touch $ROOTFS/usr/include/bits/stdio_lim.h
# We also build just enough files to link libgcc.so. The fake
# libc.so will never actually get used, but simplifies the boostrap.
make $J ARCH=${KARCH} cross-compiling=yes csu/subdir_lib
make $J ARCH=${KARCH} BUILD_CC=gcc cross-compiling=yes csu/subdir_lib
mkdirp $ROOTFS/usr/lib${SUFFIX}
for file in `cd csu; echo crt*.o`; do
@ -52,18 +52,16 @@ done
$TARGET-gcc -nostdlib -nostartfiles -shared -x c /dev/null\
-o $ROOTFS/usr/lib${SUFFIX}/libc.so
# If we are building x86_64, then the 32-bit multilib libgcc
# will also need stub 32-bit libraries.
if [ "$TARGET" = "x86_64-linux-gnu" ]; then
# 32-bit multilib libgcc needs stub 32-bit libraries
if [ ! "$TARGET32" = "" ]; then
old_CC=$CC
old_CXX=$CC
export CC="$TARGET-gcc -m32"
export CXX="$TARGET-g++ -m32"
TARGET32="i686-pc-linux-gnu"
# setup 32-bit glibc headers
# This path MUST be relative, not absolute
GV=$(cd $SRC; echo glibc-2*)
GLIBCARGS="--prefix=/usr
--with-headers=$ROOTFS/usr/include
--enable-kernel=2.6.32
@ -86,13 +84,13 @@ if [ "$TARGET" = "x86_64-linux-gnu" ]; then
# prefill glibc cache
echo libc_cv_forced_unwind=yes > config.cache
echo libc_cv_c_cleanup=yes >> config.cache
echo libc_cv_ctors_header=yes >> config.cache
#echo libc_cv_ctors_header=yes >> config.cache
echo ac_cv_header_cpuid_h=yes >> config.cache
echo libc_cv_gcc_builtin_expect=yes >> config.cache
$SRC/$GV/configure $GLIBCARGS
notparallel
make DESTDIR=$ROOTFS $J ARCH=${KARCH} cross-compiling=yes install-headers
make DESTDIR=$ROOTFS $J ARCH=${KARCH} BUILD_CC=gcc cross-compiling=yes install-headers
touch $ROOTFS/usr/include/gnu/stubs.h
touch $ROOTFS/usr/include/bits/stdio_lim.h
@ -103,7 +101,7 @@ if [ "$TARGET" = "x86_64-linux-gnu" ]; then
# We also build just enough files to link libgcc.so. The fake
# libc.so will never actually get used, but simplifies the boostrap.
make $J ARCH=${KARCH} cross-compiling=yes csu/subdir_lib
make $J ARCH=${KARCH} BUILD_CC=gcc cross-compiling=yes csu/subdir_lib
mkdirp $ROOTFS/usr/lib
for file in `cd csu; echo crt*.o`; do

View File

@ -313,8 +313,7 @@ fill_archive (struct locarhandle *tmpl_ah,
/* Add one for "_" and one for the null terminator. */
size_t len = strlen (install_langs_list[i]) + 2;
char *install_lang = (char *)xmalloc (len);
strncpy (install_lang, install_langs_list[i], len - 2);
install_lang[len - 1] = '\0';
strcpy (install_lang, install_langs_list[i]);
if (strchr (install_lang, '_') == NULL)
strcat (install_lang, "_");
if (strncmp (name, install_lang, strlen (install_lang)) == 0)

View File

@ -1,10 +1,12 @@
#!/bin/bash
# Autogeneries the quilt `series` from the patch order in the spec file.
# We don't use `quilt setup` because it makes a huge mess and doesn't work.
component="glibc"
rm -f series.new
extra_args="--fuzz=0"
count=0
# Filter out the patches, and use `_` as our pseudo-IFS to prevent expansion.
for i in `grep '%patch' glibc.spec | sed -e 's,%patch,,g' -e 's, ,_,g'`; do
for i in `grep '^%patch' glibc.spec | sed -e 's,%patch,,g' -e 's, ,_,g'`; do
# Split the patch into number and arguments.
# 1 - Patch number.
# 2-N - Patch arguments.
@ -12,15 +14,20 @@ for i in `grep '%patch' glibc.spec | sed -e 's,%patch,,g' -e 's, ,_,g'`; do
elements=(`echo $i | sed -e 's,_, ,g'`)
num=${elements[0]}
args=${elements[@]:1}
grep "Patch${num}" glibc.spec | sed -e 's,Patch.*: ,,g' -e "s,\$, ${args[@]},g" >> series.new
# Find the next patch that applies in order and write it out.
# This way we transform the patch # list into a patch file list in order.
grep "Patch${num}: " glibc.spec \
| sed -e 's,Patch.*: ,,g' -e "s,\$, ${args[@]} ${extra_args},g" \
| sed -e "s,%{name},${component},g" \
>> series.new
((count++))
done
# Double check we processed the correct number of patches.
fcount=`wc -l series.new | sed -e 's, .*$,,g'`
if [ $fcount -ne $count ]; then
echo "Error! Processed less patches than in spec file ($fcount != $count)."
echo "Error! Processed patch count doesn't match spec file count ($fcount != $count)."
exit 1
fi
echo "Processed $count patches."
mv series.new series
echo "Generated quilt ./series file, please commit."
exit 0

554
glibc-CVE-2015-7547.patch Normal file
View File

@ -0,0 +1,554 @@
Index: b/resolv/nss_dns/dns-host.c
===================================================================
--- a/resolv/nss_dns/dns-host.c
+++ b/resolv/nss_dns/dns-host.c
@@ -1031,7 +1031,10 @@ gaih_getanswer_slice (const querybuf *an
int h_namelen = 0;
if (ancount == 0)
- return NSS_STATUS_NOTFOUND;
+ {
+ *h_errnop = HOST_NOT_FOUND;
+ return NSS_STATUS_NOTFOUND;
+ }
while (ancount-- > 0 && cp < end_of_message && had_error == 0)
{
@@ -1208,7 +1211,14 @@ gaih_getanswer_slice (const querybuf *an
/* Special case here: if the resolver sent a result but it only
contains a CNAME while we are looking for a T_A or T_AAAA record,
we fail with NOTFOUND instead of TRYAGAIN. */
- return canon == NULL ? NSS_STATUS_TRYAGAIN : NSS_STATUS_NOTFOUND;
+ if (canon != NULL)
+ {
+ *h_errnop = HOST_NOT_FOUND;
+ return NSS_STATUS_NOTFOUND;
+ }
+
+ *h_errnop = NETDB_INTERNAL;
+ return NSS_STATUS_TRYAGAIN;
}
@@ -1222,11 +1232,101 @@ gaih_getanswer (const querybuf *answer1,
enum nss_status status = NSS_STATUS_NOTFOUND;
+ /* Combining the NSS status of two distinct queries requires some
+ compromise and attention to symmetry (A or AAAA queries can be
+ returned in any order). What follows is a breakdown of how this
+ code is expected to work and why. We discuss only SUCCESS,
+ TRYAGAIN, NOTFOUND and UNAVAIL, since they are the only returns
+ that apply (though RETURN and MERGE exist). We make a distinction
+ between TRYAGAIN (recoverable) and TRYAGAIN' (not-recoverable).
+ A recoverable TRYAGAIN is almost always due to buffer size issues
+ and returns ERANGE in errno and the caller is expected to retry
+ with a larger buffer.
+
+ Lastly, you may be tempted to make significant changes to the
+ conditions in this code to bring about symmetry between responses.
+ Please don't change anything without due consideration for
+ expected application behaviour. Some of the synthesized responses
+ aren't very well thought out and sometimes appear to imply that
+ IPv4 responses are always answer 1, and IPv6 responses are always
+ answer 2, but that's not true (see the implemetnation of send_dg
+ and send_vc to see response can arrive in any order, particlarly
+ for UDP). However, we expect it holds roughly enough of the time
+ that this code works, but certainly needs to be fixed to make this
+ a more robust implementation.
+
+ ----------------------------------------------
+ | Answer 1 Status / | Synthesized | Reason |
+ | Answer 2 Status | Status | |
+ |--------------------------------------------|
+ | SUCCESS/SUCCESS | SUCCESS | [1] |
+ | SUCCESS/TRYAGAIN | TRYAGAIN | [5] |
+ | SUCCESS/TRYAGAIN' | SUCCESS | [1] |
+ | SUCCESS/NOTFOUND | SUCCESS | [1] |
+ | SUCCESS/UNAVAIL | SUCCESS | [1] |
+ | TRYAGAIN/SUCCESS | TRYAGAIN | [2] |
+ | TRYAGAIN/TRYAGAIN | TRYAGAIN | [2] |
+ | TRYAGAIN/TRYAGAIN' | TRYAGAIN | [2] |
+ | TRYAGAIN/NOTFOUND | TRYAGAIN | [2] |
+ | TRYAGAIN/UNAVAIL | TRYAGAIN | [2] |
+ | TRYAGAIN'/SUCCESS | SUCCESS | [3] |
+ | TRYAGAIN'/TRYAGAIN | TRYAGAIN | [3] |
+ | TRYAGAIN'/TRYAGAIN' | TRYAGAIN' | [3] |
+ | TRYAGAIN'/NOTFOUND | TRYAGAIN' | [3] |
+ | TRYAGAIN'/UNAVAIL | UNAVAIL | [3] |
+ | NOTFOUND/SUCCESS | SUCCESS | [3] |
+ | NOTFOUND/TRYAGAIN | TRYAGAIN | [3] |
+ | NOTFOUND/TRYAGAIN' | TRYAGAIN' | [3] |
+ | NOTFOUND/NOTFOUND | NOTFOUND | [3] |
+ | NOTFOUND/UNAVAIL | UNAVAIL | [3] |
+ | UNAVAIL/SUCCESS | UNAVAIL | [4] |
+ | UNAVAIL/TRYAGAIN | UNAVAIL | [4] |
+ | UNAVAIL/TRYAGAIN' | UNAVAIL | [4] |
+ | UNAVAIL/NOTFOUND | UNAVAIL | [4] |
+ | UNAVAIL/UNAVAIL | UNAVAIL | [4] |
+ ----------------------------------------------
+
+ [1] If the first response is a success we return success.
+ This ignores the state of the second answer and in fact
+ incorrectly sets errno and h_errno to that of the second
+ answer. However because the response is a success we ignore
+ *errnop and *h_errnop (though that means you touched errno on
+ success). We are being conservative here and returning the
+ likely IPv4 response in the first answer as a success.
+
+ [2] If the first response is a recoverable TRYAGAIN we return
+ that instead of looking at the second response. The
+ expectation here is that we have failed to get an IPv4 response
+ and should retry both queries.
+
+ [3] If the first response was not a SUCCESS and the second
+ response is not NOTFOUND (had a SUCCESS, need to TRYAGAIN,
+ or failed entirely e.g. TRYAGAIN' and UNAVAIL) then use the
+ result from the second response, otherwise the first responses
+ status is used. Again we have some odd side-effects when the
+ second response is NOTFOUND because we overwrite *errnop and
+ *h_errnop that means that a first answer of NOTFOUND might see
+ its *errnop and *h_errnop values altered. Whether it matters
+ in practice that a first response NOTFOUND has the wrong
+ *errnop and *h_errnop is undecided.
+
+ [4] If the first response is UNAVAIL we return that instead of
+ looking at the second response. The expectation here is that
+ it will have failed similarly e.g. configuration failure.
+
+ [5] Testing this code is complicated by the fact that truncated
+ second response buffers might be returned as SUCCESS if the
+ first answer is a SUCCESS. To fix this we add symmetry to
+ TRYAGAIN with the second response. If the second response
+ is a recoverable error we now return TRYAGIN even if the first
+ response was SUCCESS. */
+
if (anslen1 > 0)
status = gaih_getanswer_slice(answer1, anslen1, qname,
&pat, &buffer, &buflen,
errnop, h_errnop, ttlp,
&first);
+
if ((status == NSS_STATUS_SUCCESS || status == NSS_STATUS_NOTFOUND
|| (status == NSS_STATUS_TRYAGAIN
/* We want to look at the second answer in case of an
@@ -1242,8 +1342,15 @@ gaih_getanswer (const querybuf *answer1,
&pat, &buffer, &buflen,
errnop, h_errnop, ttlp,
&first);
+ /* Use the second response status in some cases. */
if (status != NSS_STATUS_SUCCESS && status2 != NSS_STATUS_NOTFOUND)
status = status2;
+ /* Do not return a truncated second response (unless it was
+ unavoidable e.g. unrecoverable TRYAGAIN). */
+ if (status == NSS_STATUS_SUCCESS
+ && (status2 == NSS_STATUS_TRYAGAIN
+ && *errnop == ERANGE && *h_errnop != NO_RECOVERY))
+ status = NSS_STATUS_TRYAGAIN;
}
return status;
Index: b/resolv/res_query.c
===================================================================
--- a/resolv/res_query.c
+++ b/resolv/res_query.c
@@ -396,6 +396,7 @@ __libc_res_nsearch(res_state statp,
{
free (*answerp2);
*answerp2 = NULL;
+ *nanswerp2 = 0;
*answerp2_malloced = 0;
}
}
@@ -447,6 +448,7 @@ __libc_res_nsearch(res_state statp,
{
free (*answerp2);
*answerp2 = NULL;
+ *nanswerp2 = 0;
*answerp2_malloced = 0;
}
@@ -521,6 +523,7 @@ __libc_res_nsearch(res_state statp,
{
free (*answerp2);
*answerp2 = NULL;
+ *nanswerp2 = 0;
*answerp2_malloced = 0;
}
if (saved_herrno != -1)
Index: b/resolv/res_send.c
===================================================================
--- a/resolv/res_send.c
+++ b/resolv/res_send.c
@@ -1,3 +1,20 @@
+/* Copyright (C) 2016 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
+ <http://www.gnu.org/licenses/>. */
+
/*
* Copyright (c) 1985, 1989, 1993
* The Regents of the University of California. All rights reserved.
@@ -361,6 +378,8 @@ __libc_res_nsend(res_state statp, const
#ifdef USE_HOOKS
if (__glibc_unlikely (statp->qhook || statp->rhook)) {
if (anssiz < MAXPACKET && ansp) {
+ /* Always allocate MAXPACKET, callers expect
+ this specific size. */
u_char *buf = malloc (MAXPACKET);
if (buf == NULL)
return (-1);
@@ -660,6 +679,77 @@ libresolv_hidden_def (res_nsend)
/* Private */
+/* The send_vc function is responsible for sending a DNS query over TCP
+ to the nameserver numbered NS from the res_state STATP i.e.
+ EXT(statp).nssocks[ns]. The function supports sending both IPv4 and
+ IPv6 queries at the same serially on the same socket.
+
+ Please note that for TCP there is no way to disable sending both
+ queries, unlike UDP, which honours RES_SNGLKUP and RES_SNGLKUPREOP
+ and sends the queries serially and waits for the result after each
+ sent query. This implemetnation should be corrected to honour these
+ options.
+
+ Please also note that for TCP we send both queries over the same
+ socket one after another. This technically violates best practice
+ since the server is allowed to read the first query, respond, and
+ then close the socket (to service another client). If the server
+ does this, then the remaining second query in the socket data buffer
+ will cause the server to send the client an RST which will arrive
+ asynchronously and the client's OS will likely tear down the socket
+ receive buffer resulting in a potentially short read and lost
+ response data. This will force the client to retry the query again,
+ and this process may repeat until all servers and connection resets
+ are exhausted and then the query will fail. It's not known if this
+ happens with any frequency in real DNS server implementations. This
+ implementation should be corrected to use two sockets by default for
+ parallel queries.
+
+ The query stored in BUF of BUFLEN length is sent first followed by
+ the query stored in BUF2 of BUFLEN2 length. Queries are sent
+ serially on the same socket.
+
+ Answers to the query are stored firstly in *ANSP up to a max of
+ *ANSSIZP bytes. If more than *ANSSIZP bytes are needed and ANSCP
+ is non-NULL (to indicate that modifying the answer buffer is allowed)
+ then malloc is used to allocate a new response buffer and ANSCP and
+ ANSP will both point to the new buffer. If more than *ANSSIZP bytes
+ are needed but ANSCP is NULL, then as much of the response as
+ possible is read into the buffer, but the results will be truncated.
+ When truncation happens because of a small answer buffer the DNS
+ packets header feild TC will bet set to 1, indicating a truncated
+ message and the rest of the socket data will be read and discarded.
+
+ Answers to the query are stored secondly in *ANSP2 up to a max of
+ *ANSSIZP2 bytes, with the actual response length stored in
+ *RESPLEN2. If more than *ANSSIZP bytes are needed and ANSP2
+ is non-NULL (required for a second query) then malloc is used to
+ allocate a new response buffer, *ANSSIZP2 is set to the new buffer
+ size and *ANSP2_MALLOCED is set to 1.
+
+ The ANSP2_MALLOCED argument will eventually be removed as the
+ change in buffer pointer can be used to detect the buffer has
+ changed and that the caller should use free on the new buffer.
+
+ Note that the answers may arrive in any order from the server and
+ therefore the first and second answer buffers may not correspond to
+ the first and second queries.
+
+ It is not supported to call this function with a non-NULL ANSP2
+ but a NULL ANSCP. Put another way, you can call send_vc with a
+ single unmodifiable buffer or two modifiable buffers, but no other
+ combination is supported.
+
+ It is the caller's responsibility to free the malloc allocated
+ buffers by detecting that the pointers have changed from their
+ original values i.e. *ANSCP or *ANSP2 has changed.
+
+ If errors are encountered then *TERRNO is set to an appropriate
+ errno value and a zero result is returned for a recoverable error,
+ and a less-than zero result is returned for a non-recoverable error.
+
+ If no errors are encountered then *TERRNO is left unmodified and
+ a the length of the first response in bytes is returned. */
static int
send_vc(res_state statp,
const u_char *buf, int buflen, const u_char *buf2, int buflen2,
@@ -669,11 +759,7 @@ send_vc(res_state statp,
{
const HEADER *hp = (HEADER *) buf;
const HEADER *hp2 = (HEADER *) buf2;
- u_char *ans = *ansp;
- int orig_anssizp = *anssizp;
- // XXX REMOVE
- // int anssiz = *anssizp;
- HEADER *anhp = (HEADER *) ans;
+ HEADER *anhp = (HEADER *) *ansp;
struct sockaddr_in6 *nsap = EXT(statp).nsaddrs[ns];
int truncating, connreset, n;
/* On some architectures compiler might emit a warning indicating
@@ -766,6 +852,8 @@ send_vc(res_state statp,
* Receive length & response
*/
int recvresp1 = 0;
+ /* Skip the second response if there is no second query.
+ To do that we mark the second response as received. */
int recvresp2 = buf2 == NULL;
uint16_t rlen16;
read_len:
@@ -802,40 +890,14 @@ send_vc(res_state statp,
u_char **thisansp;
int *thisresplenp;
if ((recvresp1 | recvresp2) == 0 || buf2 == NULL) {
+ /* We have not received any responses
+ yet or we only have one response to
+ receive. */
thisanssizp = anssizp;
thisansp = anscp ?: ansp;
assert (anscp != NULL || ansp2 == NULL);
thisresplenp = &resplen;
} else {
- if (*anssizp != MAXPACKET) {
- /* No buffer allocated for the first
- reply. We can try to use the rest
- of the user-provided buffer. */
-#if __GNUC_PREREQ (4, 7)
- DIAG_PUSH_NEEDS_COMMENT;
- DIAG_IGNORE_NEEDS_COMMENT (5, "-Wmaybe-uninitialized");
-#endif
-#if _STRING_ARCH_unaligned
- *anssizp2 = orig_anssizp - resplen;
- *ansp2 = *ansp + resplen;
-#else
- int aligned_resplen
- = ((resplen + __alignof__ (HEADER) - 1)
- & ~(__alignof__ (HEADER) - 1));
- *anssizp2 = orig_anssizp - aligned_resplen;
- *ansp2 = *ansp + aligned_resplen;
-#endif
-#if __GNUC_PREREQ (4, 7)
- DIAG_POP_NEEDS_COMMENT;
-#endif
- } else {
- /* The first reply did not fit into the
- user-provided buffer. Maybe the second
- answer will. */
- *anssizp2 = orig_anssizp;
- *ansp2 = *ansp;
- }
-
thisanssizp = anssizp2;
thisansp = ansp2;
thisresplenp = resplen2;
@@ -843,10 +905,14 @@ send_vc(res_state statp,
anhp = (HEADER *) *thisansp;
*thisresplenp = rlen;
- if (rlen > *thisanssizp) {
- /* Yes, we test ANSCP here. If we have two buffers
- both will be allocatable. */
- if (__glibc_likely (anscp != NULL)) {
+ /* Is the answer buffer too small? */
+ if (*thisanssizp < rlen) {
+ /* If the current buffer is non-NULL and it's not
+ pointing at the static user-supplied buffer then
+ we can reallocate it. */
+ if (thisansp != NULL && thisansp != ansp) {
+ /* Always allocate MAXPACKET, callers expect
+ this specific size. */
u_char *newp = malloc (MAXPACKET);
if (newp == NULL) {
*terrno = ENOMEM;
@@ -858,6 +924,9 @@ send_vc(res_state statp,
if (thisansp == ansp2)
*ansp2_malloced = 1;
anhp = (HEADER *) newp;
+ /* A uint16_t can't be larger than MAXPACKET
+ thus it's safe to allocate MAXPACKET but
+ read RLEN bytes instead. */
len = rlen;
} else {
Dprint(statp->options & RES_DEBUG,
@@ -1021,6 +1090,66 @@ reopen (res_state statp, int *terrno, in
return 1;
}
+/* The send_dg function is responsible for sending a DNS query over UDP
+ to the nameserver numbered NS from the res_state STATP i.e.
+ EXT(statp).nssocks[ns]. The function supports IPv4 and IPv6 queries
+ along with the ability to send the query in parallel for both stacks
+ (default) or serially (RES_SINGLKUP). It also supports serial lookup
+ with a close and reopen of the socket used to talk to the server
+ (RES_SNGLKUPREOP) to work around broken name servers.
+
+ The query stored in BUF of BUFLEN length is sent first followed by
+ the query stored in BUF2 of BUFLEN2 length. Queries are sent
+ in parallel (default) or serially (RES_SINGLKUP or RES_SNGLKUPREOP).
+
+ Answers to the query are stored firstly in *ANSP up to a max of
+ *ANSSIZP bytes. If more than *ANSSIZP bytes are needed and ANSCP
+ is non-NULL (to indicate that modifying the answer buffer is allowed)
+ then malloc is used to allocate a new response buffer and ANSCP and
+ ANSP will both point to the new buffer. If more than *ANSSIZP bytes
+ are needed but ANSCP is NULL, then as much of the response as
+ possible is read into the buffer, but the results will be truncated.
+ When truncation happens because of a small answer buffer the DNS
+ packets header feild TC will bet set to 1, indicating a truncated
+ message, while the rest of the UDP packet is discarded.
+
+ Answers to the query are stored secondly in *ANSP2 up to a max of
+ *ANSSIZP2 bytes, with the actual response length stored in
+ *RESPLEN2. If more than *ANSSIZP bytes are needed and ANSP2
+ is non-NULL (required for a second query) then malloc is used to
+ allocate a new response buffer, *ANSSIZP2 is set to the new buffer
+ size and *ANSP2_MALLOCED is set to 1.
+
+ The ANSP2_MALLOCED argument will eventually be removed as the
+ change in buffer pointer can be used to detect the buffer has
+ changed and that the caller should use free on the new buffer.
+
+ Note that the answers may arrive in any order from the server and
+ therefore the first and second answer buffers may not correspond to
+ the first and second queries.
+
+ It is not supported to call this function with a non-NULL ANSP2
+ but a NULL ANSCP. Put another way, you can call send_vc with a
+ single unmodifiable buffer or two modifiable buffers, but no other
+ combination is supported.
+
+ It is the caller's responsibility to free the malloc allocated
+ buffers by detecting that the pointers have changed from their
+ original values i.e. *ANSCP or *ANSP2 has changed.
+
+ If an answer is truncated because of UDP datagram DNS limits then
+ *V_CIRCUIT is set to 1 and the return value non-zero to indicate to
+ the caller to retry with TCP. The value *GOTSOMEWHERE is set to 1
+ if any progress was made reading a response from the nameserver and
+ is used by the caller to distinguish between ECONNREFUSED and
+ ETIMEDOUT (the latter if *GOTSOMEWHERE is 1).
+
+ If errors are encountered then *TERRNO is set to an appropriate
+ errno value and a zero result is returned for a recoverable error,
+ and a less-than zero result is returned for a non-recoverable error.
+
+ If no errors are encountered then *TERRNO is left unmodified and
+ a the length of the first response in bytes is returned. */
static int
send_dg(res_state statp,
const u_char *buf, int buflen, const u_char *buf2, int buflen2,
@@ -1030,8 +1159,6 @@ send_dg(res_state statp,
{
const HEADER *hp = (HEADER *) buf;
const HEADER *hp2 = (HEADER *) buf2;
- u_char *ans = *ansp;
- int orig_anssizp = *anssizp;
struct timespec now, timeout, finish;
struct pollfd pfd[1];
int ptimeout;
@@ -1064,6 +1191,8 @@ send_dg(res_state statp,
int need_recompute = 0;
int nwritten = 0;
int recvresp1 = 0;
+ /* Skip the second response if there is no second query.
+ To do that we mark the second response as received. */
int recvresp2 = buf2 == NULL;
pfd[0].fd = EXT(statp).nssocks[ns];
pfd[0].events = POLLOUT;
@@ -1227,55 +1356,56 @@ send_dg(res_state statp,
int *thisresplenp;
if ((recvresp1 | recvresp2) == 0 || buf2 == NULL) {
+ /* We have not received any responses
+ yet or we only have one response to
+ receive. */
thisanssizp = anssizp;
thisansp = anscp ?: ansp;
assert (anscp != NULL || ansp2 == NULL);
thisresplenp = &resplen;
} else {
- if (*anssizp != MAXPACKET) {
- /* No buffer allocated for the first
- reply. We can try to use the rest
- of the user-provided buffer. */
-#if _STRING_ARCH_unaligned
- *anssizp2 = orig_anssizp - resplen;
- *ansp2 = *ansp + resplen;
-#else
- int aligned_resplen
- = ((resplen + __alignof__ (HEADER) - 1)
- & ~(__alignof__ (HEADER) - 1));
- *anssizp2 = orig_anssizp - aligned_resplen;
- *ansp2 = *ansp + aligned_resplen;
-#endif
- } else {
- /* The first reply did not fit into the
- user-provided buffer. Maybe the second
- answer will. */
- *anssizp2 = orig_anssizp;
- *ansp2 = *ansp;
- }
-
thisanssizp = anssizp2;
thisansp = ansp2;
thisresplenp = resplen2;
}
if (*thisanssizp < MAXPACKET
- /* Yes, we test ANSCP here. If we have two buffers
- both will be allocatable. */
- && anscp
+ /* If the current buffer is non-NULL and it's not
+ pointing at the static user-supplied buffer then
+ we can reallocate it. */
+ && (thisansp != NULL && thisansp != ansp)
#ifdef FIONREAD
+ /* Is the size too small? */
&& (ioctl (pfd[0].fd, FIONREAD, thisresplenp) < 0
|| *thisanssizp < *thisresplenp)
#endif
) {
+ /* Always allocate MAXPACKET, callers expect
+ this specific size. */
u_char *newp = malloc (MAXPACKET);
if (newp != NULL) {
- *anssizp = MAXPACKET;
- *thisansp = ans = newp;
+ *thisanssizp = MAXPACKET;
+ *thisansp = newp;
if (thisansp == ansp2)
*ansp2_malloced = 1;
}
}
+ /* We could end up with truncation if anscp was NULL
+ (not allowed to change caller's buffer) and the
+ response buffer size is too small. This isn't a
+ reliable way to detect truncation because the ioctl
+ may be an inaccurate report of the UDP message size.
+ Therefore we use this only to issue debug output.
+ To do truncation accurately with UDP we need
+ MSG_TRUNC which is only available on Linux. We
+ can abstract out the Linux-specific feature in the
+ future to detect truncation. */
+ if (__glibc_unlikely (*thisanssizp < *thisresplenp)) {
+ Dprint(statp->options & RES_DEBUG,
+ (stdout, ";; response may be truncated (UDP)\n")
+ );
+ }
+
HEADER *anhp = (HEADER *) *thisansp;
socklen_t fromlen = sizeof(struct sockaddr_in6);
assert (sizeof(from) <= fromlen);

View File

@ -20,8 +20,8 @@ index ded5471..7d28496 100644
+ stp xzr, x30, [sp, #32+16*2]
+
mrs x4, tpidr_el0
ldr x1, [x0,#8]
ldr x0, [x4]
/* The ldar here happens after the load from [x0] at the call site
(that is generated by the compiler as part of the TLS access ABI),
@@ -169,6 +173,8 @@ _dl_tlsdesc_dynamic:
1:
ldp x1, x2, [sp, #32+16*0]
@ -30,4 +30,4 @@ index ded5471..7d28496 100644
+ msr nzcv, x30
ldp x29, x30, [sp], #(32+16*NSAVEXREGPAIRS)
cfi_adjust_cfa_offset (32+16*NSAVEXREGPAIRS)
cfi_adjust_cfa_offset (-32-16*NSAVEXREGPAIRS)

View File

@ -1,412 +0,0 @@
diff -pruN a/benchtests/scripts/compare_bench.py b/benchtests/scripts/compare_bench.py
--- a/benchtests/scripts/compare_bench.py 1970-01-01 05:30:00.000000000 +0530
+++ b/benchtests/scripts/compare_bench.py 2015-05-07 15:32:41.843584024 +0530
@@ -0,0 +1,184 @@
+#!/usr/bin/python
+# 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
+# <http://www.gnu.org/licenses/>.
+"""Compare two benchmark results
+
+Given two benchmark result files and a threshold, this script compares the
+benchmark results and flags differences in performance beyond a given
+threshold.
+"""
+import sys
+import os
+import pylab
+import import_bench as bench
+
+def do_compare(func, var, tl1, tl2, par, threshold):
+ """Compare one of the aggregate measurements
+
+ Helper function to compare one of the aggregate measurements of a function
+ variant.
+
+ Args:
+ func: Function name
+ var: Function variant name
+ tl1: The first timings list
+ tl2: The second timings list
+ par: The aggregate to measure
+ threshold: The threshold for differences, beyond which the script should
+ print a warning.
+ """
+ d = abs(tl2[par] - tl1[par]) * 100 / tl1[str(par)]
+ if d > threshold:
+ if tl1[par] > tl2[par]:
+ ind = '+++'
+ else:
+ ind = '---'
+ print('%s %s(%s)[%s]: (%.2lf%%) from %g to %g' %
+ (ind, func, var, par, d, tl1[par], tl2[par]))
+
+
+def compare_runs(pts1, pts2, threshold):
+ """Compare two benchmark runs
+
+ Args:
+ pts1: Timing data from first machine
+ pts2: Timing data from second machine
+ """
+
+ # XXX We assume that the two benchmarks have identical functions and
+ # variants. We cannot compare two benchmarks that may have different
+ # functions or variants. Maybe that is something for the future.
+ for func in pts1['functions'].keys():
+ for var in pts1['functions'][func].keys():
+ tl1 = pts1['functions'][func][var]
+ tl2 = pts2['functions'][func][var]
+
+ # Compare the consolidated numbers
+ # do_compare(func, var, tl1, tl2, 'max', threshold)
+ do_compare(func, var, tl1, tl2, 'min', threshold)
+ do_compare(func, var, tl1, tl2, 'mean', threshold)
+
+ # Skip over to the next variant or function if there is no detailed
+ # timing info for the function variant.
+ if 'timings' not in pts1['functions'][func][var].keys() or \
+ 'timings' not in pts2['functions'][func][var].keys():
+ continue
+
+ # If two lists do not have the same length then it is likely that
+ # the performance characteristics of the function have changed.
+ # XXX: It is also likely that there was some measurement that
+ # strayed outside the usual range. Such ouiers should not
+ # happen on an idle machine with identical hardware and
+ # configuration, but ideal environments are hard to come by.
+ if len(tl1['timings']) != len(tl2['timings']):
+ print('* %s(%s): Timing characteristics changed' %
+ (func, var))
+ print('\tBefore: [%s]' %
+ ', '.join([str(x) for x in tl1['timings']]))
+ print('\tAfter: [%s]' %
+ ', '.join([str(x) for x in tl2['timings']]))
+ continue
+
+ # Collect numbers whose differences cross the threshold we have
+ # set.
+ issues = [(x, y) for x, y in zip(tl1['timings'], tl2['timings']) \
+ if abs(y - x) * 100 / x > threshold]
+
+ # Now print them.
+ for t1, t2 in issues:
+ d = abs(t2 - t1) * 100 / t1
+ if t2 > t1:
+ ind = '-'
+ else:
+ ind = '+'
+
+ print("%s %s(%s): (%.2lf%%) from %g to %g" %
+ (ind, func, var, d, t1, t2))
+
+
+def plot_graphs(bench1, bench2):
+ """Plot graphs for functions
+
+ Make scatter plots for the functions and their variants.
+
+ Args:
+ bench1: Set of points from the first machine
+ bench2: Set of points from the second machine.
+ """
+ for func in bench1['functions'].keys():
+ for var in bench1['functions'][func].keys():
+ # No point trying to print a graph if there are no detailed
+ # timings.
+ if u'timings' not in bench1['functions'][func][var].keys():
+ print('Skipping graph for %s(%s)' % (func, var))
+ continue
+
+ pylab.clf()
+ pylab.ylabel('Time (cycles)')
+
+ # First set of points
+ length = len(bench1['functions'][func][var]['timings'])
+ X = [float(x) for x in range(length)]
+ lines = pylab.scatter(X, bench1['functions'][func][var]['timings'],
+ 1.5 + 100 / length)
+ pylab.setp(lines, 'color', 'r')
+
+ # Second set of points
+ length = len(bench2['functions'][func][var]['timings'])
+ X = [float(x) for x in range(length)]
+ lines = pylab.scatter(X, bench2['functions'][func][var]['timings'],
+ 1.5 + 100 / length)
+ pylab.setp(lines, 'color', 'g')
+
+ if var:
+ filename = "%s-%s.png" % (func, var)
+ else:
+ filename = "%s.png" % func
+ print('Writing out %s' % filename)
+ pylab.savefig(filename)
+
+
+def main(args):
+ """Program Entry Point
+
+ Take two benchmark output files and compare their timings.
+ """
+ if len(args) > 4 or len(args) < 3:
+ print('Usage: %s <schema> <file1> <file2> [threshold in %%]' % sys.argv[0])
+ sys.exit(os.EX_USAGE)
+
+ bench1 = bench.parse_bench(args[1], args[0])
+ bench2 = bench.parse_bench(args[2], args[0])
+ if len(args) == 4:
+ threshold = float(args[3])
+ else:
+ threshold = 10.0
+
+ if (bench1['timing_type'] != bench2['timing_type']):
+ print('Cannot compare benchmark outputs: timing types are different')
+ return
+
+ plot_graphs(bench1, bench2)
+
+ bench.compress_timings(bench1)
+ bench.compress_timings(bench2)
+
+ compare_runs(bench1, bench2, threshold)
+
+
+if __name__ == '__main__':
+ main(sys.argv[1:])
diff -pruN a/benchtests/scripts/import_bench.py b/benchtests/scripts/import_bench.py
--- a/benchtests/scripts/import_bench.py 1970-01-01 05:30:00.000000000 +0530
+++ b/benchtests/scripts/import_bench.py 2015-05-07 15:32:41.844584032 +0530
@@ -0,0 +1,141 @@
+#!/usr/bin/python
+# 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
+# <http://www.gnu.org/licenses/>.
+"""Functions to import benchmark data and process it"""
+
+import json
+try:
+ import jsonschema as validator
+except ImportError:
+ print('Could not find jsonschema module.')
+ raise
+
+
+def mean(lst):
+ """Compute and return mean of numbers in a list
+
+ The numpy average function has horrible performance, so implement our
+ own mean function.
+
+ Args:
+ lst: The list of numbers to average.
+ Return:
+ The mean of members in the list.
+ """
+ return sum(lst) / len(lst)
+
+
+def split_list(bench, func, var):
+ """ Split the list into a smaller set of more distinct points
+
+ Group together points such that the difference between the smallest
+ point and the mean is less than 1/3rd of the mean. This means that
+ the mean is at most 1.5x the smallest member of that group.
+
+ mean - xmin < mean / 3
+ i.e. 2 * mean / 3 < xmin
+ i.e. mean < 3 * xmin / 2
+
+ For an evenly distributed group, the largest member will be less than
+ twice the smallest member of the group.
+ Derivation:
+
+ An evenly distributed series would be xmin, xmin + d, xmin + 2d...
+
+ mean = (2 * n * xmin + n * (n - 1) * d) / 2 * n
+ and max element is xmin + (n - 1) * d
+
+ Now, mean < 3 * xmin / 2
+
+ 3 * xmin > 2 * mean
+ 3 * xmin > (2 * n * xmin + n * (n - 1) * d) / n
+ 3 * n * xmin > 2 * n * xmin + n * (n - 1) * d
+ n * xmin > n * (n - 1) * d
+ xmin > (n - 1) * d
+ 2 * xmin > xmin + (n-1) * d
+ 2 * xmin > xmax
+
+ Hence, proved.
+
+ Similarly, it is trivial to prove that for a similar aggregation by using
+ the maximum element, the maximum element in the group must be at most 4/3
+ times the mean.
+
+ Args:
+ bench: The benchmark object
+ func: The function name
+ var: The function variant name
+ """
+ means = []
+ lst = bench['functions'][func][var]['timings']
+ last = len(lst) - 1
+ while lst:
+ for i in range(last + 1):
+ avg = mean(lst[i:])
+ if avg > 0.75 * lst[last]:
+ means.insert(0, avg)
+ lst = lst[:i]
+ last = i - 1
+ break
+ bench['functions'][func][var]['timings'] = means
+
+
+def do_for_all_timings(bench, callback):
+ """Call a function for all timing objects for each function and its
+ variants.
+
+ Args:
+ bench: The benchmark object
+ callback: The callback function
+ """
+ for func in bench['functions'].keys():
+ for k in bench['functions'][func].keys():
+ if 'timings' not in bench['functions'][func][k].keys():
+ continue
+
+ callback(bench, func, k)
+
+
+def compress_timings(points):
+ """Club points with close enough values into a single mean value
+
+ See split_list for details on how the clubbing is done.
+
+ Args:
+ points: The set of points.
+ """
+ do_for_all_timings(points, split_list)
+
+
+def parse_bench(filename, schema_filename):
+ """Parse the input file
+
+ Parse and validate the json file containing the benchmark outputs. Return
+ the resulting object.
+ Args:
+ filename: Name of the benchmark output file.
+ Return:
+ The bench dictionary.
+ """
+ with open(schema_filename, 'r') as schemafile:
+ schema = json.load(schemafile)
+ with open(filename, 'r') as benchfile:
+ bench = json.load(benchfile)
+ validator.validate(bench, schema)
+ do_for_all_timings(bench, lambda b, f, v:
+ b['functions'][f][v]['timings'].sort())
+ return bench
diff -pruN a/benchtests/scripts/validate_benchout.py b/benchtests/scripts/validate_benchout.py
--- a/benchtests/scripts/validate_benchout.py 2015-05-07 11:58:40.000000000 +0530
+++ b/benchtests/scripts/validate_benchout.py 2015-05-07 15:32:41.844584032 +0530
@@ -27,37 +27,26 @@ import sys
import os
try:
- import jsonschema
+ import import_bench as bench
except ImportError:
- print('Could not find jsonschema module. Output not validated.')
+ print('Import Error: Output will not be validated.')
# Return success because we don't want the bench target to fail just
# because the jsonschema module was not found.
sys.exit(os.EX_OK)
-def validate_bench(benchfile, schemafile):
- """Validate benchmark file
-
- Validate a benchmark output file against a JSON schema.
+def print_and_exit(message, exitcode):
+ """Prints message to stderr and returns the exit code.
Args:
- benchfile: The file name of the bench.out file.
- schemafile: The file name of the JSON schema file to validate
- bench.out against.
+ message: The message to print
+ exitcode: The exit code to return
- Exceptions:
- jsonschema.ValidationError: When bench.out is not valid
- jsonschema.SchemaError: When the JSON schema is not valid
- IOError: If any of the files are not found.
+ Returns:
+ The passed exit code
"""
- with open(benchfile, 'r') as bfile:
- with open(schemafile, 'r') as sfile:
- bench = json.load(bfile)
- schema = json.load(sfile)
- jsonschema.validate(bench, schema)
-
- # If we reach here, we're all good.
- print("Benchmark output in %s is valid." % benchfile)
+ print(message, file=sys.stderr)
+ return exitcode
def main(args):
@@ -73,11 +62,23 @@ def main(args):
Exceptions thrown by validate_bench
"""
if len(args) != 2:
- print("Usage: %s <bench.out file> <bench.out schema>" % sys.argv[0],
- file=sys.stderr)
- return os.EX_USAGE
+ return print_and_exit("Usage: %s <bench.out file> <bench.out schema>"
+ % sys.argv[0], os.EX_USAGE)
+
+ try:
+ bench.parse_bench(args[0], args[1])
+ except IOError as e:
+ return print_and_exit("IOError(%d): %s" % (e.errno, e.strerror),
+ os.EX_OSFILE)
+
+ except bench.validator.ValidationError as e:
+ return print_and_exit("Invalid benchmark output: %s" % e.message,
+ os.EX_DATAERR)
+
+ except bench.validator.SchemaError as e:
+ return print_and_exit("Invalid schema: %s" % e.message, os.EX_DATAERR)
- validate_bench(args[0], args[1])
+ print("Benchmark output in %s is valid." % args[0])
return os.EX_OK

22
glibc-build-time.patch Normal file
View File

@ -0,0 +1,22 @@
Various patches to improve build time.
commit e07eca6a72d21a5a37ba33df7b126609db048c41
Author: Florian Weimer <fweimer@redhat.com>
Date: Wed Aug 17 16:14:02 2016 +0200
nptl/tst-once5: Reduce time to expected failure
(cherry picked from commit 1f645571d2db9008b3cd3d5acb9ff93357864283)
diff --git a/nptl/tst-once5.cc b/nptl/tst-once5.cc
index 60bc78a..a6985b0 100644
--- a/nptl/tst-once5.cc
+++ b/nptl/tst-once5.cc
@@ -76,5 +76,7 @@ do_test (void)
return result;
}
+// The test currently hangs and is XFAILed. Reduce the timeout.
+#define TIMEOUT 1
#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"

270
glibc-c-utf8-locale.patch Normal file
View File

@ -0,0 +1,270 @@
From 2eda7b462b415105f5a05c1323372d4e39d46439 Mon Sep 17 00:00:00 2001
From: Mike FABIAN <mfabian@redhat.com>
Date: Mon, 10 Aug 2015 15:58:12 +0200
Subject: [PATCH] Add a C.UTF-8 locale
---
localedata/SUPPORTED | 1 +
localedata/locales/C | 238 +++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 239 insertions(+)
create mode 100644 localedata/locales/C
diff --git a/localedata/SUPPORTED b/localedata/SUPPORTED
index 8ca023e..2a78391 100644
--- a/localedata/SUPPORTED
+++ b/localedata/SUPPORTED
@@ -1,6 +1,7 @@
# This file names the currently supported and somewhat tested locales.
# If you have any additions please file a glibc bug report.
SUPPORTED-LOCALES=\
+C.UTF-8/UTF-8 \
aa_DJ.UTF-8/UTF-8 \
aa_DJ/ISO-8859-1 \
aa_ER/UTF-8 \
diff --git a/localedata/locales/C b/localedata/locales/C
new file mode 100644
index 0000000..fdf460e
--- /dev/null
+++ b/localedata/locales/C
@@ -0,0 +1,238 @@
+escape_char /
+comment_char %
+% Locale for C locale in UTF-8
+
+LC_IDENTIFICATION
+title "C locale"
+source ""
+address ""
+contact ""
+email "mfabian@redhat.com"
+tel ""
+fax ""
+language "C"
+territory ""
+revision "1.0"
+date "2015-08-10"
+%
+category "C:2015";LC_IDENTIFICATION
+category "C:2015";LC_CTYPE
+category "C:2015";LC_COLLATE
+category "C:2015";LC_TIME
+category "C:2015";LC_NUMERIC
+category "C:2015";LC_MONETARY
+category "C:2015";LC_MESSAGES
+category "C:2015";LC_PAPER
+category "C:2015";LC_NAME
+category "C:2015";LC_ADDRESS
+category "C:2015";LC_TELEPHONE
+category "C:2015";LC_MEASUREMENT
+END LC_IDENTIFICATION
+
+LC_CTYPE
+copy "i18n"
+
+translit_start
+include "translit_combining";""
+translit_end
+
+END LC_CTYPE
+
+LC_COLLATE
+order_start forward
+<U0000>
+..
+<UFFFF>
+<U10000>
+..
+<U1FFFF>
+<U20000>
+..
+<U2FFFF>
+<UE0000>
+..
+<UEFFFF>
+<UF0000>
+..
+<UFFFFF>
+<U100000>
+..
+<U10FFFF>
+UNDEFINED
+order_end
+END LC_COLLATE
+
+LC_MONETARY
+% This is the 14652 i18n fdcc-set definition for
+% the LC_MONETARY category
+% (except for the int_curr_symbol and currency_symbol, they are empty in
+% the 14652 i18n fdcc-set definition and also empty in
+% glibc/locale/C-monetary.c. But localedef complains in that case).
+%
+% Using "USD" for int_curr_symbol. But maybe "XXX" would be better?
+% XXX is "No currency" (https://en.wikipedia.org/wiki/ISO_4217)
+int_curr_symbol "<U0055><U0053><U0044><U0020>"
+% Using "$" for currency_symbol. But maybe <U00A4> would be better?
+% U+00A4 is the "generic currency symbol"
+% (https://en.wikipedia.org/wiki/Currency_sign_%28typography%29)
+currency_symbol "<U0024>"
+mon_decimal_point "<U002E>"
+mon_thousands_sep ""
+mon_grouping -1
+positive_sign ""
+negative_sign "<U002D>"
+int_frac_digits -1
+frac_digits -1
+p_cs_precedes -1
+int_p_sep_by_space -1
+p_sep_by_space -1
+n_cs_precedes -1
+int_n_sep_by_space -1
+n_sep_by_space -1
+p_sign_posn -1
+n_sign_posn -1
+%
+END LC_MONETARY
+
+LC_NUMERIC
+% This is the POSIX Locale definition for
+% the LC_NUMERIC category.
+%
+decimal_point "<U002E>"
+thousands_sep ""
+grouping -1
+END LC_NUMERIC
+
+LC_TIME
+% This is the POSIX Locale definition for
+% the LC_TIME category.
+%
+% Abbreviated weekday names (%a)
+abday "<U0053><U0075><U006E>";"<U004D><U006F><U006E>";/
+ "<U0054><U0075><U0065>";"<U0057><U0065><U0064>";/
+ "<U0054><U0068><U0075>";"<U0046><U0072><U0069>";/
+ "<U0053><U0061><U0074>"
+
+% Full weekday names (%A)
+day "<U0053><U0075><U006E><U0064><U0061><U0079>";/
+ "<U004D><U006F><U006E><U0064><U0061><U0079>";/
+ "<U0054><U0075><U0065><U0073><U0064><U0061><U0079>";/
+ "<U0057><U0065><U0064><U006E><U0065><U0073><U0064><U0061><U0079>";/
+ "<U0054><U0068><U0075><U0072><U0073><U0064><U0061><U0079>";/
+ "<U0046><U0072><U0069><U0064><U0061><U0079>";/
+ "<U0053><U0061><U0074><U0075><U0072><U0064><U0061><U0079>"
+
+% Abbreviated month names (%b)
+abmon "<U004A><U0061><U006E>";"<U0046><U0065><U0062>";/
+ "<U004D><U0061><U0072>";"<U0041><U0070><U0072>";/
+ "<U004D><U0061><U0079>";"<U004A><U0075><U006E>";/
+ "<U004A><U0075><U006C>";"<U0041><U0075><U0067>";/
+ "<U0053><U0065><U0070>";"<U004F><U0063><U0074>";/
+ "<U004E><U006F><U0076>";"<U0044><U0065><U0063>"
+
+% Full month names (%B)
+mon "<U004A><U0061><U006E><U0075><U0061><U0072><U0079>";/
+ "<U0046><U0065><U0062><U0072><U0075><U0061><U0072><U0079>";/
+ "<U004D><U0061><U0072><U0063><U0068>";/
+ "<U0041><U0070><U0072><U0069><U006C>";/
+ "<U004D><U0061><U0079>";/
+ "<U004A><U0075><U006E><U0065>";/
+ "<U004A><U0075><U006C><U0079>";/
+ "<U0041><U0075><U0067><U0075><U0073><U0074>";/
+ "<U0053><U0065><U0070><U0074><U0065><U006D><U0062><U0065><U0072>";/
+ "<U004F><U0063><U0074><U006F><U0062><U0065><U0072>";/
+ "<U004E><U006F><U0076><U0065><U006D><U0062><U0065><U0072>";/
+ "<U0044><U0065><U0063><U0065><U006D><U0062><U0065><U0072>"
+
+% Week description, consists of three fields:
+% 1. Number of days in a week.
+% 2. Gregorian date that is a first weekday (19971130 for Sunday, 19971201 for Monday).
+% 3. The weekday number to be contained in the first week of the year.
+%
+% ISO 8601 conforming applications should use the values 7, 19971201 (a
+% Monday), and 4 (Thursday), respectively.
+week 7;19971201;4
+first_weekday 1
+first_workday 1
+
+% Appropriate date and time representation (%c)
+% "%a %b %e %H:%M:%S %Y"
+d_t_fmt "<U0025><U0061><U0020><U0025><U0062><U0020><U0025><U0065><U0020><U0025><U0048><U003A><U0025><U004D><U003A><U0025><U0053><U0020><U0025><U0059>"
+
+% Appropriate date representation (%x)
+% "%m/%d/%y"
+d_fmt "<U0025><U006D><U002F><U0025><U0064><U002F><U0025><U0079>"
+
+% Appropriate time representation (%X)
+% "%H:%M:%S"
+t_fmt "<U0025><U0048><U003A><U0025><U004D><U003A><U0025><U0053>"
+
+% Appropriate AM/PM time representation (%r)
+% "%I:%M:%S %p"
+t_fmt_ampm "<U0025><U0049><U003A><U0025><U004D><U003A><U0025><U0053><U0020><U0025><U0070>"
+
+% Equivalent of AM/PM (%p) "AM"/"PM"
+%
+am_pm "<U0041><U004D>";"<U0050><U004D>"
+
+% Appropriate date representation (date(1)) "%a %b %e %H:%M:%S %Z %Y"
+date_fmt "<U0025><U0061><U0020><U0025><U0062><U0020><U0025><U0065><U0020><U0025><U0048><U003A><U0025><U004D><U003A><U0025><U0053><U0020><U0025><U005A><U0020><U0025><U0059>"
+END LC_TIME
+
+LC_MESSAGES
+% This is the POSIX Locale definition for
+% the LC_NUMERIC category.
+%
+yesexpr "<U005E><U005B><U0079><U0059><U005D>"
+noexpr "<U005E><U005B><U006E><U004E><U005D>"
+yesstr "<U0059><U0065><U0073>"
+nostr "<U004E><U006F>"
+END LC_MESSAGES
+
+LC_PAPER
+% This is the ISO/IEC 14652 "i18n" definition for
+% the LC_PAPER category.
+% (A4 paper, this is also used in the built in C/POSIX
+% locale in glibc/locale/C-paper.c)
+height 297
+width 210
+END LC_PAPER
+
+LC_NAME
+% This is the ISO/IEC 14652 "i18n" definition for
+% the LC_NAME category.
+% "%p%t%g%t%m%t%f"
+% (also used in the built in C/POSIX locale in glibc/locale/C-name.c)
+name_fmt "<U0025><U0070><U0025><U0074><U0025><U0067><U0025><U0074>/
+<U0025><U006D><U0025><U0074><U0025><U0066>"
+END LC_NAME
+
+LC_ADDRESS
+% This is the ISO/IEC 14652 "i18n" definition for
+% the LC_ADDRESS category.
+% "%a%N%f%N%d%N%b%N%s %h %e %r%N%C-%z %T%N%c%N"
+% (also used in the built in C/POSIX locale in glibc/locale/C-address.c)
+postal_fmt "<U0025><U0061><U0025><U004E><U0025><U0066><U0025><U004E>/
+<U0025><U0064><U0025><U004E><U0025><U0062><U0025><U004E><U0025><U0073>/
+<U0020><U0025><U0068><U0020><U0025><U0065><U0020><U0025><U0072><U0025>/
+<U004E><U0025><U0043><U002D><U0025><U007A><U0020><U0025><U0054><U0025>/
+<U004E><U0025><U0063><U0025><U004E>"
+END LC_ADDRESS
+
+LC_TELEPHONE
+% This is the ISO/IEC 14652 "i18n" definition for
+% the LC_TELEPHONE category.
+% "+%c %a %l"
+tel_int_fmt "<U002B><U0025><U0063><U0020><U0025><U0061><U0020><U0025>/
+<U006C>"
+% (also used in the built in C/POSIX locale in glibc/locale/C-telephone.c)
+END LC_TELEPHONE
+
+LC_MEASUREMENT
+% This is the ISO/IEC 14652 "i18n" definition for
+% the LC_MEASUREMENT category.
+% (same as in the built in C/POSIX locale in glibc/locale/C-measurement.c)
+%metric
+measurement 1
+END LC_MEASUREMENT
+
--
2.4.3

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,44 +0,0 @@
Revert the following fix temporarily:
commit c26efef9798914e208329c0e8c3c73bb1135d9e3
Author: Mel Gorman <mgorman@suse.de>
Date: Thu Apr 2 12:14:14 2015 +0530
malloc: Consistently apply trim_threshold to all heaps [BZ #17195]
because it makes an openjdk bug (#1209451) more prominent, crashing java
commands.
diff --git a/malloc/arena.c b/malloc/arena.c
index 8af51f0..d85f371 100644
--- a/malloc/arena.c
+++ b/malloc/arena.c
@@ -658,7 +658,7 @@ heap_trim (heap_info *heap, size_t pad)
unsigned long pagesz = GLRO (dl_pagesize);
mchunkptr top_chunk = top (ar_ptr), p, bck, fwd;
heap_info *prev_heap;
- long new_size, top_size, extra, prev_size, misalign;
+ long new_size, top_size, top_area, extra, prev_size, misalign;
/* Can this heap go away completely? */
while (top_chunk == chunk_at_offset (heap, sizeof (*heap)))
@@ -694,9 +694,16 @@ heap_trim (heap_info *heap, size_t pad)
set_head (top_chunk, new_size | PREV_INUSE);
/*check_chunk(ar_ptr, top_chunk);*/
}
+
+ /* Uses similar logic for per-thread arenas as the main arena with systrim
+ by preserving the top pad and at least a page. */
top_size = chunksize (top_chunk);
- extra = (top_size - pad - MINSIZE - 1) & ~(pagesz - 1);
- if (extra < (long) pagesz)
+ top_area = top_size - MINSIZE - 1;
+ if (top_area <= pad)
+ return 0;
+
+ extra = ALIGN_DOWN(top_area - pad, pagesz);
+ if ((unsigned long) extra < mp_.trim_threshold)
return 0;
/* Try to shrink. */

View File

@ -27,7 +27,7 @@ index 6078e2d..36fd50b 100644
+static-only-routines += libc_pthread_atfork
shared-only-routines = forward
libpthread-routines = nptl-init vars events version \
libpthread-routines = nptl-init vars events version pt-interp \
diff --git a/nptl/libc_pthread_atfork.c b/nptl/libc_pthread_atfork.c
new file mode 100644
index 0000000..667049a

View File

@ -1,47 +0,0 @@
commit 403ce35141da511898cde550f48ebc68a2a3ac82
Author: Siddhesh Poyarekar <siddhesh@redhat.com>
Date: Mon Jan 6 14:37:21 2014 +0530
Fix infinite loop in ftell when writing wide char data (BZ #16398)
ftell tries to avoid flushing the buffer when it is in write mode by
converting the wide char data and placing it into the binary buffer.
If the output buffer space is full and there is data to write, the
code reverts to flushing the buffer. This breaks when there is space
in the buffer but it is not enough to convert the next character in
the wide data buffer, due to which __codecvt_do_out returns a
__codecvt_partial status. In this case, ftell keeps running in an
infinite loop.
The fix here is to detect the __codecvt_partial status in addition to
checking if the buffer is full.
diff --git a/libio/wfileops.c b/libio/wfileops.c
index 87d3cdc..877fc1f 100644
--- a/libio/wfileops.c
+++ b/libio/wfileops.c
@@ -715,7 +715,7 @@ _IO_wfile_seekoff (fp, offset, dir, mode)
- fp->_wide_data->_IO_write_base) / clen;
else
{
- enum __codecvt_result status;
+ enum __codecvt_result status = __codecvt_ok;
delta = (fp->_wide_data->_IO_write_ptr
- fp->_wide_data->_IO_write_base);
const wchar_t *write_base = fp->_wide_data->_IO_write_base;
@@ -728,9 +728,12 @@ _IO_wfile_seekoff (fp, offset, dir, mode)
flush buffers for every ftell. */
do
{
- /* Ugh, no point trying to avoid the flush. Just do it
- and go back to how it was with the read mode. */
- if (delta > 0 && new_write_ptr == fp->_IO_buf_end)
+ /* There is not enough space in the buffer to do the entire
+ conversion, so there is no point trying to avoid the
+ buffer flush. Just do it and go back to how it was with
+ the read mode. */
+ if (status == __codecvt_partial
+ || (delta > 0 && new_write_ptr == fp->_IO_buf_end))
{
if (_IO_switch_to_wget_mode (fp))
return WEOF;

View File

@ -1,836 +0,0 @@
commit 03425ba6ab17b87b2c64f0d7b47fb0b86add9993
Author: Siddhesh Poyarekar <siddhesh@redhat.com>
Date: Thu Feb 20 15:41:18 2014 +0530
Separate ftell from fseek logic and avoid modifying FILE data (#16532)
ftell semantics are distinct from fseek(SEEK_CUR) especially when it
is called on a file handler that is not yet active. Due to this
caveat, much care needs to be taken while modifying the handler data
and hence, this first iteration on separating out ftell focusses on
maintaining handler data integrity at all times while it figures out
the current stream offset. The result is that it makes a syscall for
every offset request.
There is scope for optimizing this by caching offsets when we know
that the handler is active. A simple way to find out is when the
buffers have data. It is not so simple to find this out when the
buffer is empty without adding some kind of flag.
diff --git a/libio/Makefile b/libio/Makefile
index 8c333ce..8ccd80f 100644
--- a/libio/Makefile
+++ b/libio/Makefile
@@ -60,7 +60,7 @@ tests = tst_swprintf tst_wprintf tst_swscanf tst_wscanf tst_getwc tst_putwc \
tst-wmemstream1 tst-wmemstream2 \
bug-memstream1 bug-wmemstream1 \
tst-setvbuf1 tst-popen1 tst-fgetwc bug-wsetpos tst-fseek \
- tst-fwrite-error tst-ftell-partial-wide
+ tst-fwrite-error tst-ftell-partial-wide tst-ftell-active-handler
ifeq (yes,$(build-shared))
# Add test-fopenloc only if shared library is enabled since it depends on
# shared localedata objects.
diff --git a/libio/fileops.c b/libio/fileops.c
index a3499be..a177302 100644
--- a/libio/fileops.c
+++ b/libio/fileops.c
@@ -931,6 +931,59 @@ _IO_file_sync_mmap (_IO_FILE *fp)
_IO_off64_t
+get_file_offset (_IO_FILE *fp)
+{
+ if ((fp->_flags & _IO_IS_APPENDING) == _IO_IS_APPENDING)
+ {
+ struct stat64 st;
+ bool ret = (_IO_SYSSTAT (fp, &st) == 0 && S_ISREG (st.st_mode));
+ if (ret)
+ return st.st_size;
+ else
+ return EOF;
+ }
+ else
+ return _IO_SYSSEEK (fp, 0, _IO_seek_cur);
+}
+
+
+/* ftell{,o} implementation. Don't modify any state of the file pointer while
+ we try to get the current state of the stream. */
+static _IO_off64_t
+do_ftell (_IO_FILE *fp)
+{
+ _IO_off64_t result;
+
+ result = get_file_offset (fp);
+
+ if (result == EOF)
+ return result;
+
+ /* No point looking at unflushed data if we haven't allocated buffers
+ yet. */
+ if (fp->_IO_buf_base != NULL)
+ {
+ bool was_writing = (fp->_IO_write_ptr > fp->_IO_write_base
+ || _IO_in_put_mode (fp));
+
+ /* Adjust for unflushed data. */
+ if (!was_writing)
+ result -= fp->_IO_read_end - fp->_IO_read_ptr;
+ else
+ result += fp->_IO_write_ptr - fp->_IO_read_end;
+ }
+
+ if (result < 0)
+ {
+ __set_errno (EINVAL);
+ return EOF;
+ }
+
+ return result;
+}
+
+
+_IO_off64_t
_IO_new_file_seekoff (fp, offset, dir, mode)
_IO_FILE *fp;
_IO_off64_t offset;
@@ -940,6 +993,13 @@ _IO_new_file_seekoff (fp, offset, dir, mode)
_IO_off64_t result;
_IO_off64_t delta, new_offset;
long count;
+
+ /* Short-circuit into a separate function. We don't want to mix any
+ functionality and we don't want to touch anything inside the FILE
+ object. */
+ if (mode == 0)
+ return do_ftell (fp);
+
/* POSIX.1 8.2.3.7 says that after a call the fflush() the file
offset of the underlying file must be exact. */
int must_be_exact = (fp->_IO_read_base == fp->_IO_read_end
@@ -948,9 +1008,6 @@ _IO_new_file_seekoff (fp, offset, dir, mode)
bool was_writing = (fp->_IO_write_ptr > fp->_IO_write_base
|| _IO_in_put_mode (fp));
- if (mode == 0)
- dir = _IO_seek_cur, offset = 0; /* Don't move any pointers. */
-
/* Flush unwritten characters.
(This may do an unneeded write if we seek within the buffer.
But to be able to switch to reading, we would need to set
@@ -958,7 +1015,7 @@ _IO_new_file_seekoff (fp, offset, dir, mode)
which assumes file_ptr() is eGptr. Anyway, since we probably
end up flushing when we close(), it doesn't make much difference.)
FIXME: simulate mem-mapped files. */
- else if (was_writing && _IO_switch_to_get_mode (fp))
+ if (was_writing && _IO_switch_to_get_mode (fp))
return EOF;
if (fp->_IO_buf_base == NULL)
@@ -978,30 +1035,10 @@ _IO_new_file_seekoff (fp, offset, dir, mode)
{
case _IO_seek_cur:
/* Adjust for read-ahead (bytes is buffer). */
- if (mode != 0 || !was_writing)
- offset -= fp->_IO_read_end - fp->_IO_read_ptr;
- else
- {
- /* _IO_read_end coincides with fp._offset, so the actual file position
- is fp._offset - (_IO_read_end - new_write_ptr). This is fine
- even if fp._offset is not set, since fp->_IO_read_end is then at
- _IO_buf_base and this adjustment is for unbuffered output. */
- offset -= fp->_IO_read_end - fp->_IO_write_ptr;
- }
+ offset -= fp->_IO_read_end - fp->_IO_read_ptr;
if (fp->_offset == _IO_pos_BAD)
- {
- if (mode != 0)
- goto dumb;
- else
- {
- result = _IO_SYSSEEK (fp, 0, dir);
- if (result == EOF)
- return result;
-
- fp->_offset = result;
- }
- }
+ goto dumb;
/* Make offset absolute, assuming current pointer is file_ptr(). */
offset += fp->_offset;
if (offset < 0)
@@ -1028,10 +1065,6 @@ _IO_new_file_seekoff (fp, offset, dir, mode)
}
/* At this point, dir==_IO_seek_set. */
- /* If we are only interested in the current position we've found it now. */
- if (mode == 0)
- return offset;
-
/* If destination is within current buffer, optimize: */
if (fp->_offset != _IO_pos_BAD && fp->_IO_read_base != NULL
&& !_IO_in_backup (fp))
diff --git a/libio/libioP.h b/libio/libioP.h
index 4ca723c..8a7b85b 100644
--- a/libio/libioP.h
+++ b/libio/libioP.h
@@ -397,6 +397,7 @@ extern void _IO_wdoallocbuf (_IO_FILE *) __THROW;
libc_hidden_proto (_IO_wdoallocbuf)
extern void _IO_unsave_wmarkers (_IO_FILE *) __THROW;
extern unsigned _IO_adjust_wcolumn (unsigned, const wchar_t *, int) __THROW;
+extern _IO_off64_t get_file_offset (_IO_FILE *fp);
/* Marker-related function. */
diff --git a/libio/tst-ftell-active-handler.c b/libio/tst-ftell-active-handler.c
new file mode 100644
index 0000000..aac2923
--- /dev/null
+++ b/libio/tst-ftell-active-handler.c
@@ -0,0 +1,366 @@
+/* Verify that ftell returns the correct value at various points before and
+ after the handler on which it is called becomes active.
+ Copyright (C) 2014 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
+ <http://www.gnu.org/licenses/>. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <locale.h>
+#include <wchar.h>
+
+static int do_test (void);
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
+
+#define get_handles_fdopen(filename, fd, fp, fd_mode, mode) \
+({ \
+ int ret = 0; \
+ (fd) = open ((filename), (fd_mode), 0); \
+ if ((fd) == -1) \
+ { \
+ printf ("open failed: %m\n"); \
+ ret = 1; \
+ } \
+ else \
+ { \
+ (fp) = fdopen ((fd), (mode)); \
+ if ((fp) == NULL) \
+ { \
+ printf ("fdopen failed: %m\n"); \
+ close (fd); \
+ ret = 1; \
+ } \
+ } \
+ ret; \
+})
+
+#define get_handles_fopen(filename, fd, fp, mode) \
+({ \
+ int ret = 0; \
+ (fp) = fopen ((filename), (mode)); \
+ if ((fp) == NULL) \
+ { \
+ printf ("fopen failed: %m\n"); \
+ ret = 1; \
+ } \
+ else \
+ { \
+ (fd) = fileno (fp); \
+ if ((fd) == -1) \
+ { \
+ printf ("fileno failed: %m\n"); \
+ ret = 1; \
+ } \
+ } \
+ ret; \
+})
+
+static const void *data;
+static const char *char_data = "abcdef";
+static const wchar_t *wide_data = L"abcdef";
+static size_t data_len;
+/* Maintain the current file length for validation. */
+static size_t file_len;
+
+typedef int (*fputs_func_t) (const void *data, FILE *fp);
+fputs_func_t fputs_func;
+
+/* Test that the value of ftell is not cached when the stream handle is not
+ active. */
+static int
+do_ftell_test (const char *filename)
+{
+ int ret = 0;
+ struct test
+ {
+ const char *mode;
+ int fd_mode;
+ size_t old_off;
+ size_t new_off;
+ } test_modes[] = {
+ {"w", O_WRONLY, 0, data_len},
+ {"w+", O_RDWR, 0, data_len},
+ {"r+", O_RDWR, 0, data_len},
+ {"a", O_WRONLY, data_len, 2 * data_len},
+ {"a+", O_RDWR, 2 * data_len, 3 * data_len},
+ };
+ for (int j = 0; j < 2; j++)
+ {
+ for (int i = 0; i < sizeof (test_modes) / sizeof (struct test); i++)
+ {
+ FILE *fp;
+ int fd;
+ printf ("\tftell: %s (file, \"%s\"): ", j == 0 ? "fdopen" : "fopen",
+ test_modes[i].mode);
+
+ if (j == 0)
+ ret = get_handles_fdopen (filename, fd, fp, test_modes[i].fd_mode,
+ test_modes[i].mode);
+ else
+ ret = get_handles_fopen (filename, fd, fp, test_modes[i].mode);
+
+ if (ret != 0)
+ return 1;
+
+ long off = ftell (fp);
+ if (off != test_modes[i].old_off)
+ {
+ printf ("Incorrect old offset. Expected %zu but got %ld, ",
+ test_modes[i].old_off, off);
+ ret |= 1;
+ }
+ else
+ printf ("old offset = %ld, ", off);
+
+ int ret = write (fd, data, data_len);
+ off = ftell (fp);
+
+ if (off != test_modes[i].new_off)
+ {
+ printf ("Incorrect new offset. Expected %zu but got %ld\n",
+ test_modes[i].old_off, off);
+ ret |= 1;
+ }
+ else
+ printf ("new offset = %ld\n", off);
+
+ fclose (fp);
+ }
+ }
+
+ return ret;
+}
+
+/* This test opens the file for writing, moves the file offset of the
+ underlying file, writes out data and then checks if ftell trips on it. */
+static int
+do_write_test (const char *filename)
+{
+ FILE *fp = NULL;
+ int fd;
+ int ret = 0;
+ struct test
+ {
+ const char *mode;
+ int fd_mode;
+ } test_modes[] = {
+ {"w", O_WRONLY},
+ {"w+", O_RDWR},
+ {"r+", O_RDWR}
+ };
+
+ for (int j = 0; j < 2; j++)
+ {
+ for (int i = 0; i < sizeof (test_modes) / sizeof (struct test); i++)
+ {
+ printf ("\twrite: %s (file, \"%s\"): ", j == 0 ? "fopen" : "fdopen",
+ test_modes[i].mode);
+
+ if (j == 0)
+ ret = get_handles_fopen (filename, fd, fp, test_modes[i].mode);
+ else
+ ret = get_handles_fdopen (filename, fd, fp, test_modes[i].fd_mode,
+ test_modes[i].mode);
+
+ if (ret != 0)
+ return ret;
+
+ /* Move offset to just before the end of the file. */
+ off_t ret = lseek (fd, file_len - 1, SEEK_SET);
+ if (ret == -1)
+ {
+ printf ("lseek failed: %m\n");
+ ret |= 1;
+ }
+
+ /* Write some data. */
+ size_t written = fputs_func (data, fp);
+
+ if (written == EOF)
+ {
+ printf ("fputs[1] failed to write data\n");
+ ret |= 1;
+ }
+
+ /* Verify that the offset points to the end of the file. */
+ long offset = ftell (fp);
+ file_len = file_len - 1 + data_len;
+
+ if (offset != file_len)
+ {
+ printf ("Incorrect offset. Expected %zu, but got %ld\n",
+ file_len, offset);
+
+ ret |= 1;
+ }
+
+ printf ("offset = %ld\n", offset);
+ fclose (fp);
+ }
+ }
+
+ return ret;
+}
+
+/* This test opens a file in append mode, writes some data, and then verifies
+ that ftell does not trip over it. */
+static int
+do_append_test (const char *filename)
+{
+ FILE *fp = NULL;
+ int ret = 0;
+ int fd;
+
+ struct test
+ {
+ const char *mode;
+ int fd_mode;
+ } test_modes[] = {
+ {"a", O_WRONLY},
+ {"a+", O_RDWR}
+ };
+
+ for (int j = 0; j < 2; j++)
+ {
+ for (int i = 0; i < sizeof (test_modes) / sizeof (struct test); i++)
+ {
+ printf ("\tappend: %s (file, \"%s\"): ", j == 0 ? "fopen" : "fdopen",
+ test_modes[i].mode);
+
+ if (j == 0)
+ ret = get_handles_fopen (filename, fd, fp, test_modes[i].mode);
+ else
+ ret = get_handles_fdopen (filename, fd, fp, test_modes[i].fd_mode,
+ test_modes[i].mode);
+
+ if (ret != 0)
+ return ret;
+
+ /* Write some data. */
+ size_t written = fputs_func (data, fp);
+
+ if (written == EOF)
+ {
+ printf ("fputs[1] failed to write all data\n");
+ ret |= 1;
+ }
+
+ /* Verify that the offset points to the end of the file. */
+ long offset = ftell (fp);
+ file_len += data_len;
+
+ if (offset != file_len)
+ {
+ printf ("Incorrect offset. Expected %zu, but got %ld\n",
+ file_len, offset);
+
+ ret |= 1;
+ }
+
+ printf ("offset = %ld\n", offset);
+ fclose (fp);
+ }
+ }
+
+ return ret;
+}
+
+static int
+do_one_test (const char *filename)
+{
+ int ret = 0;
+
+ ret |= do_ftell_test (filename);
+ ret |= do_write_test (filename);
+ ret |= do_append_test (filename);
+
+ return ret;
+}
+
+static int
+do_test (void)
+{
+ int ret = 0;
+ FILE *fp = NULL;
+ char *filename;
+ size_t written;
+ int fd = create_temp_file ("tst-active-handler-tmp.", &filename);
+
+ if (fd == -1)
+ {
+ printf ("create_temp_file: %m\n");
+ return 1;
+ }
+
+ fp = fdopen (fd, "w");
+ if (fp == NULL)
+ {
+ printf ("fdopen[0]: %m\n");
+ close (fd);
+ return 1;
+ }
+
+ data = char_data;
+ data_len = strlen (char_data);
+ file_len = strlen (char_data);
+ written = fputs (data, fp);
+
+ if (written == EOF)
+ {
+ printf ("fputs[1] failed to write data\n");
+ ret = 1;
+ }
+
+ fclose (fp);
+ if (ret)
+ return ret;
+
+ /* Tests for regular files. */
+ puts ("Regular mode:");
+ fputs_func = (fputs_func_t) fputs;
+ data = char_data;
+ data_len = strlen (char_data);
+ ret |= do_one_test (filename);
+
+ /* Truncate the file before repeating the tests in wide mode. */
+ fp = fopen (filename, "w");
+ if (fp == NULL)
+ {
+ printf ("fopen failed %m\n");
+ return 1;
+ }
+ fclose (fp);
+
+ /* Tests for wide files. */
+ puts ("Wide mode:");
+ if (setlocale (LC_ALL, "en_US.UTF-8") == NULL)
+ {
+ printf ("Cannot set en_US.UTF-8 locale.\n");
+ return 1;
+ }
+ fputs_func = (fputs_func_t) fputws;
+ data = wide_data;
+ data_len = wcslen (wide_data);
+ ret |= do_one_test (filename);
+
+ return ret;
+}
diff --git a/libio/wfileops.c b/libio/wfileops.c
index 9cebe77..eda7828 100644
--- a/libio/wfileops.c
+++ b/libio/wfileops.c
@@ -596,29 +596,22 @@ done:
return 0;
}
-_IO_off64_t
-_IO_wfile_seekoff (fp, offset, dir, mode)
- _IO_FILE *fp;
- _IO_off64_t offset;
- int dir;
- int mode;
+static _IO_off64_t
+do_ftell_wide (_IO_FILE *fp)
{
- _IO_off64_t result;
- _IO_off64_t delta, new_offset;
- long int count;
- /* POSIX.1 8.2.3.7 says that after a call the fflush() the file
- offset of the underlying file must be exact. */
- int must_be_exact = ((fp->_wide_data->_IO_read_base
- == fp->_wide_data->_IO_read_end)
- && (fp->_wide_data->_IO_write_base
- == fp->_wide_data->_IO_write_ptr));
+ _IO_off64_t result, offset = 0;
- bool was_writing = ((fp->_wide_data->_IO_write_ptr
- > fp->_wide_data->_IO_write_base)
- || _IO_in_put_mode (fp));
-
- if (mode == 0)
+ /* No point looking for offsets in the buffer if it hasn't even been
+ allocated. */
+ if (fp->_wide_data->_IO_buf_base != NULL)
{
+ const wchar_t *wide_read_base;
+ const wchar_t *wide_read_ptr;
+ const wchar_t *wide_read_end;
+ bool was_writing = ((fp->_wide_data->_IO_write_ptr
+ > fp->_wide_data->_IO_write_base)
+ || _IO_in_put_mode (fp));
+
/* XXX For wide stream with backup store it is not very
reasonable to determine the offset. The pushed-back
character might require a state change and we need not be
@@ -633,14 +626,117 @@ _IO_wfile_seekoff (fp, offset, dir, mode)
return -1;
}
- /* There is no more data in the backup buffer. We can
- switch back. */
- _IO_switch_to_main_wget_area (fp);
+ /* Nothing in the backup store, so note the backed up pointers
+ without changing the state. */
+ wide_read_base = fp->_wide_data->_IO_save_base;
+ wide_read_ptr = wide_read_base;
+ wide_read_end = fp->_wide_data->_IO_save_end;
+ }
+ else
+ {
+ wide_read_base = fp->_wide_data->_IO_read_base;
+ wide_read_ptr = fp->_wide_data->_IO_read_ptr;
+ wide_read_end = fp->_wide_data->_IO_read_end;
}
- dir = _IO_seek_cur, offset = 0; /* Don't move any pointers. */
+ struct _IO_codecvt *cv = fp->_codecvt;
+ int clen = (*cv->__codecvt_do_encoding) (cv);
+
+ if (!was_writing)
+ {
+ if (clen > 0)
+ {
+ offset -= (wide_read_end - wide_read_ptr) * clen;
+ offset -= fp->_IO_read_end - fp->_IO_read_ptr;
+ }
+ else
+ {
+ int nread;
+
+ size_t delta = wide_read_ptr - wide_read_base;
+ __mbstate_t state = fp->_wide_data->_IO_last_state;
+ nread = (*cv->__codecvt_do_length) (cv, &state,
+ fp->_IO_read_base,
+ fp->_IO_read_end, delta);
+ offset -= fp->_IO_read_end - fp->_IO_read_base - nread;
+ }
+ }
+ else
+ {
+ if (clen > 0)
+ offset += (fp->_wide_data->_IO_write_ptr
+ - fp->_wide_data->_IO_write_base) * clen;
+ else
+ {
+ size_t delta = (fp->_wide_data->_IO_write_ptr
+ - fp->_wide_data->_IO_write_base);
+
+ /* Allocate enough space for the conversion. */
+ size_t outsize = delta * sizeof (wchar_t);
+ char *out = malloc (outsize);
+ char *outstop = out;
+ const wchar_t *in = fp->_wide_data->_IO_write_base;
+
+ enum __codecvt_result status;
+
+ __mbstate_t state = fp->_wide_data->_IO_last_state;
+ status = (*cv->__codecvt_do_out) (cv, &state,
+ in, in + delta, &in,
+ out, out + outsize, &outstop);
+
+ /* We don't check for __codecvt_partial because it can be
+ returned on one of two conditions: either the output
+ buffer is full or the input sequence is incomplete. We
+ take care to allocate enough buffer and our input
+ sequences must be complete since they are accepted as
+ wchar_t; if not, then that is an error. */
+ if (__glibc_unlikely (status != __codecvt_ok))
+ return WEOF;
+
+ offset += outstop - out;
+ }
+
+ /* _IO_read_end coincides with fp._offset, so the actual file position
+ is fp._offset - (_IO_read_end - new_write_ptr). */
+ offset -= fp->_IO_read_end - fp->_IO_write_ptr;
+ }
}
+ result = get_file_offset (fp);
+
+ if (result == EOF)
+ return result;
+
+ result += offset;
+
+ return result;
+}
+
+_IO_off64_t
+_IO_wfile_seekoff (fp, offset, dir, mode)
+ _IO_FILE *fp;
+ _IO_off64_t offset;
+ int dir;
+ int mode;
+{
+ _IO_off64_t result;
+ _IO_off64_t delta, new_offset;
+ long int count;
+
+ if (mode == 0)
+ return do_ftell_wide (fp);
+
+ /* POSIX.1 8.2.3.7 says that after a call the fflush() the file
+ offset of the underlying file must be exact. */
+ int must_be_exact = ((fp->_wide_data->_IO_read_base
+ == fp->_wide_data->_IO_read_end)
+ && (fp->_wide_data->_IO_write_base
+ == fp->_wide_data->_IO_write_ptr));
+
+ bool was_writing = ((fp->_wide_data->_IO_write_ptr
+ > fp->_wide_data->_IO_write_base)
+ || _IO_in_put_mode (fp));
+
/* Flush unwritten characters.
(This may do an unneeded write if we seek within the buffer.
But to be able to switch to reading, we would need to set
@@ -648,7 +744,7 @@ _IO_wfile_seekoff (fp, offset, dir, mode)
which assumes file_ptr() is eGptr. Anyway, since we probably
end up flushing when we close(), it doesn't make much difference.)
FIXME: simulate mem-mapped files. */
- else if (was_writing && _IO_switch_to_wget_mode (fp))
+ if (was_writing && _IO_switch_to_wget_mode (fp))
return WEOF;
if (fp->_wide_data->_IO_buf_base == NULL)
@@ -693,7 +789,6 @@ _IO_wfile_seekoff (fp, offset, dir, mode)
{
int nread;
- flushed:
delta = (fp->_wide_data->_IO_read_ptr
- fp->_wide_data->_IO_read_base);
fp->_wide_data->_IO_state = fp->_wide_data->_IO_last_state;
@@ -706,80 +801,9 @@ _IO_wfile_seekoff (fp, offset, dir, mode)
offset -= fp->_IO_read_end - fp->_IO_read_base - nread;
}
}
- else
- {
- char *new_write_ptr = fp->_IO_write_ptr;
-
- if (clen > 0)
- offset += (fp->_wide_data->_IO_write_ptr
- - fp->_wide_data->_IO_write_base) / clen;
- else
- {
- enum __codecvt_result status = __codecvt_ok;
- delta = (fp->_wide_data->_IO_write_ptr
- - fp->_wide_data->_IO_write_base);
- const wchar_t *write_base = fp->_wide_data->_IO_write_base;
-
- /* FIXME: This actually ends up in two iterations of conversion,
- one here and the next when the buffer actually gets flushed.
- It may be possible to optimize this in future so that
- wdo_write identifies already converted content and does not
- redo it. In any case, this is much better than having to
- flush buffers for every ftell. */
- do
- {
- /* There is not enough space in the buffer to do the entire
- conversion, so there is no point trying to avoid the
- buffer flush. Just do it and go back to how it was with
- the read mode. */
- if (status == __codecvt_partial
- || (delta > 0 && new_write_ptr == fp->_IO_buf_end))
- {
- if (_IO_switch_to_wget_mode (fp))
- return WEOF;
- goto flushed;
- }
-
- const wchar_t *new_wbase = fp->_wide_data->_IO_write_base;
- fp->_wide_data->_IO_state = fp->_wide_data->_IO_last_state;
- status = (*cv->__codecvt_do_out) (cv,
- &fp->_wide_data->_IO_state,
- write_base,
- write_base + delta,
- &new_wbase,
- new_write_ptr,
- fp->_IO_buf_end,
- &new_write_ptr);
-
- delta -= new_wbase - write_base;
-
- /* If there was an error, then return WEOF.
- TODO: set buffer state. */
- if (__glibc_unlikely (status == __codecvt_error))
- return WEOF;
- }
- while (delta > 0);
- }
-
- /* _IO_read_end coincides with fp._offset, so the actual file position
- is fp._offset - (_IO_read_end - new_write_ptr). This is fine
- even if fp._offset is not set, since fp->_IO_read_end is then at
- _IO_buf_base and this adjustment is for unbuffered output. */
- offset -= fp->_IO_read_end - new_write_ptr;
- }
if (fp->_offset == _IO_pos_BAD)
- {
- if (mode != 0)
- goto dumb;
- else
- {
- result = _IO_SYSSEEK (fp, 0, dir);
- if (result == EOF)
- return result;
- fp->_offset = result;
- }
- }
+ goto dumb;
/* Make offset absolute, assuming current pointer is file_ptr(). */
offset += fp->_offset;
@@ -802,10 +826,6 @@ _IO_wfile_seekoff (fp, offset, dir, mode)
}
/* At this point, dir==_IO_seek_set. */
- /* If we are only interested in the current position we've found it now. */
- if (mode == 0)
- return offset;
-
/* If destination is within current buffer, optimize: */
if (fp->_offset != _IO_pos_BAD && fp->_IO_read_base != NULL
&& !_IO_in_backup (fp))

View File

@ -1,183 +0,0 @@
commit 4a68e8ded4fef2b00fbfc6baf1e79e46389871ca
Author: Siddhesh Poyarekar <siddhesh@redhat.com>
Date: Thu Feb 20 15:55:16 2014 +0530
Use cached offset in ftell when reliable
The cached offset is reliable to use in ftell when the stream handle
is active. We can consider a stream as being active when there is
unbuffered data. However, even in this case, we can use the cached
offset only when the stream is not being written to in a+ mode,
because this case may have unbuffered data and a stale offset; the
previous read could have sent it off somewhere other than the end of
the file.
There were a couple of adjustments necessary to get this to work.
Firstly, fdopen now ceases to use _IO_attach_fd because it sets the
offset cache to the current file position. This is not correct
because there could be changes to the file descriptor before the
stream handle is activated, which would not get reflected.
A similar offset caching action is done in _IO_fwide, claiming that
wide streams have 'problems' with the file offsets. There don't seem
to be any obvious problems with not having the offset cache available,
other than that it will have to be queried in a subsequent
read/write/seek. I have removed this as well.
The testsuite passes successfully with these changes on x86_64.
diff --git a/libio/fileops.c b/libio/fileops.c
index a177302..c44a5da 100644
--- a/libio/fileops.c
+++ b/libio/fileops.c
@@ -952,12 +952,8 @@ get_file_offset (_IO_FILE *fp)
static _IO_off64_t
do_ftell (_IO_FILE *fp)
{
- _IO_off64_t result;
-
- result = get_file_offset (fp);
-
- if (result == EOF)
- return result;
+ _IO_off64_t result = 0;
+ bool use_cached_offset = false;
/* No point looking at unflushed data if we haven't allocated buffers
yet. */
@@ -971,8 +967,34 @@ do_ftell (_IO_FILE *fp)
result -= fp->_IO_read_end - fp->_IO_read_ptr;
else
result += fp->_IO_write_ptr - fp->_IO_read_end;
+
+ /* It is safe to use the cached offset when available if there is
+ unbuffered data (indicating that the file handle is active) and the
+ handle is not for a file open in a+ mode. The latter condition is
+ because there could be a scenario where there is a switch from read
+ mode to write mode using an fseek to an arbitrary position. In this
+ case, there would be unbuffered data due to be appended to the end of
+ the file, but the offset may not necessarily be the end of the
+ file. It is fine to use the cached offset when the a+ stream is in
+ read mode though, since the offset is maintained correctly in that
+ case. Note that this is not a comprehensive set of cases when the
+ offset is reliable. The offset may be reliable even in some cases
+ where there is no buffered input and the handle is active, but it's
+ just that we don't have a way to identify that condition reliably. */
+ use_cached_offset = (result != 0 && fp->_offset != _IO_pos_BAD
+ && ((fp->_flags & (_IO_IS_APPENDING | _IO_NO_READS))
+ == (_IO_IS_APPENDING | _IO_NO_READS)
+ && was_writing));
}
+ if (use_cached_offset)
+ result += fp->_offset;
+ else
+ result += get_file_offset (fp);
+
+ if (result == EOF)
+ return result;
+
if (result < 0)
{
__set_errno (EINVAL);
diff --git a/libio/iofdopen.c b/libio/iofdopen.c
index 066ff19..4525f0f 100644
--- a/libio/iofdopen.c
+++ b/libio/iofdopen.c
@@ -141,9 +141,6 @@ _IO_new_fdopen (fd, mode)
#ifdef _IO_MTSAFE_IO
new_f->fp.file._lock = &new_f->lock;
#endif
- /* Set up initially to use the `maybe_mmap' jump tables rather than using
- __fopen_maybe_mmap to do it, because we need them in place before we
- call _IO_file_attach or else it will allocate a buffer immediately. */
_IO_no_init (&new_f->fp.file, 0, 0, &new_f->wd,
#ifdef _G_HAVE_MMAP
(use_mmap && (read_write & _IO_NO_WRITES))
@@ -159,13 +156,10 @@ _IO_new_fdopen (fd, mode)
#if !_IO_UNIFIED_JUMPTABLES
new_f->fp.vtable = NULL;
#endif
- if (_IO_file_attach ((_IO_FILE *) &new_f->fp, fd) == NULL)
- {
- _IO_setb (&new_f->fp.file, NULL, NULL, 0);
- _IO_un_link (&new_f->fp);
- free (new_f);
- return NULL;
- }
+ /* We only record the fd because _IO_file_init will have unset the offset.
+ We don't need to get the current offset in the file now since it could
+ change between now and when the handle is activated. */
+ new_f->fp.file._fileno = fd;
new_f->fp.file._flags &= ~_IO_DELETE_DONT_CLOSE;
_IO_mask_flags (&new_f->fp.file, read_write,
diff --git a/libio/iofwide.c b/libio/iofwide.c
index 5cff632..64187e4 100644
--- a/libio/iofwide.c
+++ b/libio/iofwide.c
@@ -199,12 +199,6 @@ _IO_fwide (fp, mode)
/* From now on use the wide character callback functions. */
((struct _IO_FILE_plus *) fp)->vtable = fp->_wide_data->_wide_vtable;
-
- /* One last twist: we get the current stream position. The wide
- char streams have much more problems with not knowing the
- current position and so we should disable the optimization
- which allows the functions without knowing the position. */
- fp->_offset = _IO_SYSSEEK (fp, 0, _IO_seek_cur);
}
/* Set the mode now. */
diff --git a/libio/wfileops.c b/libio/wfileops.c
index eda7828..651f5ce 100644
--- a/libio/wfileops.c
+++ b/libio/wfileops.c
@@ -600,6 +600,7 @@ static _IO_off64_t
do_ftell_wide (_IO_FILE *fp)
{
_IO_off64_t result, offset = 0;
+ bool use_cached_offset = false;
/* No point looking for offsets in the buffer if it hasn't even been
allocated. */
@@ -696,13 +697,36 @@ do_ftell_wide (_IO_FILE *fp)
offset += outstop - out;
}
- /* _IO_read_end coincides with fp._offset, so the actual file position
- is fp._offset - (_IO_read_end - new_write_ptr). */
+ /* _IO_read_end coincides with fp._offset, so the actual file
+ position is fp._offset - (_IO_read_end - new_write_ptr). */
offset -= fp->_IO_read_end - fp->_IO_write_ptr;
+
}
+
+ /* It is safe to use the cached offset when available if there is
+ unbuffered data (indicating that the file handle is active) and
+ the handle is not for a file open in a+ mode. The latter
+ condition is because there could be a scenario where there is a
+ switch from read mode to write mode using an fseek to an arbitrary
+ position. In this case, there would be unbuffered data due to be
+ appended to the end of the file, but the offset may not
+ necessarily be the end of the file. It is fine to use the cached
+ offset when the a+ stream is in read mode though, since the offset
+ is maintained correctly in that case. Note that this is not a
+ comprehensive set of cases when the offset is reliable. The
+ offset may be reliable even in some cases where there is no
+ buffered input and the handle is active, but it's just that we
+ don't have a way to identify that condition reliably. */
+ use_cached_offset = (offset != 0 && fp->_offset != _IO_pos_BAD
+ && ((fp->_flags & (_IO_IS_APPENDING | _IO_NO_READS))
+ == (_IO_IS_APPENDING | _IO_NO_READS)
+ && was_writing));
}
- result = get_file_offset (fp);
+ if (use_cached_offset)
+ result = fp->_offset;
+ else
+ result = get_file_offset (fp);
if (result == EOF)
return result;

47
glibc-rh1114591.patch Normal file
View File

@ -0,0 +1,47 @@
Upstream patch:
commit ff889b196575c2fbf6aa7130abb1ec862714ea4e
Author: Florian Weimer <fweimer@redhat.com>
Date: Fri Feb 19 14:21:34 2016 +0100
Remove trailing newline from date_fmt in Serbian locales [BZ #19581]
diff --git a/localedata/locales/sr_ME b/localedata/locales/sr_ME
index 4f243dc..dd68df8 100644
--- a/localedata/locales/sr_ME
+++ b/localedata/locales/sr_ME
@@ -119,7 +119,7 @@ am_pm "";""
t_fmt_ampm "<U0025><U0054>"
date_fmt "<U0025><U0061><U002c><U0020><U0025><U0065><U002E><U0020>/
<U0025><U0062><U0020><U0025><U0059><U002E><U0020><U0020><U0025><U0048>/
-<U003A><U0025><U004D><U003A><U0025><U0053><U0020><U0025><U005A><U000A>"
+<U003A><U0025><U004D><U003A><U0025><U0053><U0020><U0025><U005A>"
week 7;19971130;4
first_weekday 2
first_workday 2
diff --git a/localedata/locales/sr_RS b/localedata/locales/sr_RS
index 2ae085b..ffea86f 100644
--- a/localedata/locales/sr_RS
+++ b/localedata/locales/sr_RS
@@ -300,7 +300,7 @@ am_pm "";""
t_fmt_ampm "<U0025><U0054>"
date_fmt "<U0025><U0061><U002C><U0020><U0025><U0065><U002E><U0020>/
<U0025><U0062><U0020><U0025><U0059><U002E><U0020><U0020><U0025><U0048>/
-<U003A><U0025><U004D><U003A><U0025><U0053><U0020><U0025><U005A><U000A>"
+<U003A><U0025><U004D><U003A><U0025><U0053><U0020><U0025><U005A>"
week 7;19971130;4
first_weekday 2
first_workday 2
diff --git a/localedata/locales/sr_RS@latin b/localedata/locales/sr_RS@latin
index da6628b..fd10ea6 100644
--- a/localedata/locales/sr_RS@latin
+++ b/localedata/locales/sr_RS@latin
@@ -120,7 +120,7 @@ am_pm "";""
t_fmt_ampm "<U0025><U0054>"
date_fmt "<U0025><U0061><U002c><U0020><U0025><U0065><U002E><U0020>/
<U0025><U0062><U0020><U0025><U0059><U002E><U0020><U0020><U0025><U0048>/
-<U003A><U0025><U004D><U003A><U0025><U0053><U0020><U0025><U005A><U000A>"
+<U003A><U0025><U004D><U003A><U0025><U0053><U0020><U0025><U005A>"
week 7;19971130;4
first_weekday 2
first_workday 2

29
glibc-rh1204521.patch Normal file
View File

@ -0,0 +1,29 @@
Partial backport of upstream commit 0a410e76f551c6e6cf6d128f618208049d6a952c
(localedata: CLDRv29: update LC_TIME week/first_week,workday fields).
Index: b/localedata/locales/fr_CH
===================================================================
--- a/localedata/locales/fr_CH
+++ b/localedata/locales/fr_CH
@@ -104,6 +104,8 @@ t_fmt_ampm ""
date_fmt "<U0025><U0061><U0020><U0025><U0062><U0020><U0025><U0065>/
<U0020><U0025><U0048><U003A><U0025><U004D><U003A><U0025><U0053><U0020>/
<U0025><U005A><U0020><U0025><U0059>"
+week 7;19971130;4
+first_weekday 2
END LC_TIME
LC_PAPER
Index: b/localedata/locales/it_CH
===================================================================
--- a/localedata/locales/it_CH
+++ b/localedata/locales/it_CH
@@ -99,6 +99,8 @@ t_fmt_ampm ""
date_fmt "<U0025><U0061><U0020><U0025><U0065><U0020><U0025>/
<U0062><U0020><U0025><U0059><U002C><U0020><U0025><U0048><U002E>/
<U0025><U004D><U002E><U0025><U0053><U002C><U0020><U0025><U005A>"
+week 7;19971130;4
+first_weekday 2
END LC_TIME
LC_PAPER

417
glibc-rh1252570.patch Normal file
View File

@ -0,0 +1,417 @@
Revert this upstream commit:
commit 2212c1420c92a33b0e0bd9a34938c9814a56c0f7
Author: Andreas Schwab <schwab@suse.de>
Date: Thu Feb 19 15:52:08 2015 +0100
Simplify handling of nameserver configuration in resolver
Remove use of ext.nsmap member of struct __res_state and always use
an identity mapping betwen the nsaddr_list array and the ext.nsaddrs
array. The fact that a nameserver has an IPv6 address is signalled by
setting nsaddr_list[].sin_family to zero.
reverted:
--- b/resolv/res_init.c
+++ a/resolv/res_init.c
@@ -153,8 +153,10 @@
char *cp, **pp;
int n;
char buf[BUFSIZ];
+ int nserv = 0; /* number of IPv4 nameservers read from file */
+#ifdef _LIBC
+ int nservall = 0; /* number of (IPv4 + IPV6) nameservers read from file */
+#endif
- int nserv = 0; /* number of nameservers read from file */
- int have_serv6 = 0;
int haveenv = 0;
int havesearch = 0;
#ifdef RESOLVSORT
@@ -182,9 +184,15 @@
statp->_flags = 0;
statp->qhook = NULL;
statp->rhook = NULL;
+ statp->_u._ext.nsinit = 0;
statp->_u._ext.nscount = 0;
+#ifdef _LIBC
+ statp->_u._ext.nscount6 = 0;
+ for (n = 0; n < MAXNS; n++) {
+ statp->_u._ext.nsaddrs[n] = NULL;
+ statp->_u._ext.nsmap[n] = MAXNS;
+ }
+#endif
- for (n = 0; n < MAXNS; n++)
- statp->_u._ext.nsaddrs[n] = NULL;
/* Allow user to override the local domain definition */
if ((cp = getenv("LOCALDOMAIN")) != NULL) {
@@ -288,7 +296,11 @@
continue;
}
/* read nameservers to query */
+#ifdef _LIBC
+ if (MATCH(buf, "nameserver") && nservall < MAXNS) {
+#else
if (MATCH(buf, "nameserver") && nserv < MAXNS) {
+#endif
struct in_addr a;
cp = buf + sizeof("nameserver") - 1;
@@ -296,12 +308,13 @@
cp++;
if ((*cp != '\0') && (*cp != '\n')
&& __inet_aton(cp, &a)) {
+ statp->nsaddr_list[nservall].sin_addr = a;
+ statp->nsaddr_list[nservall].sin_family = AF_INET;
+ statp->nsaddr_list[nservall].sin_port =
- statp->nsaddr_list[nserv].sin_addr = a;
- statp->nsaddr_list[nserv].sin_family = AF_INET;
- statp->nsaddr_list[nserv].sin_port =
htons(NAMESERVER_PORT);
nserv++;
#ifdef _LIBC
+ nservall++;
} else {
struct in6_addr a6;
char *el;
@@ -343,11 +356,10 @@
}
}
+ statp->_u._ext.nsaddrs[nservall] = sa6;
+ statp->_u._ext.nssocks[nservall] = -1;
+ statp->_u._ext.nsmap[nservall] = MAXNS + 1;
+ nservall++;
- statp->nsaddr_list[nserv].sin_family = 0;
- statp->_u._ext.nsaddrs[nserv] = sa6;
- statp->_u._ext.nssocks[nserv] = -1;
- have_serv6 = 1;
- nserv++;
}
}
#endif
@@ -402,9 +414,10 @@
continue;
}
}
+ statp->nscount = nservall;
- statp->nscount = nserv;
#ifdef _LIBC
+ if (nservall - nserv > 0) {
+ statp->_u._ext.nscount6 = nservall - nserv;
- if (have_serv6) {
/* We try IPv6 servers again. */
statp->ipv6_unavail = false;
}
@@ -593,7 +606,11 @@
statp->_vcsock = -1;
statp->_flags &= ~(RES_F_VC | RES_F_CONN);
}
+#ifdef _LIBC
+ for (ns = 0; ns < MAXNS; ns++)
+#else
for (ns = 0; ns < statp->_u._ext.nscount; ns++)
+#endif
if (statp->_u._ext.nsaddrs[ns]) {
if (statp->_u._ext.nssocks[ns] != -1) {
close_not_cancel_no_status(statp->_u._ext.nssocks[ns]);
@@ -604,6 +621,8 @@
statp->_u._ext.nsaddrs[ns] = NULL;
}
}
+ if (free_addr)
+ statp->_u._ext.nsinit = 0;
}
libc_hidden_def (__res_iclose)
reverted:
--- b/resolv/res_send.c
+++ a/resolv/res_send.c
@@ -184,7 +184,6 @@
/* Forward. */
-static struct sockaddr *get_nsaddr (res_state, int);
static int send_vc(res_state, const u_char *, int,
const u_char *, int,
u_char **, int *, int *, int, u_char **,
@@ -222,21 +221,20 @@
in_port_t port = in4p->sin_port;
in_addr_t addr = in4p->sin_addr.s_addr;
+ for (ns = 0; ns < MAXNS; ns++) {
- for (ns = 0; ns < statp->nscount; ns++) {
const struct sockaddr_in *srv =
+ (struct sockaddr_in *)EXT(statp).nsaddrs[ns];
- (struct sockaddr_in *) get_nsaddr (statp, ns);
+ if ((srv != NULL) && (srv->sin_family == AF_INET) &&
- if ((srv->sin_family == AF_INET) &&
(srv->sin_port == port) &&
(srv->sin_addr.s_addr == INADDR_ANY ||
srv->sin_addr.s_addr == addr))
return (1);
}
} else if (inp->sin6_family == AF_INET6) {
+ for (ns = 0; ns < MAXNS; ns++) {
+ const struct sockaddr_in6 *srv = EXT(statp).nsaddrs[ns];
+ if ((srv != NULL) && (srv->sin6_family == AF_INET6) &&
- for (ns = 0; ns < statp->nscount; ns++) {
- const struct sockaddr_in6 *srv
- = (struct sockaddr_in6 *) get_nsaddr (statp, ns);
- if ((srv->sin6_family == AF_INET6) &&
(srv->sin6_port == inp->sin6_port) &&
!(memcmp(&srv->sin6_addr, &in6addr_any,
sizeof (struct in6_addr)) &&
@@ -386,48 +384,80 @@
* If the ns_addr_list in the resolver context has changed, then
* invalidate our cached copy and the associated timing data.
*/
+ if (EXT(statp).nsinit) {
- if (EXT(statp).nscount != 0) {
int needclose = 0;
if (EXT(statp).nscount != statp->nscount)
needclose++;
else
+ for (ns = 0; ns < MAXNS; ns++) {
+ unsigned int map = EXT(statp).nsmap[ns];
+ if (map < MAXNS
- for (ns = 0; ns < statp->nscount; ns++) {
- if (statp->nsaddr_list[ns].sin_family != 0
&& !sock_eq((struct sockaddr_in6 *)
+ &statp->nsaddr_list[map],
- &statp->nsaddr_list[ns],
EXT(statp).nsaddrs[ns]))
{
needclose++;
break;
}
}
+ if (needclose)
- if (needclose) {
__res_iclose(statp, false);
- EXT(statp).nscount = 0;
- }
}
/*
* Maybe initialize our private copy of the ns_addr_list.
*/
+ if (EXT(statp).nsinit == 0) {
+ unsigned char map[MAXNS];
+
+ memset (map, MAXNS, sizeof (map));
+ for (n = 0; n < MAXNS; n++) {
+ ns = EXT(statp).nsmap[n];
+ if (ns < statp->nscount)
+ map[ns] = n;
+ else if (ns < MAXNS) {
+ free(EXT(statp).nsaddrs[n]);
+ EXT(statp).nsaddrs[n] = NULL;
+ EXT(statp).nsmap[n] = MAXNS;
+ }
+ }
+ n = statp->nscount;
+ if (statp->nscount > EXT(statp).nscount)
+ for (n = EXT(statp).nscount, ns = 0;
+ n < statp->nscount; n++) {
+ while (ns < MAXNS
+ && EXT(statp).nsmap[ns] != MAXNS)
+ ns++;
+ if (ns == MAXNS)
+ break;
+ /* NS never exceeds MAXNS, but gcc 4.9 somehow
+ does not see this. */
+ DIAG_PUSH_NEEDS_COMMENT;
+ DIAG_IGNORE_NEEDS_COMMENT (4.9,
+ "-Warray-bounds");
+ EXT(statp).nsmap[ns] = n;
+ DIAG_POP_NEEDS_COMMENT;
+ map[n] = ns++;
+ }
+ EXT(statp).nscount = n;
+ for (ns = 0; ns < EXT(statp).nscount; ns++) {
+ n = map[ns];
+ if (EXT(statp).nsaddrs[n] == NULL)
+ EXT(statp).nsaddrs[n] =
- if (EXT(statp).nscount == 0) {
- for (ns = 0; ns < statp->nscount; ns++) {
- EXT(statp).nssocks[ns] = -1;
- if (statp->nsaddr_list[ns].sin_family == 0)
- continue;
- if (EXT(statp).nsaddrs[ns] == NULL)
- EXT(statp).nsaddrs[ns] =
malloc(sizeof (struct sockaddr_in6));
+ if (EXT(statp).nsaddrs[n] != NULL) {
+ memset (mempcpy(EXT(statp).nsaddrs[n],
- if (EXT(statp).nsaddrs[ns] != NULL)
- memset (mempcpy(EXT(statp).nsaddrs[ns],
&statp->nsaddr_list[ns],
sizeof (struct sockaddr_in)),
'\0',
sizeof (struct sockaddr_in6)
- sizeof (struct sockaddr_in));
+ EXT(statp).nssocks[n] = -1;
+ n++;
+ }
}
+ EXT(statp).nsinit = 1;
- EXT(statp).nscount = statp->nscount;
}
/*
@@ -436,37 +466,44 @@
*/
if (__builtin_expect ((statp->options & RES_ROTATE) != 0, 0) &&
(statp->options & RES_BLAST) == 0) {
+ struct sockaddr_in6 *ina;
+ unsigned int map;
+
+ n = 0;
+ while (n < MAXNS && EXT(statp).nsmap[n] == MAXNS)
+ n++;
+ if (n < MAXNS) {
+ ina = EXT(statp).nsaddrs[n];
+ map = EXT(statp).nsmap[n];
+ for (;;) {
+ ns = n + 1;
+ while (ns < MAXNS
+ && EXT(statp).nsmap[ns] == MAXNS)
+ ns++;
+ if (ns == MAXNS)
+ break;
+ EXT(statp).nsaddrs[n] = EXT(statp).nsaddrs[ns];
+ EXT(statp).nsmap[n] = EXT(statp).nsmap[ns];
+ n = ns;
+ }
+ EXT(statp).nsaddrs[n] = ina;
+ EXT(statp).nsmap[n] = map;
- struct sockaddr_in ina;
- struct sockaddr_in6 *inp;
- int lastns = statp->nscount - 1;
- int fd;
-
- inp = EXT(statp).nsaddrs[0];
- ina = statp->nsaddr_list[0];
- fd = EXT(statp).nssocks[0];
- for (ns = 0; ns < lastns; ns++) {
- EXT(statp).nsaddrs[ns] = EXT(statp).nsaddrs[ns + 1];
- statp->nsaddr_list[ns] = statp->nsaddr_list[ns + 1];
- EXT(statp).nssocks[ns] = EXT(statp).nssocks[ns + 1];
}
- EXT(statp).nsaddrs[lastns] = inp;
- statp->nsaddr_list[lastns] = ina;
- EXT(statp).nssocks[lastns] = fd;
}
/*
* Send request, RETRY times, or until successful.
*/
for (try = 0; try < statp->retry; try++) {
+ for (ns = 0; ns < MAXNS; ns++)
- for (ns = 0; ns < statp->nscount; ns++)
{
#ifdef DEBUG
char tmpbuf[40];
#endif
+ struct sockaddr_in6 *nsap = EXT(statp).nsaddrs[ns];
-#if defined USE_HOOKS || defined DEBUG
- struct sockaddr *nsap = get_nsaddr (statp, ns);
-#endif
+ if (nsap == NULL)
+ goto next_ns;
same_ns:
#ifdef USE_HOOKS
if (__glibc_unlikely (statp->qhook != NULL)) {
@@ -505,9 +542,9 @@
Dprint(statp->options & RES_DEBUG,
(stdout, ";; Querying server (# %d) address = %s\n",
+ ns + 1, inet_ntop(nsap->sin6_family,
+ (nsap->sin6_family == AF_INET6
+ ? &nsap->sin6_addr
- ns + 1, inet_ntop(nsap->sa_family,
- (nsap->sa_family == AF_INET6
- ? &((struct sockaddr_in6 *) nsap)->sin6_addr
: &((struct sockaddr_in *) nsap)->sin_addr),
tmpbuf, sizeof (tmpbuf))));
@@ -623,21 +660,6 @@
/* Private */
-static struct sockaddr *
-get_nsaddr (res_state statp, int n)
-{
-
- if (statp->nsaddr_list[n].sin_family == 0 && EXT(statp).nsaddrs[n] != NULL)
- /* EXT(statp).nsaddrs[n] holds an address that is larger than
- struct sockaddr, and user code did not update
- statp->nsaddr_list[n]. */
- return (struct sockaddr *) EXT(statp).nsaddrs[n];
- else
- /* User code updated statp->nsaddr_list[n], or statp->nsaddr_list[n]
- has the same content as EXT(statp).nsaddrs[n]. */
- return (struct sockaddr *) (void *) &statp->nsaddr_list[n];
-}
-
static int
send_vc(res_state statp,
const u_char *buf, int buflen, const u_char *buf2, int buflen2,
@@ -652,7 +674,7 @@
// XXX REMOVE
// int anssiz = *anssizp;
HEADER *anhp = (HEADER *) ans;
+ struct sockaddr_in6 *nsap = EXT(statp).nsaddrs[ns];
- struct sockaddr *nsap = get_nsaddr (statp, ns);
int truncating, connreset, n;
/* On some architectures compiler might emit a warning indicating
'resplen' may be used uninitialized. However if buf2 == NULL
@@ -689,8 +711,8 @@
if (getpeername(statp->_vcsock,
(struct sockaddr *)&peer, &size) < 0 ||
+ !sock_eq(&peer, nsap)) {
+ __res_iclose(statp, false);
- !sock_eq(&peer, (struct sockaddr_in6 *) nsap)) {
- __res_iclose(statp, false);
statp->_flags &= ~RES_F_VC;
}
}
@@ -699,19 +721,20 @@
if (statp->_vcsock >= 0)
__res_iclose(statp, false);
+ statp->_vcsock = socket(nsap->sin6_family, SOCK_STREAM, 0);
- statp->_vcsock = socket(nsap->sa_family, SOCK_STREAM, 0);
if (statp->_vcsock < 0) {
*terrno = errno;
Perror(statp, stderr, "socket(vc)", errno);
return (-1);
}
__set_errno (0);
+ if (connect(statp->_vcsock, (struct sockaddr *)nsap,
+ nsap->sin6_family == AF_INET
- if (connect(statp->_vcsock, nsap,
- nsap->sa_family == AF_INET
? sizeof (struct sockaddr_in)
: sizeof (struct sockaddr_in6)) < 0) {
*terrno = errno;
+ Aerror(statp, stderr, "connect/vc", errno,
+ (struct sockaddr *) nsap);
- Aerror(statp, stderr, "connect/vc", errno, nsap);
__res_iclose(statp, false);
return (0);
}
@@ -922,7 +945,8 @@
reopen (res_state statp, int *terrno, int ns)
{
if (EXT(statp).nssocks[ns] == -1) {
+ struct sockaddr *nsap
+ = (struct sockaddr *) EXT(statp).nsaddrs[ns];
- struct sockaddr *nsap = get_nsaddr (statp, ns);
socklen_t slen;
/* only try IPv6 if IPv6 NS and if not failed before */

583
glibc-rh1276112.patch Normal file
View File

@ -0,0 +1,583 @@
commit 85ee11e317058d44d5c6c29bb4c53acc6c0e22c9
Author: Florian Weimer <fweimer@redhat.com>
Date: Wed Oct 28 19:32:46 2015 +0100
malloc: Prevent arena free_list from turning cyclic [BZ #19048]
[BZ# 19048]
* malloc/malloc.c (struct malloc_state): Update comment. Add
attached_threads member.
(main_arena): Initialize attached_threads.
* malloc/arena.c (list_lock): Update comment.
(ptmalloc_lock_all, ptmalloc_unlock_all): Likewise.
(ptmalloc_unlock_all2): Reinitialize arena reference counts.
(deattach_arena): New function.
(_int_new_arena): Initialize arena reference count and deattach
replaced arena.
(get_free_list, reused_arena): Update reference count and deattach
replaced arena.
(arena_thread_freeres): Update arena reference count and only put
unreferenced arenas on the free list.
(Backport reintroduces tsd_getspecific, tsd_setspecific.)
commit 3da825ce483903e3a881a016113b3e59fd4041de
Author: Florian Weimer <fweimer@redhat.com>
Date: Wed Dec 16 12:39:48 2015 +0100
malloc: Fix attached thread reference count handling [BZ #19243]
reused_arena can increase the attached thread count of arenas on the
free list. This means that the assertion that the reference count is
zero is incorrect. In this case, the reference count initialization
is incorrect as well and could cause arenas to be put on the free
list too early (while they still have attached threads).
commit 90c400bd4904b0240a148f0b357a5cbc36179239
Author: Florian Weimer <fweimer@redhat.com>
Date: Mon Dec 21 16:42:46 2015 +0100
malloc: Fix list_lock/arena lock deadlock [BZ #19182]
commit 7962541a32eff5597bc4207e781cfac8d1bb0d87
Author: Florian Weimer <fweimer@redhat.com>
Date: Wed Dec 23 17:23:33 2015 +0100
malloc: Update comment for list_lock
Index: b/malloc/arena.c
===================================================================
--- a/malloc/arena.c
+++ b/malloc/arena.c
@@ -67,10 +67,30 @@ extern int sanity_check_heap_info_alignm
/* Thread specific data */
static tsd_key_t arena_key;
-static mutex_t list_lock = MUTEX_INITIALIZER;
+
+/* Arena free list. free_list_lock synchronizes access to the
+ free_list variable below, and the next_free and attached_threads
+ members of struct malloc_state objects. No other locks must be
+ acquired after free_list_lock has been acquired. */
+
+static mutex_t free_list_lock = MUTEX_INITIALIZER;
static size_t narenas = 1;
static mstate free_list;
+/* list_lock prevents concurrent writes to the next member of struct
+ malloc_state objects.
+
+ Read access to the next member is supposed to synchronize with the
+ atomic_write_barrier and the write to the next member in
+ _int_new_arena. This suffers from data races; see the FIXME
+ comments in _int_new_arena and reused_arena.
+
+ list_lock also prevents concurrent forks. At the time list_lock is
+ acquired, no arena lock must have been acquired, but it is
+ permitted to acquire arena locks subsequently, while list_lock is
+ acquired. */
+static mutex_t list_lock = MUTEX_INITIALIZER;
+
/* Mapped memory in non-main arenas (reliable only for NO_THREADS). */
static unsigned long arena_mem;
@@ -210,6 +230,9 @@ ptmalloc_lock_all (void)
if (__malloc_initialized < 1)
return;
+ /* We do not acquire free_list_lock here because we completely
+ reconstruct free_list in ptmalloc_unlock_all2. */
+
if (mutex_trylock (&list_lock))
{
void *my_arena;
@@ -233,7 +256,10 @@ ptmalloc_lock_all (void)
save_free_hook = __free_hook;
__malloc_hook = malloc_atfork;
__free_hook = free_atfork;
- /* Only the current thread may perform malloc/free calls now. */
+ /* Only the current thread may perform malloc/free calls now.
+ save_arena will be reattached to the current thread, in
+ ptmalloc_lock_all, so save_arena->attached_threads is not
+ updated. */
tsd_getspecific (arena_key, save_arena);
tsd_setspecific (arena_key, ATFORK_ARENA_PTR);
out:
@@ -251,6 +277,9 @@ ptmalloc_unlock_all (void)
if (--atfork_recursive_cntr != 0)
return;
+ /* Replace ATFORK_ARENA_PTR with save_arena.
+ save_arena->attached_threads was not changed in ptmalloc_lock_all
+ and is still correct. */
tsd_setspecific (arena_key, save_arena);
__malloc_hook = save_malloc_hook;
__free_hook = save_free_hook;
@@ -282,12 +311,20 @@ ptmalloc_unlock_all2 (void)
tsd_setspecific (arena_key, save_arena);
__malloc_hook = save_malloc_hook;
__free_hook = save_free_hook;
+
+ /* Push all arenas to the free list, except save_arena, which is
+ attached to the current thread. */
+ mutex_init (&free_list_lock);
+ if (save_arena != NULL)
+ ((mstate) save_arena)->attached_threads = 1;
free_list = NULL;
for (ar_ptr = &main_arena;; )
{
mutex_init (&ar_ptr->mutex);
if (ar_ptr != save_arena)
{
+ /* This arena is no longer attached to any thread. */
+ ar_ptr->attached_threads = 0;
ar_ptr->next_free = free_list;
free_list = ar_ptr;
}
@@ -295,6 +332,7 @@ ptmalloc_unlock_all2 (void)
if (ar_ptr == &main_arena)
break;
}
+
mutex_init (&list_lock);
atfork_recursive_cntr = 0;
}
@@ -721,6 +759,22 @@ heap_trim (heap_info *heap, size_t pad)
/* Create a new arena with initial size "size". */
+/* If REPLACED_ARENA is not NULL, detach it from this thread. Must be
+ called while free_list_lock is held. */
+static void
+detach_arena (mstate replaced_arena)
+{
+ if (replaced_arena != NULL)
+ {
+ assert (replaced_arena->attached_threads > 0);
+ /* The current implementation only detaches from main_arena in
+ case of allocation failure. This means that it is likely not
+ beneficial to put the arena on free_list even if the
+ reference count reaches zero. */
+ --replaced_arena->attached_threads;
+ }
+}
+
static mstate
_int_new_arena (size_t size)
{
@@ -742,6 +796,7 @@ _int_new_arena (size_t size)
}
a = h->ar_ptr = (mstate) (h + 1);
malloc_init_state (a);
+ a->attached_threads = 1;
/*a->next = NULL;*/
a->system_mem = a->max_system_mem = h->size;
arena_mem += h->size;
@@ -755,34 +810,67 @@ _int_new_arena (size_t size)
set_head (top (a), (((char *) h + h->size) - ptr) | PREV_INUSE);
LIBC_PROBE (memory_arena_new, 2, a, size);
+ mstate replaced_arena;
+ {
+ void *vptr = NULL;
+ replaced_arena = tsd_getspecific (arena_key, vptr);
+ }
tsd_setspecific (arena_key, (void *) a);
mutex_init (&a->mutex);
- (void) mutex_lock (&a->mutex);
(void) mutex_lock (&list_lock);
/* Add the new arena to the global list. */
a->next = main_arena.next;
+ /* FIXME: The barrier is an attempt to synchronize with read access
+ in reused_arena, which does not acquire list_lock while
+ traversing the list. */
atomic_write_barrier ();
main_arena.next = a;
(void) mutex_unlock (&list_lock);
+ (void) mutex_lock (&free_list_lock);
+ detach_arena (replaced_arena);
+ (void) mutex_unlock (&free_list_lock);
+
+ /* Lock this arena. NB: Another thread may have been attached to
+ this arena because the arena is now accessible from the
+ main_arena.next list and could have been picked by reused_arena.
+ This can only happen for the last arena created (before the arena
+ limit is reached). At this point, some arena has to be attached
+ to two threads. We could acquire the arena lock before list_lock
+ to make it less likely that reused_arena picks this new arena,
+ but this could result in a deadlock with ptmalloc_lock_all. */
+
+ (void) mutex_lock (&a->mutex);
+
return a;
}
+/* Remove an arena from free_list. The arena may be in use because it
+ was attached concurrently to a thread by reused_arena below. */
static mstate
get_free_list (void)
{
+ void *vptr = NULL;
+ mstate replaced_arena = tsd_getspecific (arena_key, vptr);
mstate result = free_list;
if (result != NULL)
{
- (void) mutex_lock (&list_lock);
+ (void) mutex_lock (&free_list_lock);
result = free_list;
if (result != NULL)
- free_list = result->next_free;
- (void) mutex_unlock (&list_lock);
+ {
+ free_list = result->next_free;
+
+ /* The arena will be attached to this thread. */
+ ++result->attached_threads;
+
+ detach_arena (replaced_arena);
+ }
+ (void) mutex_unlock (&free_list_lock);
if (result != NULL)
{
@@ -802,16 +890,20 @@ static mstate
reused_arena (mstate avoid_arena)
{
mstate result;
+ /* FIXME: Access to next_to_use suffers from data races. */
static mstate next_to_use;
if (next_to_use == NULL)
next_to_use = &main_arena;
+ /* Iterate over all arenas (including those linked from
+ free_list). */
result = next_to_use;
do
{
if (!arena_is_corrupt (result) && !mutex_trylock (&result->mutex))
goto out;
+ /* FIXME: This is a data race, see _int_new_arena. */
result = result->next;
}
while (result != next_to_use);
@@ -840,6 +932,18 @@ reused_arena (mstate avoid_arena)
(void) mutex_lock (&result->mutex);
out:
+ /* Attach the arena to the current thread. Note that we may have
+ selected an arena which was on free_list. */
+ {
+ /* Update the arena thread attachment counters. */
+ void *vptr = NULL;
+ mstate replaced_arena = tsd_getspecific (arena_key, vptr);
+ (void) mutex_lock (&free_list_lock);
+ detach_arena (replaced_arena);
+ ++result->attached_threads;
+ (void) mutex_unlock (&free_list_lock);
+ }
+
LIBC_PROBE (memory_arena_reuse, 2, result, avoid_arena);
tsd_setspecific (arena_key, (void *) result);
next_to_use = result->next;
@@ -932,10 +1036,16 @@ arena_thread_freeres (void)
if (a != NULL)
{
- (void) mutex_lock (&list_lock);
- a->next_free = free_list;
- free_list = a;
- (void) mutex_unlock (&list_lock);
+ (void) mutex_lock (&free_list_lock);
+ /* If this was the last attached thread for this arena, put the
+ arena on the free list. */
+ assert (a->attached_threads > 0);
+ if (--a->attached_threads == 0)
+ {
+ a->next_free = free_list;
+ free_list = a;
+ }
+ (void) mutex_unlock (&free_list_lock);
}
}
text_set_element (__libc_thread_subfreeres, arena_thread_freeres);
Index: b/malloc/malloc.c
===================================================================
--- a/malloc/malloc.c
+++ b/malloc/malloc.c
@@ -1709,9 +1709,15 @@ struct malloc_state
/* Linked list */
struct malloc_state *next;
- /* Linked list for free arenas. */
+ /* Linked list for free arenas. Access to this field is serialized
+ by free_list_lock in arena.c. */
struct malloc_state *next_free;
+ /* Number of threads attached to this arena. 0 if the arena is on
+ the free list. Access to this field is serialized by
+ free_list_lock in arena.c. */
+ INTERNAL_SIZE_T attached_threads;
+
/* Memory allocated from the system in this arena. */
INTERNAL_SIZE_T system_mem;
INTERNAL_SIZE_T max_system_mem;
@@ -1755,7 +1761,8 @@ struct malloc_par
static struct malloc_state main_arena =
{
.mutex = MUTEX_INITIALIZER,
- .next = &main_arena
+ .next = &main_arena,
+ .attached_threads = 1
};
/* There is only one instance of the malloc parameters. */
Index: b/malloc/Makefile
===================================================================
--- a/malloc/Makefile
+++ b/malloc/Makefile
@@ -28,7 +28,7 @@ tests := mallocbug tst-malloc tst-valloc
tst-mallocstate tst-mcheck tst-mallocfork tst-trim1 \
tst-malloc-usable tst-realloc tst-posix_memalign \
tst-pvalloc tst-memalign tst-mallopt tst-scratch_buffer \
- tst-malloc-backtrace
+ tst-malloc-backtrace tst-malloc-thread-exit
test-srcs = tst-mtrace
routines = malloc morecore mcheck mtrace obstack \
@@ -47,6 +47,8 @@ libmemusage-inhibit-o = $(filter-out .os
$(objpfx)tst-malloc-backtrace: $(common-objpfx)nptl/libpthread.so \
$(common-objpfx)nptl/libpthread_nonshared.a
+$(objpfx)tst-malloc-thread-exit: $(common-objpfx)nptl/libpthread.so \
+ $(common-objpfx)nptl/libpthread_nonshared.a
# These should be removed by `make clean'.
extra-objs = mcheck-init.o libmcheck.a
Index: b/malloc/tst-malloc-thread-exit.c
===================================================================
--- /dev/null
+++ b/malloc/tst-malloc-thread-exit.c
@@ -0,0 +1,217 @@
+/* Test malloc with concurrent thread termination.
+ 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
+ <http://www.gnu.org/licenses/>. */
+
+/* This thread spawns a number of outer threads, equal to the arena
+ limit. The outer threads run a loop which start and join two
+ different kinds of threads: the first kind allocates (attaching an
+ arena to the thread; malloc_first_thread) and waits, the second
+ kind waits and allocates (wait_first_threads). Both kinds of
+ threads exit immediately after waiting. The hope is that this will
+ exhibit races in thread termination and arena management,
+ particularly related to the arena free list. */
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#define TIMEOUT 7
+
+static bool termination_requested;
+static int inner_thread_count = 4;
+static size_t malloc_size = 32;
+
+static void
+__attribute__ ((noinline, noclone))
+unoptimized_free (void *ptr)
+{
+ free (ptr);
+}
+
+static void *
+malloc_first_thread (void * closure)
+{
+ pthread_barrier_t *barrier = closure;
+ void *ptr = malloc (malloc_size);
+ if (ptr == NULL)
+ {
+ printf ("error: malloc: %m\n");
+ abort ();
+ }
+ int ret = pthread_barrier_wait (barrier);
+ if (ret != 0 && ret != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ errno = ret;
+ printf ("error: pthread_barrier_wait: %m\n");
+ abort ();
+ }
+ unoptimized_free (ptr);
+ return NULL;
+}
+
+static void *
+wait_first_thread (void * closure)
+{
+ pthread_barrier_t *barrier = closure;
+ int ret = pthread_barrier_wait (barrier);
+ if (ret != 0 && ret != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ errno = ret;
+ printf ("error: pthread_barrier_wait: %m\n");
+ abort ();
+ }
+ void *ptr = malloc (malloc_size);
+ if (ptr == NULL)
+ {
+ printf ("error: malloc: %m\n");
+ abort ();
+ }
+ unoptimized_free (ptr);
+ return NULL;
+}
+
+static void *
+outer_thread (void *closure)
+{
+ pthread_t *threads = calloc (sizeof (*threads), inner_thread_count);
+ if (threads == NULL)
+ {
+ printf ("error: calloc: %m\n");
+ abort ();
+ }
+
+ while (!__atomic_load_n (&termination_requested, __ATOMIC_RELAXED))
+ {
+ pthread_barrier_t barrier;
+ int ret = pthread_barrier_init (&barrier, NULL, inner_thread_count + 1);
+ if (ret != 0)
+ {
+ errno = ret;
+ printf ("pthread_barrier_init: %m\n");
+ abort ();
+ }
+ for (int i = 0; i < inner_thread_count; ++i)
+ {
+ void *(*func) (void *);
+ if ((i % 2) == 0)
+ func = malloc_first_thread;
+ else
+ func = wait_first_thread;
+ ret = pthread_create (threads + i, NULL, func, &barrier);
+ if (ret != 0)
+ {
+ errno = ret;
+ printf ("error: pthread_create: %m\n");
+ abort ();
+ }
+ }
+ ret = pthread_barrier_wait (&barrier);
+ if (ret != 0 && ret != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ errno = ret;
+ printf ("pthread_wait: %m\n");
+ abort ();
+ }
+ for (int i = 0; i < inner_thread_count; ++i)
+ {
+ ret = pthread_join (threads[i], NULL);
+ if (ret != 0)
+ {
+ ret = errno;
+ printf ("error: pthread_join: %m\n");
+ abort ();
+ }
+ }
+ ret = pthread_barrier_destroy (&barrier);
+ if (ret != 0)
+ {
+ ret = errno;
+ printf ("pthread_barrier_destroy: %m\n");
+ abort ();
+ }
+ }
+
+ free (threads);
+
+ return NULL;
+}
+
+static int
+do_test (void)
+{
+ /* The number of top-level threads should be equal to the number of
+ arenas. See arena_get2. */
+ long outer_thread_count = sysconf (_SC_NPROCESSORS_ONLN);
+ if (outer_thread_count >= 1)
+ {
+ /* See NARENAS_FROM_NCORES in malloc.c. */
+ if (sizeof (long) == 4)
+ outer_thread_count *= 2;
+ else
+ outer_thread_count *= 8;
+ }
+
+ /* Leave some room for shutting down all threads gracefully. */
+ int timeout = TIMEOUT - 2;
+
+ pthread_t *threads = calloc (sizeof (*threads), outer_thread_count);
+ if (threads == NULL)
+ {
+ printf ("error: calloc: %m\n");
+ abort ();
+ }
+
+ for (long i = 0; i < outer_thread_count; ++i)
+ {
+ int ret = pthread_create (threads + i, NULL, outer_thread, NULL);
+ if (ret != 0)
+ {
+ errno = ret;
+ printf ("error: pthread_create: %m\n");
+ abort ();
+ }
+ }
+
+ struct timespec ts = {timeout, 0};
+ if (nanosleep (&ts, NULL))
+ {
+ printf ("error: error: nanosleep: %m\n");
+ abort ();
+ }
+
+ __atomic_store_n (&termination_requested, true, __ATOMIC_RELAXED);
+
+ for (long i = 0; i < outer_thread_count; ++i)
+ {
+ int ret = pthread_join (threads[i], NULL);
+ if (ret != 0)
+ {
+ errno = ret;
+ printf ("error: pthread_join: %m\n");
+ abort ();
+ }
+ }
+ free (threads);
+
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"

391
glibc-rh1276711.patch Normal file
View File

@ -0,0 +1,391 @@
Description: Remove incorrect strcoll implementation.
Author: Carlos O'Donell <codonell@redhat.com>
Origin: git://sourceware.org/glibc.git
Bug-RHEL: N/A
Bug-Fedora: #1276711
Bug-Upstream: #18589
Upstream status: committed
commit 60cf80f09d029257caedc0c8abe7e3e09c64e6c7
Author: Martin Sebor <msebor@gcc.gnu.org>
Date: Mon Sep 28 16:55:57 2015 -0400
Let 'make check subdirs=string' succeed even when it's invoked
immediately after glibc has been built and before 'make check'
(or after 'make clean').
commit facdd9ea29ab94aac2b188ec3cc41f8733d769e0
Author: Carlos O'Donell <carlos@systemhalted.org>
Date: Fri Oct 9 16:35:53 2015 -0400
Fix typo in bug-strcoll2 (Bug 18589)
Fix the copyright year and remove contributed by in the
bug-strcoll2 test. In addition add the correct dependency
on $(gen-locales) to ensure all the test locales are generated.
commit 02018629a1397d03eccceacaf2ee1c50e3c4001c
Author: Carlos O'Donell <carlos@systemhalted.org>
Date: Thu Oct 8 16:54:30 2015 -0400
strcoll: Add bug-strcoll2 to testsuite (Bug 18589).
Adds bug-strcoll2 to the string tests, along with the
generation of required locales.
commit 87701a58e291bd7ac3b407d10a829dac52c9c16e
Author: Carlos O'Donell <carlos@systemhalted.org>
Date: Thu Oct 8 16:34:53 2015 -0400
strcoll: Remove incorrect STRDIFF-based optimization (Bug 18589).
The optimization introduced in commit
f13c2a8dff2329c6692a80176262ceaaf8a6f74e, causes regressions in
sorting for languages that have digraphs that change sort order, like
cs_CZ which sorts ch between h and i.
My analysis shows the fast-forwarding optimization in STRCOLL advances
through a digraph while possibly stopping in the middle which results
in a subsequent skipping of the digraph and incorrect sorting. The
optimization is incorrect as implemented and because of that I'm
removing it for 2.23, and I will also commit this fix for 2.22 where
it was originally introduced.
This patch reverts the optimization, introduces a new bug-strcoll2.c
regression test that tests both cs_CZ.UTF-8 and da_DK.ISO-8859-1 and
ensures they sort one digraph each correctly. The optimization can't be
applied without regressing this test.
Checked on x86_64, bug-strcoll2.c fails without this patch and passes
after. This will also get a fix on 2.22 which has the same bug.
Index: glibc-2.22/locale/C-collate.c
===================================================================
--- glibc-2.22.orig/locale/C-collate.c
+++ glibc-2.22/locale/C-collate.c
@@ -144,8 +144,6 @@ const struct __locale_data _nl_C_LC_COLL
/* _NL_COLLATE_COLLSEQWC */
{ .string = (const char *) collseqwc },
/* _NL_COLLATE_CODESET */
- { .string = _nl_C_codeset },
- /* _NL_COLLATE_ENCODING_TYPE */
- { .word = __cet_8bit }
+ { .string = _nl_C_codeset }
}
};
Index: glibc-2.22/locale/categories.def
===================================================================
--- glibc-2.22.orig/locale/categories.def
+++ glibc-2.22/locale/categories.def
@@ -58,7 +58,6 @@ DEFINE_CATEGORY
DEFINE_ELEMENT (_NL_COLLATE_COLLSEQMB, "collate-collseqmb", std, wstring)
DEFINE_ELEMENT (_NL_COLLATE_COLLSEQWC, "collate-collseqwc", std, wstring)
DEFINE_ELEMENT (_NL_COLLATE_CODESET, "collate-codeset", std, string)
- DEFINE_ELEMENT (_NL_COLLATE_ENCODING_TYPE, "collate-encoding-type", std, word)
), NO_POSTLOAD)
Index: glibc-2.22/locale/langinfo.h
===================================================================
--- glibc-2.22.orig/locale/langinfo.h
+++ glibc-2.22/locale/langinfo.h
@@ -255,7 +255,6 @@ enum
_NL_COLLATE_COLLSEQMB,
_NL_COLLATE_COLLSEQWC,
_NL_COLLATE_CODESET,
- _NL_COLLATE_ENCODING_TYPE,
_NL_NUM_LC_COLLATE,
/* LC_CTYPE category: character classification.
Index: glibc-2.22/locale/localeinfo.h
===================================================================
--- glibc-2.22.orig/locale/localeinfo.h
+++ glibc-2.22/locale/localeinfo.h
@@ -110,14 +110,6 @@ enum coll_sort_rule
sort_mask
};
-/* Collation encoding type. */
-enum collation_encoding_type
-{
- __cet_other,
- __cet_8bit,
- __cet_utf8
-};
-
/* We can map the types of the entries into a few categories. */
enum value_type
{
Index: glibc-2.22/locale/programs/ld-collate.c
===================================================================
--- glibc-2.22.orig/locale/programs/ld-collate.c
+++ glibc-2.22/locale/programs/ld-collate.c
@@ -32,7 +32,6 @@
#include "linereader.h"
#include "locfile.h"
#include "elem-hash.h"
-#include "../localeinfo.h"
/* Uncomment the following line in the production version. */
/* #define NDEBUG 1 */
@@ -2131,8 +2130,6 @@ collate_output (struct localedef_t *loca
/* The words have to be handled specially. */
if (idx == _NL_ITEM_INDEX (_NL_COLLATE_SYMB_HASH_SIZEMB))
add_locale_uint32 (&file, 0);
- else if (idx == _NL_ITEM_INDEX (_NL_COLLATE_ENCODING_TYPE))
- add_locale_uint32 (&file, __cet_other);
else
add_locale_empty (&file);
}
@@ -2496,12 +2493,6 @@ collate_output (struct localedef_t *loca
add_locale_raw_data (&file, collate->mbseqorder, 256);
add_locale_collseq_table (&file, &collate->wcseqorder);
add_locale_string (&file, charmap->code_set_name);
- if (strcmp (charmap->code_set_name, "UTF-8") == 0)
- add_locale_uint32 (&file, __cet_utf8);
- else if (charmap->mb_cur_max == 1)
- add_locale_uint32 (&file, __cet_8bit);
- else
- add_locale_uint32 (&file, __cet_other);
write_locale_data (output_path, LC_COLLATE, "LC_COLLATE", &file);
obstack_free (&weightpool, NULL);
Index: glibc-2.22/string/Makefile
===================================================================
--- glibc-2.22.orig/string/Makefile
+++ glibc-2.22/string/Makefile
@@ -54,7 +54,7 @@ tests := tester inl-tester noinl-tester
tst-strtok tst-strxfrm bug-strcoll1 tst-strfry \
bug-strtok1 $(addprefix test-,$(strop-tests)) \
bug-envz1 tst-strxfrm2 tst-endian tst-svc2 \
- tst-strtok_r
+ tst-strtok_r bug-strcoll2
xtests = tst-strcoll-overflow
@@ -75,4 +75,18 @@ ifeq ($(run-built-tests),yes)
$(objpfx)tst-svc-cmp.out: tst-svc.expect $(objpfx)tst-svc.out
cmp $^ > $@; \
$(evaluate-test)
+
+LOCALES := de_DE.UTF-8 en_US.ISO-8859-1 en_US.UTF-8 \
+ tr_TR.ISO-8859-9 tr_TR.UTF-8 cs_CZ.UTF-8 \
+ da_DK.ISO-8859-1
+
+include ../gen-locales.mk
+
+$(objpfx)test-strcasecmp.out: $(gen-locales)
+$(objpfx)test-strncasecmp.out: $(gen-locales)
+$(objpfx)tst-strxfrm.out: $(gen-locales)
+$(objpfx)tst-strxfrm2.out: $(gen-locales)
+# bug-strcoll2 needs cs_CZ.UTF-8 and da_DK.ISO-8859-1.
+$(objpfx)bug-strcoll2.out: $(gen-locales)
+
endif
Index: glibc-2.22/string/bug-strcoll2.c
===================================================================
--- /dev/null
+++ glibc-2.22/string/bug-strcoll2.c
@@ -0,0 +1,92 @@
+/* Bug 18589: sort-test.sh fails at random.
+ 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
+ <http://www.gnu.org/licenses/>. */
+
+#include <stdio.h>
+#include <string.h>
+#include <locale.h>
+
+/* An incorrect strcoll optimization resulted in incorrect
+ results from strcoll for cs_CZ and da_DK. */
+
+int
+test_cs_CZ (void)
+{
+ const char t1[] = "config";
+ const char t2[] = "choose";
+ if (setlocale (LC_ALL, "cs_CZ.UTF-8") == NULL)
+ {
+ perror ("setlocale");
+ return 1;
+ }
+ /* In Czech the digraph ch sorts after c, therefore we expect
+ config to sort before choose. */
+ int a = strcoll (t1, t2);
+ int b = strcoll (t2, t1);
+ printf ("strcoll (\"%s\", \"%s\") = %d\n", t1, t2, a);
+ printf ("strcoll (\"%s\", \"%s\") = %d\n", t2, t1, b);
+ if (a < 0 && b > 0)
+ {
+ puts ("PASS: config < choose");
+ return 0;
+ }
+ else
+ {
+ puts ("FAIL: Wrong sorting in cs_CZ.UTF-8.");
+ return 1;
+ }
+}
+
+int
+test_da_DK (void)
+{
+ const char t1[] = "AS";
+ const char t2[] = "AA";
+ if (setlocale (LC_ALL, "da_DK.ISO-8859-1") == NULL)
+ {
+ perror ("setlocale");
+ return 1;
+ }
+ /* AA should be treated as the last letter of the Danish alphabet,
+ hence sorting after AS. */
+ int a = strcoll (t1, t2);
+ int b = strcoll (t2, t1);
+ printf ("strcoll (\"%s\", \"%s\") = %d\n", t1, t2, a);
+ printf ("strcoll (\"%s\", \"%s\") = %d\n", t2, t1, b);
+ if (a < 0 && b > 0)
+ {
+ puts ("PASS: AS < AA");
+ return 0;
+ }
+ else
+ {
+ puts ("FAIL: Wrong sorting in da_DK.ISO-8859-1");
+ return 1;
+ }
+}
+
+static int
+do_test (void)
+{
+ int err = 0;
+ err |= test_cs_CZ ();
+ err |= test_da_DK ();
+ return err;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
Index: glibc-2.22/string/strcoll_l.c
===================================================================
--- glibc-2.22.orig/string/strcoll_l.c
+++ glibc-2.22/string/strcoll_l.c
@@ -29,7 +29,6 @@
# define STRING_TYPE char
# define USTRING_TYPE unsigned char
# define STRCOLL __strcoll_l
-# define STRDIFF __strdiff
# define STRCMP strcmp
# define WEIGHT_H "../locale/weight.h"
# define SUFFIX MB
@@ -42,20 +41,6 @@
#include "../locale/localeinfo.h"
#include WEIGHT_H
-#define MASK_UTF8_7BIT (1 << 7)
-#define MASK_UTF8_START (3 << 6)
-
-size_t
-STRDIFF (const STRING_TYPE *s, const STRING_TYPE *t)
-{
- size_t n;
-
- for (n = 0; *s != '\0' && *s++ == *t++; ++n)
- continue;
-
- return n;
-}
-
/* Track status while looking for sequences in a string. */
typedef struct
{
@@ -269,29 +254,9 @@ STRCOLL (const STRING_TYPE *s1, const ST
const USTRING_TYPE *extra;
const int32_t *indirect;
- /* In case there is no locale specific sort order (C / POSIX). */
if (nrules == 0)
return STRCMP (s1, s2);
- /* Fast forward to the position of the first difference. Needs to be
- encoding aware as the byte-by-byte comparison can stop in the middle
- of a char sequence for multibyte encodings like UTF-8. */
- uint_fast32_t encoding =
- current->values[_NL_ITEM_INDEX (_NL_COLLATE_ENCODING_TYPE)].word;
- if (encoding != __cet_other)
- {
- size_t diff = STRDIFF (s1, s2);
- if (diff > 0)
- {
- if (encoding == __cet_utf8 && (*(s1 + diff) & MASK_UTF8_7BIT) != 0)
- do
- diff--;
- while (diff > 0 && (*(s1 + diff) & MASK_UTF8_START) != MASK_UTF8_START);
- s1 += diff;
- s2 += diff;
- }
- }
-
/* Catch empty strings. */
if (__glibc_unlikely (*s1 == '\0') || __glibc_unlikely (*s2 == '\0'))
return (*s1 != '\0') - (*s2 != '\0');
@@ -358,8 +323,7 @@ STRCOLL (const STRING_TYPE *s1, const ST
byte-level comparison to ensure that we don't waste time
going through multiple passes for totally equal strings
before proceeding to subsequent passes. */
- if (pass == 0 && encoding == __cet_other &&
- STRCMP (s1, s2) == 0)
+ if (pass == 0 && STRCMP (s1, s2) == 0)
return result;
else
break;
Index: glibc-2.22/string/tst-strxfrm2.c
===================================================================
--- glibc-2.22.orig/string/tst-strxfrm2.c
+++ glibc-2.22/string/tst-strxfrm2.c
@@ -5,6 +5,8 @@
static int
do_test (void)
{
+ static const char test_locale[] = "de_DE.UTF-8";
+
int res = 0;
char buf[20];
@@ -38,9 +40,9 @@ do_test (void)
res = 1;
}
- if (setlocale (LC_ALL, "de_DE.UTF-8") == NULL)
+ if (setlocale (LC_ALL, test_locale) == NULL)
{
- puts ("setlocale failed");
+ printf ("cannot set locale \"%s\"\n", test_locale);
res = 1;
}
else
Index: glibc-2.22/wcsmbs/wcscoll_l.c
===================================================================
--- glibc-2.22.orig/wcsmbs/wcscoll_l.c
+++ glibc-2.22/wcsmbs/wcscoll_l.c
@@ -23,7 +23,6 @@
#define STRING_TYPE wchar_t
#define USTRING_TYPE wint_t
#define STRCOLL __wcscoll_l
-#define STRDIFF __wcsdiff
#define STRCMP __wcscmp
#define WEIGHT_H "../locale/weightwc.h"
#define SUFFIX WC

66
glibc-rh1276761-1.patch Normal file
View File

@ -0,0 +1,66 @@
commit a014cecd82b71b70a6a843e250e06b541ad524f7
Author: Florian Weimer <fweimer@redhat.com>
Date: Thu Oct 15 09:23:07 2015 +0200
Always enable pointer guard [BZ #18928]
Honoring the LD_POINTER_GUARD environment variable in AT_SECURE mode
has security implications. This commit enables pointer guard
unconditionally, and the environment variable is now ignored.
Index: b/elf/rtld.c
===================================================================
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -160,7 +160,6 @@ struct rtld_global_ro _rtld_global_ro at
._dl_hwcap_mask = HWCAP_IMPORTANT,
._dl_lazy = 1,
._dl_fpu_control = _FPU_DEFAULT,
- ._dl_pointer_guard = 1,
._dl_pagesize = EXEC_PAGESIZE,
._dl_inhibit_cache = 0,
@@ -707,15 +706,12 @@ security_init (void)
#endif
/* Set up the pointer guard as well, if necessary. */
- if (GLRO(dl_pointer_guard))
- {
- uintptr_t pointer_chk_guard = _dl_setup_pointer_guard (_dl_random,
- stack_chk_guard);
+ uintptr_t pointer_chk_guard
+ = _dl_setup_pointer_guard (_dl_random, stack_chk_guard);
#ifdef THREAD_SET_POINTER_GUARD
- THREAD_SET_POINTER_GUARD (pointer_chk_guard);
+ THREAD_SET_POINTER_GUARD (pointer_chk_guard);
#endif
- __pointer_chk_guard_local = pointer_chk_guard;
- }
+ __pointer_chk_guard_local = pointer_chk_guard;
/* We do not need the _dl_random value anymore. The less
information we leave behind, the better, so clear the
@@ -2467,9 +2463,6 @@ process_envvars (enum mode *modep)
GLRO(dl_use_load_bias) = envline[14] == '1' ? -1 : 0;
break;
}
-
- if (memcmp (envline, "POINTER_GUARD", 13) == 0)
- GLRO(dl_pointer_guard) = envline[14] != '0';
break;
case 14:
Index: b/sysdeps/generic/ldsodefs.h
===================================================================
--- a/sysdeps/generic/ldsodefs.h
+++ b/sysdeps/generic/ldsodefs.h
@@ -592,9 +592,6 @@ struct rtld_global_ro
/* List of auditing interfaces. */
struct audit_ifaces *_dl_audit;
unsigned int _dl_naudit;
-
- /* 0 if internal pointer values should not be guarded, 1 if they should. */
- EXTERN int _dl_pointer_guard;
};
# define __rtld_global_attribute__
# if IS_IN (rtld)

377
glibc-rh1276761-2.patch Normal file
View File

@ -0,0 +1,377 @@
commit 99e1dc0a688d6c25d3f422bc9f3fa29adb483339
Author: Florian Weimer <fweimer@redhat.com>
Date: Tue Oct 6 21:27:55 2015 +0200
Add a test case for C++11 thread_local support
This requires a C++ compiler with thread_local support, and a new
configure check is needed.
Index: b/config.make.in
===================================================================
--- a/config.make.in
+++ b/config.make.in
@@ -67,6 +67,7 @@ bind-now = @bindnow@
have-hash-style = @libc_cv_hashstyle@
use-default-link = @use_default_link@
output-format = @libc_cv_output_format@
+have-cxx-thread_local = @libc_cv_cxx_thread_local@
static-libgcc = @libc_cv_gcc_static_libgcc@
Index: b/configure
===================================================================
--- a/configure
+++ b/configure
@@ -614,6 +614,7 @@ use_nscd
libc_cv_gcc_unwind_find_fde
libc_extra_cppflags
libc_extra_cflags
+libc_cv_cxx_thread_local
CPPUNDEFS
sizeof_long_double
have_selinux
@@ -7202,6 +7203,61 @@ if test $libc_cv_builtin_trap = yes; the
fi
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C++ compiler supports thread_local" >&5
+$as_echo_n "checking whether the C++ compiler supports thread_local... " >&6; }
+if ${libc_cv_cxx_thread_local+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+old_CXXFLAGS="$CXXFLAGS"
+CXXFLAGS="$CXXFLAGS -std=gnu++11"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+#include <thread>
+
+// Compiler support.
+struct S
+{
+ S ();
+ ~S ();
+};
+thread_local S s;
+S * get () { return &s; }
+
+// libstdc++ support.
+#ifndef _GLIBCXX_HAVE___CXA_THREAD_ATEXIT_IMPL
+#error __cxa_thread_atexit_impl not supported
+#endif
+
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ libc_cv_cxx_thread_local=yes
+else
+ libc_cv_cxx_thread_local=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+CXXFLAGS="$old_CXXFLAGS"
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_cxx_thread_local" >&5
+$as_echo "$libc_cv_cxx_thread_local" >&6; }
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
### End of automated tests.
### Now run sysdeps configure fragments.
Index: b/configure.ac
===================================================================
--- a/configure.ac
+++ b/configure.ac
@@ -1976,6 +1976,39 @@ if test $libc_cv_builtin_trap = yes; the
AC_DEFINE([HAVE_BUILTIN_TRAP])
fi
+dnl C++ feature tests.
+AC_LANG_PUSH([C++])
+
+AC_CACHE_CHECK([whether the C++ compiler supports thread_local],
+ libc_cv_cxx_thread_local, [
+old_CXXFLAGS="$CXXFLAGS"
+CXXFLAGS="$CXXFLAGS -std=gnu++11"
+AC_COMPILE_IFELSE([AC_LANG_SOURCE([
+#include <thread>
+
+// Compiler support.
+struct S
+{
+ S ();
+ ~S ();
+};
+thread_local S s;
+S * get () { return &s; }
+
+// libstdc++ support.
+#ifndef _GLIBCXX_HAVE___CXA_THREAD_ATEXIT_IMPL
+#error __cxa_thread_atexit_impl not supported
+#endif
+])],
+ [libc_cv_cxx_thread_local=yes],
+ [libc_cv_cxx_thread_local=no])
+CXXFLAGS="$old_CXXFLAGS"
+])
+AC_SUBST(libc_cv_cxx_thread_local)
+
+AC_LANG_POP([C++])
+dnl End of C++ feature tests.
+
### End of automated tests.
### Now run sysdeps configure fragments.
Index: b/nptl/Makefile
===================================================================
--- a/nptl/Makefile
+++ b/nptl/Makefile
@@ -214,6 +214,8 @@ CFLAGS-recvfrom.c = -fexceptions -fasync
CFLAGS-pt-system.c = -fexceptions
LDLIBS-tst-once5 = -lstdc++
+CFLAGS-tst-thread_local1.o = -std=gnu++11
+LDLIBS-tst-thread_local1 = -lstdc++
tests = tst-typesizes \
tst-attr1 tst-attr2 tst-attr3 tst-default-attr \
@@ -285,7 +287,8 @@ tests = tst-typesizes \
tst-getpid3 \
tst-setuid3 \
tst-initializers1 $(addprefix tst-initializers1-,c89 gnu89 c99 gnu99) \
- tst-bad-schedattr
+ tst-bad-schedattr \
+ tst-thread_local1
xtests = tst-setuid1 tst-setuid1-static tst-setuid2 \
tst-mutexpp1 tst-mutexpp6 tst-mutexpp10
test-srcs = tst-oddstacklimit
@@ -405,6 +408,10 @@ ifeq (,$(CXX))
# These tests require a C++ compiler and runtime.
tests-unsupported += tst-cancel24 tst-cancel24-static tst-once5
endif
+# These tests require a C++ compiler and runtime with thread_local support.
+ifneq ($(have-cxx-thread_local),yes)
+tests-unsupported += tst-thread_local1
+endif
include ../Rules
Index: b/nptl/tst-thread_local1.cc
===================================================================
--- /dev/null
+++ b/nptl/tst-thread_local1.cc
@@ -0,0 +1,199 @@
+/* Test basic thread_local support.
+ 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
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <functional>
+#include <string>
+#include <thread>
+
+struct counter
+{
+ int constructed {};
+ int destructed {};
+
+ void reset ();
+};
+
+void
+counter::reset ()
+{
+ constructed = 0;
+ destructed = 0;
+}
+
+static std::string
+to_string (const counter &c)
+{
+ char buf[128];
+ snprintf (buf, sizeof (buf), "%d/%d",
+ c.constructed, c.destructed);
+ return buf;
+}
+
+template <counter *Counter>
+struct counting
+{
+ counting () __attribute__ ((noinline, noclone));
+ ~counting () __attribute__ ((noinline, noclone));
+ void operation () __attribute__ ((noinline, noclone));
+};
+
+template<counter *Counter>
+__attribute__ ((noinline, noclone))
+counting<Counter>::counting ()
+{
+ ++Counter->constructed;
+}
+
+template<counter *Counter>
+__attribute__ ((noinline, noclone))
+counting<Counter>::~counting ()
+{
+ ++Counter->destructed;
+}
+
+template<counter *Counter>
+void __attribute__ ((noinline, noclone))
+counting<Counter>::operation ()
+{
+ // Optimization barrier.
+ asm ("");
+}
+
+static counter counter_static;
+static counter counter_anonymous_namespace;
+static counter counter_extern;
+static counter counter_function_local;
+static bool errors (false);
+
+static std::string
+all_counters ()
+{
+ return to_string (counter_static)
+ + ' ' + to_string (counter_anonymous_namespace)
+ + ' ' + to_string (counter_extern)
+ + ' ' + to_string (counter_function_local);
+}
+
+static void
+check_counters (const char *name, const char *expected)
+{
+ std::string actual{all_counters ()};
+ if (actual != expected)
+ {
+ printf ("error: %s: (%s) != (%s)\n",
+ name, actual.c_str (), expected);
+ errors = true;
+ }
+}
+
+static void
+reset_all ()
+{
+ counter_static.reset ();
+ counter_anonymous_namespace.reset ();
+ counter_extern.reset ();
+ counter_function_local.reset ();
+}
+
+static thread_local counting<&counter_static> counting_static;
+namespace {
+ thread_local counting<&counter_anonymous_namespace>
+ counting_anonymous_namespace;
+}
+extern thread_local counting<&counter_extern> counting_extern;
+thread_local counting<&counter_extern> counting_extern;
+
+static void *
+thread_without_access (void *)
+{
+ return nullptr;
+}
+
+static void *
+thread_with_access (void *)
+{
+ thread_local counting<&counter_function_local> counting_function_local;
+ counting_function_local.operation ();
+ check_counters ("early in thread_with_access", "0/0 0/0 0/0 1/0");
+ counting_static.operation ();
+ counting_anonymous_namespace.operation ();
+ counting_extern.operation ();
+ check_counters ("in thread_with_access", "1/0 1/0 1/0 1/0");
+ return nullptr;
+}
+
+static int
+do_test (void)
+{
+ std::function<void (void *(void *))> do_pthread =
+ [](void *(func) (void *))
+ {
+ pthread_t thr;
+ int ret = pthread_create (&thr, nullptr, func, nullptr);
+ if (ret != 0)
+ {
+ errno = ret;
+ printf ("error: pthread_create: %m\n");
+ errors = true;
+ return;
+ }
+ ret = pthread_join (thr, nullptr);
+ if (ret != 0)
+ {
+ errno = ret;
+ printf ("error: pthread_join: %m\n");
+ errors = true;
+ return;
+ }
+ };
+ std::function<void (void *(void *))> do_std_thread =
+ [](void *(func) (void *))
+ {
+ std::thread thr{[func] {func (nullptr);}};
+ thr.join ();
+ };
+
+ std::array<std::pair<const char *, std::function<void (void *(void *))>>, 2>
+ do_thread_X
+ {{
+ {"pthread_create", do_pthread},
+ {"std::thread", do_std_thread},
+ }};
+
+ for (auto do_thread : do_thread_X)
+ {
+ printf ("info: testing %s\n", do_thread.first);
+ check_counters ("initial", "0/0 0/0 0/0 0/0");
+ do_thread.second (thread_without_access);
+ check_counters ("after thread_without_access", "0/0 0/0 0/0 0/0");
+ reset_all ();
+ do_thread.second (thread_with_access);
+ check_counters ("after thread_with_access", "1/1 1/1 1/1 1/1");
+ reset_all ();
+ }
+
+ return errors;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"

36
glibc-rh1276761-3.patch Normal file
View File

@ -0,0 +1,36 @@
commit f586e1328681b400078c995a0bb6ad301ef73549
Author: Florian Weimer <fweimer@redhat.com>
Date: Tue Oct 6 13:12:36 2015 +0200
Harden tls_dtor_list with pointer mangling [BZ #19018]
diff --git a/stdlib/cxa_thread_atexit_impl.c b/stdlib/cxa_thread_atexit_impl.c
index 2d5d56a..5717f09 100644
--- a/stdlib/cxa_thread_atexit_impl.c
+++ b/stdlib/cxa_thread_atexit_impl.c
@@ -98,6 +98,10 @@ static __thread struct link_map *lm_cache;
int
__cxa_thread_atexit_impl (dtor_func func, void *obj, void *dso_symbol)
{
+#ifdef PTR_MANGLE
+ PTR_MANGLE (func);
+#endif
+
/* Prepend. */
struct dtor_list *new = calloc (1, sizeof (struct dtor_list));
new->func = func;
@@ -142,9 +146,13 @@ __call_tls_dtors (void)
while (tls_dtor_list)
{
struct dtor_list *cur = tls_dtor_list;
+ dtor_func func = cur->func;
+#ifdef PTR_DEMANGLE
+ PTR_DEMANGLE (func);
+#endif
tls_dtor_list = tls_dtor_list->next;
- cur->func (cur->obj);
+ func (cur->obj);
/* Ensure that the MAP dereference happens before
l_tls_dtor_count decrement. That way, we protect this access from a

16
glibc-rh1282011.patch Normal file
View File

@ -0,0 +1,16 @@
Partial backport of upstream commit 0a410e76f551c6e6cf6d128f618208049d6a952c
(localedata: CLDRv29: update LC_TIME week/first_week,workday fields).
Index: b/localedata/locales/hr_HR
===================================================================
--- a/localedata/locales/hr_HR
+++ b/localedata/locales/hr_HR
@@ -2211,6 +2211,8 @@ t_fmt_ampm ""
date_fmt "<U0025><U0061><U0020><U0025><U0062><U0020><U0025><U0065>/
<U0020><U0025><U0048><U003A><U0025><U004D><U003A><U0025><U0053><U0020>/
<U0025><U005A><U0020><U0025><U0059>"
+week 7;19971130;1
+first_weekday 2
END LC_TIME
LC_PAPER

63
glibc-rh1288662.patch Normal file
View File

@ -0,0 +1,63 @@
Upstream commit:
commit eb32b0d40308166c4d8f6330cc2958cb1e545075
Author: Andreas Schwab <schwab@suse.de>
Date: Mon Aug 10 14:12:47 2015 +0200
Readd O_LARGEFILE flag for openat64 (bug 18781)
diff --git a/io/test-lfs.c b/io/test-lfs.c
index 539c2a2..b6ebae4 100644
--- a/io/test-lfs.c
+++ b/io/test-lfs.c
@@ -144,7 +144,7 @@ test_ftello (void)
int
do_test (int argc, char *argv[])
{
- int ret;
+ int ret, fd2;
struct stat64 statbuf;
ret = lseek64 (fd, TWO_GB+100, SEEK_SET);
@@ -195,6 +195,25 @@ do_test (int argc, char *argv[])
error (EXIT_FAILURE, 0, "stat reported size %lld instead of %lld.",
(long long int) statbuf.st_size, (TWO_GB + 100 + 5));
+ fd2 = openat64 (AT_FDCWD, name, O_RDWR);
+ if (fd2 == -1)
+ {
+ if (errno == ENOSYS)
+ {
+ /* Silently ignore this test. */
+ error (0, 0, "openat64 is not supported");
+ }
+ else
+ error (EXIT_FAILURE, errno, "openat64 failed to open big file");
+ }
+ else
+ {
+ ret = close (fd2);
+
+ if (ret == -1)
+ error (EXIT_FAILURE, errno, "error closing file");
+ }
+
test_ftello ();
return 0;
diff --git a/sysdeps/unix/sysv/linux/openat.c b/sysdeps/unix/sysv/linux/openat.c
index 6777123..ad8e31d 100644
--- a/sysdeps/unix/sysv/linux/openat.c
+++ b/sysdeps/unix/sysv/linux/openat.c
@@ -68,6 +68,11 @@ __OPENAT (int fd, const char *file, int oflag, ...)
va_end (arg);
}
+ /* We have to add the O_LARGEFILE flag for openat64. */
+#ifdef MORE_OFLAGS
+ oflag |= MORE_OFLAGS;
+#endif
+
return SYSCALL_CANCEL (openat, fd, file, oflag, mode);
}
libc_hidden_def (__OPENAT)

21
glibc-rh1288740.patch Normal file
View File

@ -0,0 +1,21 @@
commit e535ce250143b9c1600b306911710c0de73e2a5e
Author: Szabolcs Nagy <szabolcs.nagy@arm.com>
Date: Thu Feb 11 17:17:38 2016 +0000
[ARM] add missing -funwind-tables to test case (bug 19529)
stdlib/tst-makecontext test failed on arm because it used backtrace
without -funwind-tables.
diff --git a/stdlib/Makefile b/stdlib/Makefile
index e406856..26fe67a 100644
--- a/stdlib/Makefile
+++ b/stdlib/Makefile
@@ -112,6 +112,7 @@ CFLAGS-strfmon_l.c = $(libio-mtsafe)
CFLAGS-tst-bsearch.c = $(stack-align-test-flags)
CFLAGS-tst-qsort.c = $(stack-align-test-flags)
+CFLAGS-tst-makecontext.c += -funwind-tables
CFLAGS-tst-makecontext2.c = $(stack-align-test-flags)
# Run a test on the header files we use.

191
glibc-rh1293139.patch Normal file
View File

@ -0,0 +1,191 @@
commit b0e805fa0d6fea33745952df7b7f5442ca4c374f
Author: Mike Frysinger <vapier@gentoo.org>
Date: Fri Aug 28 17:08:49 2015 -0400
getmntent: fix memory corruption w/blank lines [BZ #18887]
The fix for BZ #17273 introduced a single byte of memory corruption when
the line is entirely blank. It would walk back past the start of the
buffer if the heap happened to be 0x20 or 0x09 and then write a NUL byte.
buffer = '\n';
end_ptr = buffer;
while (end_ptr[-1] == ' ' || end_ptr[-1] == '\t')
end_ptr--;
*end_ptr = '\0';
Fix that and rework the tests. Adding the testcase for BZ #17273 to the
existing \040 parser does not really make sense as it's unrelated, and
leads to confusing behavior: it implicitly relies on the new entry being
longer than the previous entry (since it just rewinds the FILE*). Split
it out into its own dedicated testcase instead.
diff --git a/misc/Makefile b/misc/Makefile
index aecb0da..2f5edf6 100644
--- a/misc/Makefile
+++ b/misc/Makefile
@@ -76,7 +76,8 @@ install-lib := libg.a
gpl2lgpl := error.c error.h
tests := tst-dirname tst-tsearch tst-fdset tst-efgcvt tst-mntent tst-hsearch \
- tst-error1 tst-pselect tst-insremque tst-mntent2 bug-hsearch1
+ tst-error1 tst-pselect tst-insremque tst-mntent2 bug-hsearch1 \
+ tst-mntent-blank-corrupt tst-mntent-blank-passno
ifeq ($(run-built-tests),yes)
tests-special += $(objpfx)tst-error1-mem.out
endif
diff --git a/misc/mntent_r.c b/misc/mntent_r.c
index 6159873..4f26998 100644
--- a/misc/mntent_r.c
+++ b/misc/mntent_r.c
@@ -136,7 +136,9 @@ __getmntent_r (FILE *stream, struct mntent *mp, char *buffer, int bufsiz)
end_ptr = strchr (buffer, '\n');
if (end_ptr != NULL) /* chop newline */
{
- while (end_ptr[-1] == ' ' || end_ptr[-1] == '\t')
+ /* Do not walk past the start of buffer if it's all whitespace. */
+ while (end_ptr != buffer
+ && (end_ptr[-1] == ' ' || end_ptr[-1] == '\t'))
end_ptr--;
*end_ptr = '\0';
}
diff --git a/misc/tst-mntent-blank-corrupt.c b/misc/tst-mntent-blank-corrupt.c
new file mode 100644
index 0000000..92266a3
--- /dev/null
+++ b/misc/tst-mntent-blank-corrupt.c
@@ -0,0 +1,45 @@
+/* Make sure blank lines does not cause memory corruption BZ #18887.
+
+ Copyright (C) 2009-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
+ <http://www.gnu.org/licenses/>. */
+
+#include <mntent.h>
+#include <stdio.h>
+#include <string.h>
+
+/* Make sure blank lines don't trigger memory corruption. This doesn't happen
+ for all targets though, so it's a best effort test BZ #18887. */
+static int
+do_test (void)
+{
+ FILE *fp;
+
+ fp = tmpfile ();
+ fputs ("\n \n/foo\\040dir /bar\\040dir auto bind \t \n", fp);
+ rewind (fp);
+
+ /* The corruption happens here ... */
+ getmntent (fp);
+ /* ... but trigers here. */
+ endmntent (fp);
+
+ /* If the test failed, we would crash, and not hit this point. */
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/misc/tst-mntent-blank-passno.c b/misc/tst-mntent-blank-passno.c
new file mode 100644
index 0000000..fc04291
--- /dev/null
+++ b/misc/tst-mntent-blank-passno.c
@@ -0,0 +1,53 @@
+/* Make sure trailing whitespace is handled properly BZ #17273.
+
+ Copyright (C) 2009-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
+ <http://www.gnu.org/licenses/>. */
+
+#include <mntent.h>
+#include <stdio.h>
+#include <string.h>
+
+/* Check entries to make sure trailing whitespace is ignored and we return the
+ correct passno value BZ #17273. */
+static int
+do_test (void)
+{
+ int result = 0;
+ FILE *fp;
+ struct mntent *mnt;
+
+ fp = tmpfile ();
+ fputs ("/foo\\040dir /bar\\040dir auto bind \t \n", fp);
+ rewind (fp);
+
+ mnt = getmntent (fp);
+ if (strcmp (mnt->mnt_fsname, "/foo dir") != 0
+ || strcmp (mnt->mnt_dir, "/bar dir") != 0
+ || strcmp (mnt->mnt_type, "auto") != 0
+ || strcmp (mnt->mnt_opts, "bind") != 0
+ || mnt->mnt_freq != 0
+ || mnt->mnt_passno != 0)
+ {
+ puts ("Error while reading entry with trailing whitespaces");
+ result = 1;
+ }
+
+ return result;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/misc/tst-mntent.c b/misc/tst-mntent.c
index 932fd3f..b6ad8af 100644
--- a/misc/tst-mntent.c
+++ b/misc/tst-mntent.c
@@ -73,26 +73,6 @@ do_test (void)
puts ("Error while reading written entry back in");
result = 1;
}
-
- /* Part III: Entry with whitespaces at the end of a line. */
- rewind (fp);
-
- fputs ("/foo\\040dir /bar\\040dir auto bind \t \n", fp);
-
- rewind (fp);
-
- mnt = getmntent (fp);
-
- if (strcmp (mnt->mnt_fsname, "/foo dir") != 0
- || strcmp (mnt->mnt_dir, "/bar dir") != 0
- || strcmp (mnt->mnt_type, "auto") != 0
- || strcmp (mnt->mnt_opts, "bind") != 0
- || mnt->mnt_freq != 0
- || mnt->mnt_passno != 0)
- {
- puts ("Error while reading entry with trailing whitespaces");
- result = 1;
- }
}
return result;

56
glibc-rh1294574.patch Normal file
View File

@ -0,0 +1,56 @@
commit a8c871a8714b968b1a1e3e679919a2125fc968f3
Author: Andreas Schwab <schwab@suse.de>
Date: Thu Jun 16 12:44:29 2016 +0200
Return proper status from _nss_nis_initgroups_dyn (bug 20262)
(cherry picked from commit 73fb56a4d51fd4437e4cde6dd3c8077a610f88a8)
diff --git a/nis/nss_nis/nis-initgroups.c b/nis/nss_nis/nis-initgroups.c
index ed5c26b..5845b6d 100644
--- a/nis/nss_nis/nis-initgroups.c
+++ b/nis/nss_nis/nis-initgroups.c
@@ -266,7 +266,7 @@ _nss_nis_initgroups_dyn (const char *user, gid_t group, long int *start,
tmpbuf = __alloca (buflen);
- do
+ while (1)
{
while ((status =
internal_getgrent_r (&grpbuf, tmpbuf, buflen, errnop,
@@ -275,8 +275,11 @@ _nss_nis_initgroups_dyn (const char *user, gid_t group, long int *start,
tmpbuf = extend_alloca (tmpbuf, buflen, 2 * buflen);
if (status != NSS_STATUS_SUCCESS)
- goto done;
-
+ {
+ if (status == NSS_STATUS_NOTFOUND)
+ status = NSS_STATUS_SUCCESS;
+ goto done;
+ }
g = &grpbuf;
if (g->gr_gid != group)
@@ -304,7 +307,11 @@ _nss_nis_initgroups_dyn (const char *user, gid_t group, long int *start,
newgroups = realloc (groups, newsize * sizeof (*groups));
if (newgroups == NULL)
- goto done;
+ {
+ status = NSS_STATUS_TRYAGAIN;
+ *errnop = errno;
+ goto done;
+ }
*groupsp = groups = newgroups;
*size = newsize;
}
@@ -316,7 +323,6 @@ _nss_nis_initgroups_dyn (const char *user, gid_t group, long int *start,
}
}
}
- while (status == NSS_STATUS_SUCCESS);
done:
while (intern.start != NULL)

124
glibc-rh1300300.patch Normal file
View File

@ -0,0 +1,124 @@
commit d36c75fc0d44deec29635dd239b0fbd206ca49b7
Author: Paul Pluzhnikov <ppluzhnikov@google.com>
Date: Sat Sep 26 13:27:48 2015 -0700
Fix BZ #18985 -- out of range data to strftime() causes a segfault
diff --git a/time/strftime_l.c b/time/strftime_l.c
index b48ef34..4eb647c 100644
--- a/time/strftime_l.c
+++ b/time/strftime_l.c
@@ -510,13 +510,17 @@ __strftime_internal (s, maxsize, format, tp, tzset_called ut_argument
only a few elements. Dereference the pointers only if the format
requires this. Then it is ok to fail if the pointers are invalid. */
# define a_wkday \
- ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(ABDAY_1) + tp->tm_wday))
+ ((const CHAR_T *) (tp->tm_wday < 0 || tp->tm_wday > 6 \
+ ? "?" : _NL_CURRENT (LC_TIME, NLW(ABDAY_1) + tp->tm_wday)))
# define f_wkday \
- ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(DAY_1) + tp->tm_wday))
+ ((const CHAR_T *) (tp->tm_wday < 0 || tp->tm_wday > 6 \
+ ? "?" : _NL_CURRENT (LC_TIME, NLW(DAY_1) + tp->tm_wday)))
# define a_month \
- ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(ABMON_1) + tp->tm_mon))
+ ((const CHAR_T *) (tp->tm_mon < 0 || tp->tm_mon > 11 \
+ ? "?" : _NL_CURRENT (LC_TIME, NLW(ABMON_1) + tp->tm_mon)))
# define f_month \
- ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(MON_1) + tp->tm_mon))
+ ((const CHAR_T *) (tp->tm_mon < 0 || tp->tm_mon > 11 \
+ ? "?" : _NL_CURRENT (LC_TIME, NLW(MON_1) + tp->tm_mon)))
# define ampm \
((const CHAR_T *) _NL_CURRENT (LC_TIME, tp->tm_hour > 11 \
? NLW(PM_STR) : NLW(AM_STR)))
@@ -526,8 +530,10 @@ __strftime_internal (s, maxsize, format, tp, tzset_called ut_argument
# define ap_len STRLEN (ampm)
#else
# if !HAVE_STRFTIME
-# define f_wkday (weekday_name[tp->tm_wday])
-# define f_month (month_name[tp->tm_mon])
+# define f_wkday (tp->tm_wday < 0 || tp->tm_wday > 6 \
+ ? "?" : weekday_name[tp->tm_wday])
+# define f_month (tp->tm_mon < 0 || tp->tm_mon > 11 \
+ ? "?" : month_name[tp->tm_mon])
# define a_wkday f_wkday
# define a_month f_month
# define ampm (L_("AMPM") + 2 * (tp->tm_hour > 11))
@@ -1321,7 +1327,7 @@ __strftime_internal (s, maxsize, format, tp, tzset_called ut_argument
*tzset_called = true;
}
# endif
- zone = tzname[tp->tm_isdst];
+ zone = tp->tm_isdst <= 1 ? tzname[tp->tm_isdst] : "?";
}
#endif
if (! zone)
diff --git a/time/tst-strftime.c b/time/tst-strftime.c
index 374fba4..af3ff72 100644
--- a/time/tst-strftime.c
+++ b/time/tst-strftime.c
@@ -4,6 +4,56 @@
#include <time.h>
+static int
+do_bz18985 (void)
+{
+ char buf[1000];
+ struct tm ttm;
+ int rc, ret = 0;
+
+ memset (&ttm, 1, sizeof (ttm));
+ ttm.tm_zone = NULL; /* Dereferenced directly if non-NULL. */
+ rc = strftime (buf, sizeof (buf), "%a %A %b %B %c %z %Z", &ttm);
+
+ if (rc == 66)
+ {
+ const char expected[]
+ = "? ? ? ? ? ? 16843009 16843009:16843009:16843009 16844909 +467836 ?";
+ if (0 != strcmp (buf, expected))
+ {
+ printf ("expected:\n %s\ngot:\n %s\n", expected, buf);
+ ret += 1;
+ }
+ }
+ else
+ {
+ printf ("expected 66, got %d\n", rc);
+ ret += 1;
+ }
+
+ /* Check negative values as well. */
+ memset (&ttm, 0xFF, sizeof (ttm));
+ ttm.tm_zone = NULL; /* Dereferenced directly if non-NULL. */
+ rc = strftime (buf, sizeof (buf), "%a %A %b %B %c %z %Z", &ttm);
+
+ if (rc == 30)
+ {
+ const char expected[] = "? ? ? ? ? ? -1 -1:-1:-1 1899 ";
+ if (0 != strcmp (buf, expected))
+ {
+ printf ("expected:\n %s\ngot:\n %s\n", expected, buf);
+ ret += 1;
+ }
+ }
+ else
+ {
+ printf ("expected 30, got %d\n", rc);
+ ret += 1;
+ }
+
+ return ret;
+}
+
static struct
{
const char *fmt;
@@ -104,7 +154,7 @@ do_test (void)
}
}
- return result;
+ return result + do_bz18985 ();
}
#define TEST_FUNCTION do_test ()

41
glibc-rh1300304-1.patch Normal file
View File

@ -0,0 +1,41 @@
commit 2f5c1750558fe64bac361f52d6827ab1bcfe52bc
Author: Ondřej Bílka <neleai@seznam.cz>
Date: Sat Jul 11 17:44:10 2015 +0200
Handle overflow in __hcreate_r
Hi,
As in bugzilla entry there is overflow in hsearch when looking for prime
number as SIZE_MAX - 1 is divisible by 5. We fix that by rejecting large
inputs before looking for prime.
* misc/hsearch_r.c (__hcreate_r): Handle overflow.
diff --git a/misc/hsearch_r.c b/misc/hsearch_r.c
index 9f55e84..559df29 100644
--- a/misc/hsearch_r.c
+++ b/misc/hsearch_r.c
@@ -19,7 +19,7 @@
#include <errno.h>
#include <malloc.h>
#include <string.h>
-
+#include <stdint.h>
#include <search.h>
/* [Aho,Sethi,Ullman] Compilers: Principles, Techniques and Tools, 1986
@@ -73,6 +73,13 @@ __hcreate_r (nel, htab)
return 0;
}
+ if (nel >= SIZE_MAX / sizeof (_ENTRY))
+ {
+ __set_errno (ENOMEM);
+ return 0;
+ }
+
+
/* There is still another table active. Return with error. */
if (htab->table != NULL)
return 0;

148
glibc-rh1300304-2.patch Normal file
View File

@ -0,0 +1,148 @@
commit bae7c7c764413b23e61cb099ce33be4c4ee259bb
Author: Florian Weimer <fweimer@redhat.com>
Date: Thu Jan 28 13:59:11 2016 +0100
Improve check against integer wraparound in hcreate_r [BZ #18240]
Index: b/misc/bug18240.c
===================================================================
--- /dev/null
+++ b/misc/bug18240.c
@@ -0,0 +1,75 @@
+/* Test integer wraparound in hcreate.
+ Copyright (C) 2016 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
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <limits.h>
+#include <search.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+static void
+test_size (size_t size)
+{
+ int res = hcreate (size);
+ if (res == 0)
+ {
+ if (errno == ENOMEM)
+ return;
+ printf ("error: hcreate (%zu): %m\n", size);
+ exit (1);
+ }
+ char *keys[100];
+ for (int i = 0; i < 100; ++i)
+ {
+ if (asprintf (keys + i, "%d", i) < 0)
+ {
+ printf ("error: asprintf: %m\n");
+ exit (1);
+ }
+ ENTRY e = { keys[i], (char *) "value" };
+ if (hsearch (e, ENTER) == NULL)
+ {
+ printf ("error: hsearch (\"%s\"): %m\n", keys[i]);
+ exit (1);
+ }
+ }
+ hdestroy ();
+
+ for (int i = 0; i < 100; ++i)
+ free (keys[i]);
+}
+
+static int
+do_test (void)
+{
+ test_size (500);
+ test_size (-1);
+ test_size (-3);
+ test_size (INT_MAX - 2);
+ test_size (INT_MAX - 1);
+ test_size (INT_MAX);
+ test_size (((unsigned) INT_MAX) + 1);
+ test_size (UINT_MAX - 2);
+ test_size (UINT_MAX - 1);
+ test_size (UINT_MAX);
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
Index: b/misc/hsearch_r.c
===================================================================
--- a/misc/hsearch_r.c
+++ b/misc/hsearch_r.c
@@ -46,15 +46,12 @@ static int
isprime (unsigned int number)
{
/* no even number will be passed */
- unsigned int div = 3;
-
- while (div * div < number && number % div != 0)
- div += 2;
-
- return number % div != 0;
+ for (unsigned int div = 3; div <= number / div; div += 2)
+ if (number % div == 0)
+ return 0;
+ return 1;
}
-
/* Before using the hash table we must allocate memory for it.
Test for an existing table are done. We allocate one element
more as the found prime number says. This is done for more effective
@@ -73,13 +70,6 @@ __hcreate_r (nel, htab)
return 0;
}
- if (nel >= SIZE_MAX / sizeof (_ENTRY))
- {
- __set_errno (ENOMEM);
- return 0;
- }
-
-
/* There is still another table active. Return with error. */
if (htab->table != NULL)
return 0;
@@ -88,10 +78,19 @@ __hcreate_r (nel, htab)
use will not work. */
if (nel < 3)
nel = 3;
- /* Change nel to the first prime number not smaller as nel. */
- nel |= 1; /* make odd */
- while (!isprime (nel))
- nel += 2;
+
+ /* Change nel to the first prime number in the range [nel, UINT_MAX - 2],
+ The '- 2' means 'nel += 2' cannot overflow. */
+ for (nel |= 1; ; nel += 2)
+ {
+ if (UINT_MAX - 2 < nel)
+ {
+ __set_errno (ENOMEM);
+ return 0;
+ }
+ if (isprime (nel))
+ break;
+ }
htab->size = nel;
htab->filled = 0;

46
glibc-rh1300304-3.patch Normal file
View File

@ -0,0 +1,46 @@
commit f34f146e682d8d529dcf64b3c2781bf3f2f05f6c
Author: Florian Weimer <fweimer@redhat.com>
Date: Fri Feb 12 12:57:40 2016 +0100
hsearch_r: Apply VM size limit in test case
diff --git a/misc/bug18240.c b/misc/bug18240.c
index 4b26865..773586e 100644
--- a/misc/bug18240.c
+++ b/misc/bug18240.c
@@ -22,6 +22,7 @@
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
+#include <sys/resource.h>
static void
test_size (size_t size)
@@ -58,6 +59,27 @@ test_size (size_t size)
static int
do_test (void)
{
+ /* Limit the size of the process, so that memory allocation will
+ fail without impacting the entire system. */
+ {
+ struct rlimit limit;
+ if (getrlimit (RLIMIT_AS, &limit) != 0)
+ {
+ printf ("getrlimit (RLIMIT_AS) failed: %m\n");
+ return 1;
+ }
+ long target = 100 * 1024 * 1024;
+ if (limit.rlim_cur == RLIM_INFINITY || limit.rlim_cur > target)
+ {
+ limit.rlim_cur = target;
+ if (setrlimit (RLIMIT_AS, &limit) != 0)
+ {
+ printf ("setrlimit (RLIMIT_AS) failed: %m\n");
+ return 1;
+ }
+ }
+ }
+
test_size (500);
test_size (-1);
test_size (-3);

259
glibc-rh1300311-1.patch Normal file
View File

@ -0,0 +1,259 @@
commit f881f6ff62bba53448c5d8997287ea2e628b3a65
Author: Andreas Schwab <schwab@suse.de>
Date: Mon Oct 12 12:24:41 2015 +0200
Add dependencies on needed locales in each subdir tests (bug 18969)
Index: b/debug/Makefile
===================================================================
--- a/debug/Makefile
+++ b/debug/Makefile
@@ -162,6 +162,13 @@ generated += catchsegv xtrace
include ../Rules
+ifeq ($(run-built-tests),yes)
+LOCALES := de_DE.UTF-8
+include ../gen-locales.mk
+
+$(objpfx)tst-chk1.out: $(gen-locales)
+endif
+
sLIBdir := $(shell echo $(slibdir) | sed 's,lib\(\|64\)$$,\\\\$$LIB,')
$(objpfx)catchsegv: catchsegv.sh $(common-objpfx)soversions.mk \
Index: b/iconvdata/Makefile
===================================================================
--- a/iconvdata/Makefile
+++ b/iconvdata/Makefile
@@ -271,6 +271,14 @@ endif
include ../Rules
+ifeq ($(run-built-tests),yes)
+LOCALES := de_DE.UTF-8
+include ../gen-locales.mk
+
+$(objpfx)bug-iconv6.out: $(gen-locales)
+$(objpfx)tst-iconv7.out: $(gen-locales)
+endif
+
# Set libof-* for each routine.
cpp-srcs-left := $(modules) $(generated-modules) $(libJIS-routines) \
$(libKSC-routines) $(libGB-routines) $(libCNS-routines) \
Index: b/intl/Makefile
===================================================================
--- a/intl/Makefile
+++ b/intl/Makefile
@@ -105,6 +105,19 @@ $(objpfx)tst-codeset.out: $(codeset_mo)
$(objpfx)tst-gettext3.out: $(codeset_mo)
$(objpfx)tst-gettext5.out: $(codeset_mo)
endif
+
+LOCALES := de_DE.ISO-8859-1 de_DE.UTF-8 en_US.ANSI_X3.4-1968 fr_FR.ISO-8859-1 \
+ ja_JP.UTF-8
+include ../gen-locales.mk
+
+$(objpfx)tst-codeset.out: $(gen-locales)
+$(objpfx)tst-gettext.out: $(gen-locales)
+$(objpfx)tst-gettext2.out: $(gen-locales)
+$(objpfx)tst-gettext3.out: $(gen-locales)
+$(objpfx)tst-gettext4.out: $(gen-locales)
+$(objpfx)tst-gettext5.out: $(gen-locales)
+$(objpfx)tst-gettext6.out: $(gen-locales)
+$(objpfx)tst-translit.out: $(gen-locales)
endif
$(objpfx)msgs.h: po2test.awk ../po/de.po
Index: b/libio/Makefile
===================================================================
--- a/libio/Makefile
+++ b/libio/Makefile
@@ -174,6 +174,30 @@ endif
include ../Rules
+ifeq ($(run-built-tests),yes)
+LOCALES := de_DE.ISO-8859-1 de_DE.UTF-8 en_US.ISO-8859-1 en_US.UTF-8 \
+ ja_JP.EUC-JP ja_JP.UTF-8
+include ../gen-locales.mk
+
+$(objpfx)bug-ftell.out: $(gen-locales)
+$(objpfx)bug-ungetwc1.out: $(gen-locales)
+$(objpfx)bug-ungetwc2.out: $(gen-locales)
+$(objpfx)tst-fgetwc.out: $(gen-locales)
+$(objpfx)tst-fgetws.out: $(gen-locales)
+$(objpfx)tst-fopenloc.out: $(gen-locales)
+$(objpfx)tst-fputws.out: $(gen-locales)
+$(objpfx)tst-fseek.out: $(gen-locales)
+$(objpfx)tst-ftell-active-handler.out: $(gen-locales)
+$(objpfx)tst-ftell-append.out: $(gen-locales)
+$(objpfx)tst-ftell-partial-wide.out: $(gen-locales)
+$(objpfx)tst-setvbuf1.out: $(gen-locales)
+$(objpfx)tst-swscanf.out: $(gen-locales)
+$(objpfx)tst-ungetwc1.out: $(gen-locales)
+$(objpfx)tst-ungetwc2.out: $(gen-locales)
+$(objpfx)tst-widetext.out: $(gen-locales)
+$(objpfx)tst_wprintf2.out: $(gen-locales)
+endif
+
$(objpfx)test-freopen.out: test-freopen.sh $(objpfx)test-freopen
$(SHELL) $< $(common-objpfx) '$(test-program-prefix)' \
$(common-objpfx)libio/; \
Index: b/libio/tst_wprintf2.c
===================================================================
--- a/libio/tst_wprintf2.c
+++ b/libio/tst_wprintf2.c
@@ -26,7 +26,7 @@ main (int argc, char *argv[])
unlink (name);
- setlocale (LC_ALL, "");
+ setlocale (LC_ALL, "en_US.UTF-8");
fp = fdopen (dup (fd), "w");
if (fp == NULL)
Index: b/posix/Makefile
===================================================================
--- a/posix/Makefile
+++ b/posix/Makefile
@@ -148,6 +148,36 @@ $(objpfx)wordexp-tst.out: wordexp-tst.sh
'$(run-program-env)' '$(test-program-prefix-after-env)'; \
$(evaluate-test)
endif
+
+LOCALES := cs_CZ.UTF-8 da_DK.ISO-8859-1 de_DE.ISO-8859-1 de_DE.UTF-8 \
+ en_US.UTF-8 es_US.ISO-8859-1 es_US.UTF-8 ja_JP.EUC-JP tr_TR.UTF-8
+include ../gen-locales.mk
+
+$(objpfx)bug-regex1.out: $(gen-locales)
+$(objpfx)bug-regex4.out: $(gen-locales)
+$(objpfx)bug-regex5.out: $(gen-locales)
+$(objpfx)bug-regex6.out: $(gen-locales)
+$(objpfx)bug-regex17.out: $(gen-locales)
+$(objpfx)bug-regex18.out: $(gen-locales)
+$(objpfx)bug-regex19.out: $(gen-locales)
+$(objpfx)bug-regex20.out: $(gen-locales)
+$(objpfx)bug-regex22.out: $(gen-locales)
+$(objpfx)bug-regex23.out: $(gen-locales)
+$(objpfx)bug-regex25.out: $(gen-locales)
+$(objpfx)bug-regex26.out: $(gen-locales)
+$(objpfx)bug-regex30.out: $(gen-locales)
+$(objpfx)bug-regex32.out: $(gen-locales)
+$(objpfx)bug-regex33.out: $(gen-locales)
+$(objpfx)bug-regex34.out: $(gen-locales)
+$(objpfx)bug-regex35.out: $(gen-locales)
+$(objpfx)tst-fnmatch.out: $(gen-locales)
+$(objpfx)tst-fnmatch4.out: $(gen-locales)
+$(objpfx)tst-fnmatch5.out: $(gen-locales)
+$(objpfx)tst-regex.out: $(gen-locales)
+$(objpfx)tst-regex2.out: $(gen-locales)
+$(objpfx)tst-regexloc.out: $(gen-locales)
+$(objpfx)tst-rxspencer.out: $(gen-locales)
+$(objpfx)tst-rxspencer-no-utf8.out: $(gen-locales)
endif
# If we will use the generic uname implementation, we must figure out what
Index: b/stdio-common/Makefile
===================================================================
--- a/stdio-common/Makefile
+++ b/stdio-common/Makefile
@@ -69,6 +69,19 @@ endif
include ../Rules
ifeq ($(run-built-tests),yes)
+LOCALES := de_DE.ISO-8859-1 de_DE.UTF-8 en_US.ISO-8859-1 ja_JP.EUC-JP
+include ../gen-locales.mk
+
+$(objpfx)bug14.out: $(gen-locales)
+$(objpfx)scanf13.out: $(gen-locales)
+$(objpfx)test-vfprintf.out: $(gen-locales)
+$(objpfx)tst-grouping.out: $(gen-locales)
+$(objpfx)tst-sprintf.out: $(gen-locales)
+$(objpfx)tst-sscanf.out: $(gen-locales)
+$(objpfx)tst-swprintf.out: $(gen-locales)
+endif
+
+ifeq ($(run-built-tests),yes)
$(objpfx)tst-unbputc.out: tst-unbputc.sh $(objpfx)tst-unbputc
$(SHELL) $< $(common-objpfx) '$(test-program-prefix)'; \
$(evaluate-test)
Index: b/stdlib/Makefile
===================================================================
--- a/stdlib/Makefile
+++ b/stdlib/Makefile
@@ -121,6 +121,18 @@ endif
include ../Rules
+ifeq ($(run-built-tests),yes)
+LOCALES := cs_CZ.UTF-8 de_DE.UTF-8 en_US.ISO-8859-1 tr_TR.UTF-8
+include ../gen-locales.mk
+
+$(objpfx)bug-strtod2.out: $(gen-locales)
+$(objpfx)testmb2.out: $(gen-locales)
+$(objpfx)tst-strtod.out: $(gen-locales)
+$(objpfx)tst-strtod3.out: $(gen-locales)
+$(objpfx)tst-strtod4.out: $(gen-locales)
+$(objpfx)tst-strtod5.out: $(gen-locales)
+endif
+
# Testdir has to be named stdlib and needs to be writable
test-canon-ARGS = --test-dir=${common-objpfx}stdlib
Index: b/time/Makefile
===================================================================
--- a/time/Makefile
+++ b/time/Makefile
@@ -41,6 +41,14 @@ tests := test_time clocktest tst-posixtz
include ../Rules
+ifeq ($(run-built-tests),yes)
+LOCALES := de_DE.ISO-8859-1 en_US.ISO-8859-1 ja_JP.EUC-JP
+include ../gen-locales.mk
+
+$(objpfx)tst-ftime_l.out: $(gen-locales)
+$(objpfx)tst-strptime.out: $(gen-locales)
+endif
+
tz-cflags = -DTZDIR='"$(zonedir)"' \
-DTZDEFAULT='"$(localtime-file)"' \
-DTZDEFRULES='"$(posixrules-file)"'
Index: b/wcsmbs/Makefile
===================================================================
--- a/wcsmbs/Makefile
+++ b/wcsmbs/Makefile
@@ -49,6 +49,19 @@ tests := tst-wcstof wcsmbs-tst1 tst-wcsn
include ../Rules
+ifeq ($(run-built-tests),yes)
+LOCALES := de_DE.ISO-8859-1 de_DE.UTF-8 en_US.ANSI_X3.4-1968 hr_HR.ISO-8859-2 \
+ ja_JP.EUC-JP zh_TW.EUC-TW
+include ../gen-locales.mk
+
+$(objpfx)tst-btowc.out: $(gen-locales)
+$(objpfx)tst-c16c32-1.out: $(gen-locales)
+$(objpfx)tst-mbrtowc.out: $(gen-locales)
+$(objpfx)tst-mbrtowc2.out: $(gen-locales)
+$(objpfx)tst-wcrtomb.out: $(gen-locales)
+$(objpfx)wcsmbs-tst1.out: $(gen-locales)
+endif
+
CFLAGS-wcwidth.c = -I../wctype
CFLAGS-wcswidth.c = -I../wctype
Index: b/wcsmbs/wcsmbs-tst1.c
===================================================================
--- a/wcsmbs/wcsmbs-tst1.c
+++ b/wcsmbs/wcsmbs-tst1.c
@@ -18,7 +18,7 @@ main (void)
char str[] = "Hello";
int result = 0;
- pchar = setlocale (LC_ALL, "");
+ pchar = setlocale (LC_ALL, "de_DE.UTF-8");
printf ("locale : %s\n",pchar);
printf ("MB_CUR_MAX %Zd\n", MB_CUR_MAX);

285
glibc-rh1300311-2.patch Normal file
View File

@ -0,0 +1,285 @@
commit f5eee5c72b2ab56f3faf4f46729fe82805efde68
Author: Joseph Myers <joseph@codesourcery.com>
Date: Mon Nov 23 08:50:53 2015 +0000
Fix strtol in Turkish locales (bug 19242).
The implementations of strtol and related functions use
locale-specific conversions to upper case before determining whether a
character is a valid letter in the argument. This means that in
Turkish locales such as tr_TR.UTF-8 and tr_TR.ISO-8859-9, "i" is
interpreted as not being a valid number, when if the base passed to
strtol is 19 or more it should be interpreted as the number 18.
ISO C explicitly says "The letters from a (or A) through z (or Z) are
ascribed the values 10 through 35", so clearly intends the standard
ASCII letters (otherwise you wouldn't generally have exactly 26
letters to ascribe such values) (whereas white-space must be
identified according to the locale). In particular, 'i' and 'I' must
be understood to be in that sequence.
This patch makes the code do the case conversions and classification
in the C locale; the user's locale remains used for whitespace testing
(explicitly correct according to ISO C). Note that the way the code
worked, the only non-ASCII letter that would previously have been
accepted would have been the Turkish 'ı' (dotless 'i'), because the
uppercase version of that in Turkish locales is 'I'. This patch means
that will no longer be accepted, which seems appropriate.
Tested for x86_64 and x86.
[BZ #19242]
* stdlib/strtol_l.c (ISALPHA): Use _nl_C_locobj_ptr for locale.
(TOUPPER): Likewise.
* stdlib/tst-strtol-locale-main.c: New file.
* stdlib/tst-strtol-locale.c: Likewise.
* stdlib/Makefile (tests): Add tst-strtol-locale.
[$(run-built-tests) = yes] (LOCALES): Add tr_TR.ISO-8859-9.
[$(run-built-tests) = yes] ($(objpfx)tst-strtol-locale.out):
Depend on $(gen-locales).
* wcsmbs/tst-wcstol-locale.c: New file.
* wcsmbs/Makefile (tests): Add tst-wcstol-locale.
[$(run-built-tests) = yes] (LOCALES): Add tr_TR.UTF-8 and
tr_TR.ISO-8859-9.
[$(run-built-tests) = yes] ($(objpfx)tst-wcstol-locale.out):
Depend on $(gen-locales).
Index: b/stdlib/Makefile
===================================================================
--- a/stdlib/Makefile
+++ b/stdlib/Makefile
@@ -74,7 +74,8 @@ tests := tst-strtol tst-strtod testmb t
tst-makecontext3 bug-getcontext bug-fmtmsg1 \
tst-secure-getenv tst-strtod-overflow tst-strtod-round \
tst-tininess tst-strtod-underflow tst-tls-atexit \
- tst-setcontext3 tst-tls-atexit-nodelete
+ tst-setcontext3 tst-tls-atexit-nodelete \
+ tst-strtol-locale
tests-static := tst-secure-getenv
modules-names = tst-tls-atexit-lib
@@ -122,7 +123,8 @@ endif
include ../Rules
ifeq ($(run-built-tests),yes)
-LOCALES := cs_CZ.UTF-8 de_DE.UTF-8 en_US.ISO-8859-1 tr_TR.UTF-8
+LOCALES := cs_CZ.UTF-8 de_DE.UTF-8 en_US.ISO-8859-1 tr_TR.UTF-8 \
+ tr_TR.ISO-8859-9
include ../gen-locales.mk
$(objpfx)bug-strtod2.out: $(gen-locales)
@@ -131,6 +133,7 @@ $(objpfx)tst-strtod.out: $(gen-locales)
$(objpfx)tst-strtod3.out: $(gen-locales)
$(objpfx)tst-strtod4.out: $(gen-locales)
$(objpfx)tst-strtod5.out: $(gen-locales)
+$(objpfx)tst-strtol-locale.out: $(gen-locales)
endif
# Testdir has to be named stdlib and needs to be writable
Index: b/stdlib/strtol_l.c
===================================================================
--- a/stdlib/strtol_l.c
+++ b/stdlib/strtol_l.c
@@ -137,8 +137,8 @@
# define UCHAR_TYPE wint_t
# define STRING_TYPE wchar_t
# define ISSPACE(Ch) __iswspace_l ((Ch), loc)
-# define ISALPHA(Ch) __iswalpha_l ((Ch), loc)
-# define TOUPPER(Ch) __towupper_l ((Ch), loc)
+# define ISALPHA(Ch) __iswalpha_l ((Ch), _nl_C_locobj_ptr)
+# define TOUPPER(Ch) __towupper_l ((Ch), _nl_C_locobj_ptr)
#else
# if defined _LIBC \
|| defined STDC_HEADERS || (!defined isascii && !defined HAVE_ISASCII)
@@ -150,8 +150,8 @@
# define UCHAR_TYPE unsigned char
# define STRING_TYPE char
# define ISSPACE(Ch) __isspace_l ((Ch), loc)
-# define ISALPHA(Ch) __isalpha_l ((Ch), loc)
-# define TOUPPER(Ch) __toupper_l ((Ch), loc)
+# define ISALPHA(Ch) __isalpha_l ((Ch), _nl_C_locobj_ptr)
+# define TOUPPER(Ch) __toupper_l ((Ch), _nl_C_locobj_ptr)
#endif
#define INTERNAL(X) INTERNAL1(X)
Index: b/stdlib/tst-strtol-locale-main.c
===================================================================
--- /dev/null
+++ b/stdlib/tst-strtol-locale-main.c
@@ -0,0 +1,87 @@
+/* Test strtol functions work with all ASCII letters in Turkish
+ locales (bug 19242).
+ 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
+ <http://www.gnu.org/licenses/>. */
+
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <wchar.h>
+
+#define STR_(X) #X
+#define STR(X) STR_(X)
+#define FNPFXS STR (FNPFX)
+#define CONCAT_(X, Y) X ## Y
+#define CONCAT(X, Y) CONCAT_ (X, Y)
+#define FNX(FN) CONCAT (FNPFX, FN)
+
+#define TEST(LOC, STR, EXP_VAL, FN, TYPE, FMT) \
+ do \
+ { \
+ CHAR *ep; \
+ TYPE val = FNX (FN) (STR, &ep, 36); \
+ printf ("%s: " FNPFXS #FN " (" SFMT ") == " FMT "\n", LOC, STR, val); \
+ if (val == (TYPE) (EXP_VAL) && *ep == 0) \
+ printf ("PASS: %s: " FNPFXS #FN " (" SFMT ")\n", LOC, STR); \
+ else \
+ { \
+ printf ("FAIL: %s: " FNPFXS #FN " (" SFMT ")\n", LOC, STR); \
+ result = 1; \
+ } \
+ } \
+ while (0)
+
+static int
+test_one_locale (const char *loc)
+{
+ if (setlocale (LC_ALL, loc) == NULL)
+ {
+ printf ("setlocale (LC_ALL, \"%s\") failed\n", loc);
+ return 1;
+ }
+ int result = 0;
+ for (int i = 10; i < 36; i++)
+ {
+ CHAR s[2];
+ s[0] = L_('A') + i - 10;
+ s[1] = 0;
+ TEST (loc, s, i, l, long int, "%ld");
+ TEST (loc, s, i, ul, unsigned long int, "%lu");
+ TEST (loc, s, i, ll, long long int, "%lld");
+ TEST (loc, s, i, ull, unsigned long long int, "%llu");
+ s[0] = L_('a') + i - 10;
+ s[1] = 0;
+ TEST (loc, s, i, l, long int, "%ld");
+ TEST (loc, s, i, ul, unsigned long int, "%lu");
+ TEST (loc, s, i, ll, long long int, "%lld");
+ TEST (loc, s, i, ull, unsigned long long int, "%llu");
+ }
+ return result;
+}
+
+static int
+do_test (void)
+{
+ int result = 0;
+ result |= test_one_locale ("C");
+ result |= test_one_locale ("tr_TR.UTF-8");
+ result |= test_one_locale ("tr_TR.ISO-8859-9");
+ return result;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
Index: b/stdlib/tst-strtol-locale.c
===================================================================
--- /dev/null
+++ b/stdlib/tst-strtol-locale.c
@@ -0,0 +1,25 @@
+/* Test strtol functions work with all ASCII letters in Turkish
+ locales (bug 19242). Narrow string version.
+ 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
+ <http://www.gnu.org/licenses/>. */
+
+#define CHAR char
+#define SFMT "\"%s\""
+#define FNPFX strto
+#define L_(C) C
+
+#include <tst-strtol-locale-main.c>
Index: b/wcsmbs/Makefile
===================================================================
--- a/wcsmbs/Makefile
+++ b/wcsmbs/Makefile
@@ -45,13 +45,14 @@ routines := wcscat wcschr wcscmp wcscpy
strop-tests := wcscmp wcsncmp wmemcmp wcslen wcschr wcsrchr wcscpy
tests := tst-wcstof wcsmbs-tst1 tst-wcsnlen tst-btowc tst-mbrtowc \
tst-wcrtomb tst-wcpncpy tst-mbsrtowcs tst-wchar-h tst-mbrtowc2 \
- tst-c16c32-1 wcsatcliff $(addprefix test-,$(strop-tests))
+ tst-c16c32-1 wcsatcliff tst-wcstol-locale \
+ $(addprefix test-,$(strop-tests))
include ../Rules
ifeq ($(run-built-tests),yes)
LOCALES := de_DE.ISO-8859-1 de_DE.UTF-8 en_US.ANSI_X3.4-1968 hr_HR.ISO-8859-2 \
- ja_JP.EUC-JP zh_TW.EUC-TW
+ ja_JP.EUC-JP zh_TW.EUC-TW tr_TR.UTF-8 tr_TR.ISO-8859-9
include ../gen-locales.mk
$(objpfx)tst-btowc.out: $(gen-locales)
@@ -60,6 +61,7 @@ $(objpfx)tst-mbrtowc.out: $(gen-locales)
$(objpfx)tst-mbrtowc2.out: $(gen-locales)
$(objpfx)tst-wcrtomb.out: $(gen-locales)
$(objpfx)wcsmbs-tst1.out: $(gen-locales)
+$(objpfx)tst-wcstol-locale.out: $(gen-locales)
endif
CFLAGS-wcwidth.c = -I../wctype
Index: b/wcsmbs/tst-wcstol-locale.c
===================================================================
--- /dev/null
+++ b/wcsmbs/tst-wcstol-locale.c
@@ -0,0 +1,25 @@
+/* Test strtol functions work with all ASCII letters in Turkish
+ locales (bug 19242). Wide string version.
+ 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
+ <http://www.gnu.org/licenses/>. */
+
+#define CHAR wchar_t
+#define SFMT "L\"%ls\""
+#define FNPFX wcsto
+#define L_(C) L ## C
+
+#include "../stdlib/tst-strtol-locale-main.c"

265
glibc-rh1300311-3.patch Normal file
View File

@ -0,0 +1,265 @@
commit a7f0c5ae4184916f0e145de3aefc794bf2e280ad
Author: Joseph Myers <joseph@codesourcery.com>
Date: Tue Nov 24 22:21:59 2015 +0000
Fix strtod ("NAN(I)") in Turkish locales (bug 19266).
The implementations of strtod and related functions use
locale-specific conversions to lower case when parsing the contents of
a string NAN(n-char-sequence_opt). This has the consequence that
NAN(I) is not treated as being of that form (only the initial NAN part
is accepted). The syntax of n-char-sequence directly maps to the
ASCII letters, digits and underscore as in identifiers, so it is
unambiguous that all ASCII letters must be accepted in all locales.
This patch, relative to a tree with
<https://sourceware.org/ml/libc-alpha/2015-11/msg00258.html> (pending
review) applied and depending on that patch, fixes this problem by
checking directly for ASCII letters. This will have the side effect
of no longer accepting 'İ' (dotted 'I') inside NAN() in Turkish
locales, which seems appropriate (that letter wouldn't have been
interpreted as having any meaning in the NaN payload anyway, as not
acceptable to strtoull).
Tested for x86_64 and x86.
[BZ #19266]
* stdlib/strtod_l.c (____STRTOF_INTERNAL): Check directly for
upper case and lower case letters inside NAN(), not using TOLOWER.
* stdlib/tst-strtod-nan-locale-main.c: New file.
* stdlib/tst-strtod-nan-locale.c: Likewise.
* stdlib/Makefile (tests): Add tst-strtod-nan-locale.
[$(run-built-tests) = yes] ($(objpfx)tst-strtod-nan-locale.out):
Depend on $(gen-locales).
($(objpfx)tst-strtod-nan-locale): Depend on $(libm).
* wcsmbs/tst-wcstod-nan-locale.c: New file.
* wcsmbs/Makefile (tests): Add tst-wcstod-nan-locale.
[$(run-built-tests) = yes] ($(objpfx)tst-wcstod-nan-locale.out):
Depend on $(gen-locales).
($(objpfx)tst-wcstod-nan-locale): Depend on $(libm).
Index: b/stdlib/Makefile
===================================================================
--- a/stdlib/Makefile
+++ b/stdlib/Makefile
@@ -75,7 +75,7 @@ tests := tst-strtol tst-strtod testmb t
tst-secure-getenv tst-strtod-overflow tst-strtod-round \
tst-tininess tst-strtod-underflow tst-tls-atexit \
tst-setcontext3 tst-tls-atexit-nodelete \
- tst-strtol-locale
+ tst-strtol-locale tst-strtod-nan-locale
tests-static := tst-secure-getenv
modules-names = tst-tls-atexit-lib
@@ -134,6 +134,7 @@ $(objpfx)tst-strtod3.out: $(gen-locales)
$(objpfx)tst-strtod4.out: $(gen-locales)
$(objpfx)tst-strtod5.out: $(gen-locales)
$(objpfx)tst-strtol-locale.out: $(gen-locales)
+$(objpfx)tst-strtod-nan-locale.out: $(gen-locales)
endif
# Testdir has to be named stdlib and needs to be writable
@@ -168,6 +169,7 @@ $(objpfx)tst-strtod-round: $(libm)
$(objpfx)tst-tininess: $(libm)
$(objpfx)tst-strtod-underflow: $(libm)
$(objpfx)tst-strtod6: $(libm)
+$(objpfx)tst-strtod-nan-locale: $(libm)
tst-tls-atexit-lib.so-no-z-defs = yes
Index: b/stdlib/strtod_l.c
===================================================================
--- a/stdlib/strtod_l.c
+++ b/stdlib/strtod_l.c
@@ -658,8 +658,8 @@ ____STRTOF_INTERNAL (nptr, endptr, group
do
++cp;
while ((*cp >= L_('0') && *cp <= L_('9'))
- || ({ CHAR_TYPE lo = TOLOWER (*cp);
- lo >= L_('a') && lo <= L_('z'); })
+ || (*cp >= L_('A') && *cp <= L_('Z'))
+ || (*cp >= L_('a') && *cp <= L_('z'))
|| *cp == L_('_'));
if (*cp != L_(')'))
Index: b/stdlib/tst-strtod-nan-locale-main.c
===================================================================
--- /dev/null
+++ b/stdlib/tst-strtod-nan-locale-main.c
@@ -0,0 +1,89 @@
+/* Test strtod functions work with all ASCII letters in NAN(...) in
+ Turkish locales (bug 19266).
+ 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
+ <http://www.gnu.org/licenses/>. */
+
+#include <locale.h>
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <wchar.h>
+
+#define STR_(X) #X
+#define STR(X) STR_(X)
+#define FNPFXS STR (FNPFX)
+#define CONCAT_(X, Y) X ## Y
+#define CONCAT(X, Y) CONCAT_ (X, Y)
+#define FNX(FN) CONCAT (FNPFX, FN)
+
+#define TEST(LOC, STR, FN, TYPE) \
+ do \
+ { \
+ CHAR *ep; \
+ TYPE val = FNX (FN) (STR, &ep); \
+ if (isnan (val) && *ep == 0) \
+ printf ("PASS: %s: " FNPFXS #FN " (" SFMT ")\n", LOC, STR); \
+ else \
+ { \
+ printf ("FAIL: %s: " FNPFXS #FN " (" SFMT ")\n", LOC, STR); \
+ result = 1; \
+ } \
+ } \
+ while (0)
+
+static int
+test_one_locale (const char *loc)
+{
+ if (setlocale (LC_ALL, loc) == NULL)
+ {
+ printf ("setlocale (LC_ALL, \"%s\") failed\n", loc);
+ return 1;
+ }
+ int result = 0;
+ for (int i = 10; i < 36; i++)
+ {
+ CHAR s[7];
+ s[0] = L_('N');
+ s[1] = L_('A');
+ s[2] = L_('N');
+ s[3] = L_('(');
+ s[4] = L_('A') + i - 10;
+ s[5] = L_(')');
+ s[6] = 0;
+ TEST (loc, s, f, float);
+ TEST (loc, s, d, double);
+ TEST (loc, s, ld, long double);
+ s[4] = L_('a') + i - 10;
+ TEST (loc, s, f, float);
+ TEST (loc, s, d, double);
+ TEST (loc, s, ld, long double);
+ }
+ return result;
+}
+
+static int
+do_test (void)
+{
+ int result = 0;
+ result |= test_one_locale ("C");
+ result |= test_one_locale ("tr_TR.UTF-8");
+ result |= test_one_locale ("tr_TR.ISO-8859-9");
+ return result;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
Index: b/stdlib/tst-strtod-nan-locale.c
===================================================================
--- /dev/null
+++ b/stdlib/tst-strtod-nan-locale.c
@@ -0,0 +1,25 @@
+/* Test strtod functions work with all ASCII letters in NAN(...) in
+ Turkish locales (bug 19266). Narrow string version.
+ 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
+ <http://www.gnu.org/licenses/>. */
+
+#define CHAR char
+#define SFMT "\"%s\""
+#define FNPFX strto
+#define L_(C) C
+
+#include <tst-strtod-nan-locale-main.c>
Index: b/wcsmbs/Makefile
===================================================================
--- a/wcsmbs/Makefile
+++ b/wcsmbs/Makefile
@@ -45,7 +45,7 @@ routines := wcscat wcschr wcscmp wcscpy
strop-tests := wcscmp wcsncmp wmemcmp wcslen wcschr wcsrchr wcscpy
tests := tst-wcstof wcsmbs-tst1 tst-wcsnlen tst-btowc tst-mbrtowc \
tst-wcrtomb tst-wcpncpy tst-mbsrtowcs tst-wchar-h tst-mbrtowc2 \
- tst-c16c32-1 wcsatcliff tst-wcstol-locale \
+ tst-c16c32-1 wcsatcliff tst-wcstol-locale tst-wcstod-nan-locale \
$(addprefix test-,$(strop-tests))
include ../Rules
@@ -62,6 +62,7 @@ $(objpfx)tst-mbrtowc2.out: $(gen-locales
$(objpfx)tst-wcrtomb.out: $(gen-locales)
$(objpfx)wcsmbs-tst1.out: $(gen-locales)
$(objpfx)tst-wcstol-locale.out: $(gen-locales)
+$(objpfx)tst-wcstod-nan-locale.out: $(gen-locales)
endif
CFLAGS-wcwidth.c = -I../wctype
@@ -93,3 +94,5 @@ CPPFLAGS += $(libio-mtsafe)
# We need to find the default version of strtold_l in stdlib.
CPPFLAGS-wcstold_l.c = -I../stdlib
+
+$(objpfx)tst-wcstod-nan-locale: $(libm)
Index: b/wcsmbs/tst-wcstod-nan-locale.c
===================================================================
--- /dev/null
+++ b/wcsmbs/tst-wcstod-nan-locale.c
@@ -0,0 +1,25 @@
+/* Test strtod functions work with all ASCII letters in NAN(...) in
+ Turkish locales (bug 19266). Wide string version.
+ 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
+ <http://www.gnu.org/licenses/>. */
+
+#define CHAR wchar_t
+#define SFMT "L\"%ls\""
+#define FNPFX wcsto
+#define L_(C) L ## C
+
+#include "../stdlib/tst-strtod-nan-locale-main.c"

925
glibc-rh1300311-4.patch Normal file
View File

@ -0,0 +1,925 @@
commit e02cabecf0d025ec4f4ddee290bdf7aadb873bb3
Author: Joseph Myers <joseph@codesourcery.com>
Date: Tue Nov 24 22:24:52 2015 +0000
Refactor strtod parsing of NaN payloads.
The nan* functions handle their string argument by constructing a
NAN(...) string on the stack as a VLA and passing it to strtod
functions.
This approach has problems discussed in bug 16961 and bug 16962: the
stack usage is unbounded, and it gives incorrect results in certain
cases where the argument is not a valid n-char-sequence.
The natural fix for both issues is to refactor the NaN payload parsing
out of strtod into a separate function that the nan* functions can
call directly, so that no temporary string needs constructing on the
stack at all. This patch does that refactoring in preparation for
fixing those bugs (but without actually using the new functions from
nan* - which will also require exporting them from libc at version
GLIBC_PRIVATE). This patch is not intended to change any user-visible
behavior, so no tests are added (fixes for the above bugs will of
course add tests for them).
This patch builds on my recent fixes for strtol and strtod issues in
Turkish locales. Given those fixes, the parsing of NaN payloads is
locale-independent; thus, the new functions do not need to take a
locale_t argument.
Tested for x86_64, x86, mips64 and powerpc.
* stdlib/strtod_nan.c: New file.
* stdlib/strtod_nan_double.h: Likewise.
* stdlib/strtod_nan_float.h: Likewise.
* stdlib/strtod_nan_main.c: Likewise.
* stdlib/strtod_nan_narrow.h: Likewise.
* stdlib/strtod_nan_wide.h: Likewise.
* stdlib/strtof_nan.c: Likewise.
* stdlib/strtold_nan.c: Likewise.
* sysdeps/ieee754/ldbl-128/strtod_nan_ldouble.h: Likewise.
* sysdeps/ieee754/ldbl-128ibm/strtod_nan_ldouble.h: Likewise.
* sysdeps/ieee754/ldbl-96/strtod_nan_ldouble.h: Likewise.
* wcsmbs/wcstod_nan.c: Likewise.
* wcsmbs/wcstof_nan.c: Likewise.
* wcsmbs/wcstold_nan.c: Likewise.
* stdlib/Makefile (routines): Add strtof_nan, strtod_nan and
strtold_nan.
* wcsmbs/Makefile (routines): Add wcstod_nan, wcstold_nan and
wcstof_nan.
* include/stdlib.h (__strtof_nan): Declare and use
libc_hidden_proto.
(__strtod_nan): Likewise.
(__strtold_nan): Likewise.
(__wcstof_nan): Likewise.
(__wcstod_nan): Likewise.
(__wcstold_nan): Likewise.
* include/wchar.h (____wcstoull_l_internal): Declare.
* stdlib/strtod_l.c: Do not include <ieee754.h>.
(____strtoull_l_internal): Remove declaration.
(STRTOF_NAN): Define macro.
(SET_MANTISSA): Remove macro.
(STRTOULL): Likewise.
(____STRTOF_INTERNAL): Use STRTOF_NAN to parse NaN payload.
* stdlib/strtof_l.c (____strtoull_l_internal): Remove declaration.
(STRTOF_NAN): Define macro.
(SET_MANTISSA): Remove macro.
* sysdeps/ieee754/ldbl-128/strtold_l.c (STRTOF_NAN): Define macro.
(SET_MANTISSA): Remove macro.
* sysdeps/ieee754/ldbl-128ibm/strtold_l.c (STRTOF_NAN): Define
macro.
(SET_MANTISSA): Remove macro.
* sysdeps/ieee754/ldbl-64-128/strtold_l.c (STRTOF_NAN): Define
macro.
(SET_MANTISSA): Remove macro.
* sysdeps/ieee754/ldbl-96/strtold_l.c (STRTOF_NAN): Define macro.
(SET_MANTISSA): Remove macro.
* wcsmbs/wcstod_l.c (____wcstoull_l_internal): Remove declaration.
* wcsmbs/wcstof_l.c (____wcstoull_l_internal): Likewise.
* wcsmbs/wcstold_l.c (____wcstoull_l_internal): Likewise.
Index: b/include/stdlib.h
===================================================================
--- a/include/stdlib.h
+++ b/include/stdlib.h
@@ -203,6 +203,24 @@ libc_hidden_proto (strtoll)
libc_hidden_proto (strtoul)
libc_hidden_proto (strtoull)
+extern float __strtof_nan (const char *, char **, char) internal_function;
+extern double __strtod_nan (const char *, char **, char) internal_function;
+extern long double __strtold_nan (const char *, char **, char)
+ internal_function;
+extern float __wcstof_nan (const wchar_t *, wchar_t **, wchar_t)
+ internal_function;
+extern double __wcstod_nan (const wchar_t *, wchar_t **, wchar_t)
+ internal_function;
+extern long double __wcstold_nan (const wchar_t *, wchar_t **, wchar_t)
+ internal_function;
+
+libc_hidden_proto (__strtof_nan)
+libc_hidden_proto (__strtod_nan)
+libc_hidden_proto (__strtold_nan)
+libc_hidden_proto (__wcstof_nan)
+libc_hidden_proto (__wcstod_nan)
+libc_hidden_proto (__wcstold_nan)
+
extern char *__ecvt (double __value, int __ndigit, int *__restrict __decpt,
int *__restrict __sign);
extern char *__fcvt (double __value, int __ndigit, int *__restrict __decpt,
Index: b/include/wchar.h
===================================================================
--- a/include/wchar.h
+++ b/include/wchar.h
@@ -52,6 +52,9 @@ extern unsigned long long int __wcstoull
__restrict __endptr,
int __base,
int __group) __THROW;
+extern unsigned long long int ____wcstoull_l_internal (const wchar_t *,
+ wchar_t **, int, int,
+ __locale_t);
libc_hidden_proto (__wcstof_internal)
libc_hidden_proto (__wcstod_internal)
libc_hidden_proto (__wcstold_internal)
Index: b/stdlib/Makefile
===================================================================
--- a/stdlib/Makefile
+++ b/stdlib/Makefile
@@ -50,6 +50,7 @@ routines := \
strtol_l strtoul_l strtoll_l strtoull_l \
strtof strtod strtold \
strtof_l strtod_l strtold_l \
+ strtof_nan strtod_nan strtold_nan \
system canonicalize \
a64l l64a \
rpmatch strfmon strfmon_l getsubopt xpg_basename fmtmsg \
Index: b/stdlib/strtod_l.c
===================================================================
--- a/stdlib/strtod_l.c
+++ b/stdlib/strtod_l.c
@@ -20,8 +20,6 @@
#include <xlocale.h>
extern double ____strtod_l_internal (const char *, char **, int, __locale_t);
-extern unsigned long long int ____strtoull_l_internal (const char *, char **,
- int, int, __locale_t);
/* Configuration part. These macros are defined by `strtold.c',
`strtof.c', `wcstod.c', `wcstold.c', and `wcstof.c' to produce the
@@ -33,27 +31,20 @@ extern unsigned long long int ____strtou
# ifdef USE_WIDE_CHAR
# define STRTOF wcstod_l
# define __STRTOF __wcstod_l
+# define STRTOF_NAN __wcstod_nan
# else
# define STRTOF strtod_l
# define __STRTOF __strtod_l
+# define STRTOF_NAN __strtod_nan
# endif
# define MPN2FLOAT __mpn_construct_double
# define FLOAT_HUGE_VAL HUGE_VAL
-# define SET_MANTISSA(flt, mant) \
- do { union ieee754_double u; \
- u.d = (flt); \
- u.ieee_nan.mantissa0 = (mant) >> 32; \
- u.ieee_nan.mantissa1 = (mant); \
- if ((u.ieee.mantissa0 | u.ieee.mantissa1) != 0) \
- (flt) = u.d; \
- } while (0)
#endif
/* End of configuration part. */
#include <ctype.h>
#include <errno.h>
#include <float.h>
-#include <ieee754.h>
#include "../locale/localeinfo.h"
#include <locale.h>
#include <math.h>
@@ -104,7 +95,6 @@ extern unsigned long long int ____strtou
# define TOLOWER_C(Ch) __towlower_l ((Ch), _nl_C_locobj_ptr)
# define STRNCASECMP(S1, S2, N) \
__wcsncasecmp_l ((S1), (S2), (N), _nl_C_locobj_ptr)
-# define STRTOULL(S, E, B) ____wcstoull_l_internal ((S), (E), (B), 0, loc)
#else
# define STRING_TYPE char
# define CHAR_TYPE char
@@ -116,7 +106,6 @@ extern unsigned long long int ____strtou
# define TOLOWER_C(Ch) __tolower_l ((Ch), _nl_C_locobj_ptr)
# define STRNCASECMP(S1, S2, N) \
__strncasecmp_l ((S1), (S2), (N), _nl_C_locobj_ptr)
-# define STRTOULL(S, E, B) ____strtoull_l_internal ((S), (E), (B), 0, loc)
#endif
@@ -655,33 +644,14 @@ ____STRTOF_INTERNAL (nptr, endptr, group
if (*cp == L_('('))
{
const STRING_TYPE *startp = cp;
- do
- ++cp;
- while ((*cp >= L_('0') && *cp <= L_('9'))
- || (*cp >= L_('A') && *cp <= L_('Z'))
- || (*cp >= L_('a') && *cp <= L_('z'))
- || *cp == L_('_'));
-
- if (*cp != L_(')'))
- /* The closing brace is missing. Only match the NAN
- part. */
- cp = startp;
+ STRING_TYPE *endp;
+ retval = STRTOF_NAN (cp + 1, &endp, L_(')'));
+ if (*endp == L_(')'))
+ /* Consume the closing parenthesis. */
+ cp = endp + 1;
else
- {
- /* This is a system-dependent way to specify the
- bitmask used for the NaN. We expect it to be
- a number which is put in the mantissa of the
- number. */
- STRING_TYPE *endp;
- unsigned long long int mant;
-
- mant = STRTOULL (startp + 1, &endp, 0);
- if (endp == cp)
- SET_MANTISSA (retval, mant);
-
- /* Consume the closing brace. */
- ++cp;
- }
+ /* Only match the NAN part. */
+ cp = startp;
}
if (endptr != NULL)
Index: b/stdlib/strtod_nan.c
===================================================================
--- /dev/null
+++ b/stdlib/strtod_nan.c
@@ -0,0 +1,24 @@
+/* Convert string for NaN payload to corresponding NaN. Narrow
+ strings, double.
+ 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
+ <http://www.gnu.org/licenses/>. */
+
+#include <strtod_nan_narrow.h>
+#include <strtod_nan_double.h>
+
+#define STRTOD_NAN __strtod_nan
+#include <strtod_nan_main.c>
Index: b/stdlib/strtod_nan_double.h
===================================================================
--- /dev/null
+++ b/stdlib/strtod_nan_double.h
@@ -0,0 +1,30 @@
+/* Convert string for NaN payload to corresponding NaN. For double.
+ Copyright (C) 1997-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
+ <http://www.gnu.org/licenses/>. */
+
+#define FLOAT double
+#define SET_MANTISSA(flt, mant) \
+ do \
+ { \
+ union ieee754_double u; \
+ u.d = (flt); \
+ u.ieee_nan.mantissa0 = (mant) >> 32; \
+ u.ieee_nan.mantissa1 = (mant); \
+ if ((u.ieee.mantissa0 | u.ieee.mantissa1) != 0) \
+ (flt) = u.d; \
+ } \
+ while (0)
Index: b/stdlib/strtod_nan_float.h
===================================================================
--- /dev/null
+++ b/stdlib/strtod_nan_float.h
@@ -0,0 +1,29 @@
+/* Convert string for NaN payload to corresponding NaN. For float.
+ Copyright (C) 1997-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
+ <http://www.gnu.org/licenses/>. */
+
+#define FLOAT float
+#define SET_MANTISSA(flt, mant) \
+ do \
+ { \
+ union ieee754_float u; \
+ u.f = (flt); \
+ u.ieee_nan.mantissa = (mant); \
+ if (u.ieee.mantissa != 0) \
+ (flt) = u.f; \
+ } \
+ while (0)
Index: b/stdlib/strtod_nan_main.c
===================================================================
--- /dev/null
+++ b/stdlib/strtod_nan_main.c
@@ -0,0 +1,63 @@
+/* Convert string for NaN payload to corresponding NaN.
+ Copyright (C) 1997-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
+ <http://www.gnu.org/licenses/>. */
+
+#include <ieee754.h>
+#include <locale.h>
+#include <math.h>
+#include <stdlib.h>
+#include <wchar.h>
+
+
+/* If STR starts with an optional n-char-sequence as defined by ISO C
+ (a sequence of ASCII letters, digits and underscores), followed by
+ ENDC, return a NaN whose payload is set based on STR. Otherwise,
+ return a default NAN. If ENDPTR is not NULL, set *ENDPTR to point
+ to the character after the initial n-char-sequence. */
+
+internal_function
+FLOAT
+STRTOD_NAN (const STRING_TYPE *str, STRING_TYPE **endptr, STRING_TYPE endc)
+{
+ const STRING_TYPE *cp = str;
+
+ while ((*cp >= L_('0') && *cp <= L_('9'))
+ || (*cp >= L_('A') && *cp <= L_('Z'))
+ || (*cp >= L_('a') && *cp <= L_('z'))
+ || *cp == L_('_'))
+ ++cp;
+
+ FLOAT retval = NAN;
+ if (*cp != endc)
+ goto out;
+
+ /* This is a system-dependent way to specify the bitmask used for
+ the NaN. We expect it to be a number which is put in the
+ mantissa of the number. */
+ STRING_TYPE *endp;
+ unsigned long long int mant;
+
+ mant = STRTOULL (str, &endp, 0);
+ if (endp == cp)
+ SET_MANTISSA (retval, mant);
+
+ out:
+ if (endptr != NULL)
+ *endptr = (STRING_TYPE *) cp;
+ return retval;
+}
+libc_hidden_def (STRTOD_NAN)
Index: b/stdlib/strtod_nan_narrow.h
===================================================================
--- /dev/null
+++ b/stdlib/strtod_nan_narrow.h
@@ -0,0 +1,22 @@
+/* Convert string for NaN payload to corresponding NaN. Narrow strings.
+ Copyright (C) 1997-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
+ <http://www.gnu.org/licenses/>. */
+
+#define STRING_TYPE char
+#define L_(Ch) Ch
+#define STRTOULL(S, E, B) ____strtoull_l_internal ((S), (E), (B), 0, \
+ _nl_C_locobj_ptr)
Index: b/stdlib/strtod_nan_wide.h
===================================================================
--- /dev/null
+++ b/stdlib/strtod_nan_wide.h
@@ -0,0 +1,22 @@
+/* Convert string for NaN payload to corresponding NaN. Wide strings.
+ Copyright (C) 1997-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
+ <http://www.gnu.org/licenses/>. */
+
+#define STRING_TYPE wchar_t
+#define L_(Ch) L##Ch
+#define STRTOULL(S, E, B) ____wcstoull_l_internal ((S), (E), (B), 0, \
+ _nl_C_locobj_ptr)
Index: b/stdlib/strtof_l.c
===================================================================
--- a/stdlib/strtof_l.c
+++ b/stdlib/strtof_l.c
@@ -20,26 +20,19 @@
#include <xlocale.h>
extern float ____strtof_l_internal (const char *, char **, int, __locale_t);
-extern unsigned long long int ____strtoull_l_internal (const char *, char **,
- int, int, __locale_t);
#define FLOAT float
#define FLT FLT
#ifdef USE_WIDE_CHAR
# define STRTOF wcstof_l
# define __STRTOF __wcstof_l
+# define STRTOF_NAN __wcstof_nan
#else
# define STRTOF strtof_l
# define __STRTOF __strtof_l
+# define STRTOF_NAN __strtof_nan
#endif
#define MPN2FLOAT __mpn_construct_float
#define FLOAT_HUGE_VAL HUGE_VALF
-#define SET_MANTISSA(flt, mant) \
- do { union ieee754_float u; \
- u.f = (flt); \
- u.ieee_nan.mantissa = (mant); \
- if (u.ieee.mantissa != 0) \
- (flt) = u.f; \
- } while (0)
#include "strtod_l.c"
Index: b/stdlib/strtof_nan.c
===================================================================
--- /dev/null
+++ b/stdlib/strtof_nan.c
@@ -0,0 +1,24 @@
+/* Convert string for NaN payload to corresponding NaN. Narrow
+ strings, float.
+ 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
+ <http://www.gnu.org/licenses/>. */
+
+#include <strtod_nan_narrow.h>
+#include <strtod_nan_float.h>
+
+#define STRTOD_NAN __strtof_nan
+#include <strtod_nan_main.c>
Index: b/stdlib/strtold_nan.c
===================================================================
--- /dev/null
+++ b/stdlib/strtold_nan.c
@@ -0,0 +1,30 @@
+/* Convert string for NaN payload to corresponding NaN. Narrow
+ strings, long double.
+ 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
+ <http://www.gnu.org/licenses/>. */
+
+#include <math.h>
+
+/* This function is unused if long double and double have the same
+ representation. */
+#ifndef __NO_LONG_DOUBLE_MATH
+# include <strtod_nan_narrow.h>
+# include <strtod_nan_ldouble.h>
+
+# define STRTOD_NAN __strtold_nan
+# include <strtod_nan_main.c>
+#endif
Index: b/sysdeps/ieee754/ldbl-128/strtod_nan_ldouble.h
===================================================================
--- /dev/null
+++ b/sysdeps/ieee754/ldbl-128/strtod_nan_ldouble.h
@@ -0,0 +1,33 @@
+/* Convert string for NaN payload to corresponding NaN. For ldbl-128.
+ Copyright (C) 1997-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
+ <http://www.gnu.org/licenses/>. */
+
+#define FLOAT long double
+#define SET_MANTISSA(flt, mant) \
+ do \
+ { \
+ union ieee854_long_double u; \
+ u.d = (flt); \
+ u.ieee_nan.mantissa0 = 0; \
+ u.ieee_nan.mantissa1 = 0; \
+ u.ieee_nan.mantissa2 = (mant) >> 32; \
+ u.ieee_nan.mantissa3 = (mant); \
+ if ((u.ieee.mantissa0 | u.ieee.mantissa1 \
+ | u.ieee.mantissa2 | u.ieee.mantissa3) != 0) \
+ (flt) = u.d; \
+ } \
+ while (0)
Index: b/sysdeps/ieee754/ldbl-128/strtold_l.c
===================================================================
--- a/sysdeps/ieee754/ldbl-128/strtold_l.c
+++ b/sysdeps/ieee754/ldbl-128/strtold_l.c
@@ -25,22 +25,13 @@
#ifdef USE_WIDE_CHAR
# define STRTOF wcstold_l
# define __STRTOF __wcstold_l
+# define STRTOF_NAN __wcstold_nan
#else
# define STRTOF strtold_l
# define __STRTOF __strtold_l
+# define STRTOF_NAN __strtold_nan
#endif
#define MPN2FLOAT __mpn_construct_long_double
#define FLOAT_HUGE_VAL HUGE_VALL
-#define SET_MANTISSA(flt, mant) \
- do { union ieee854_long_double u; \
- u.d = (flt); \
- u.ieee_nan.mantissa0 = 0; \
- u.ieee_nan.mantissa1 = 0; \
- u.ieee_nan.mantissa2 = (mant) >> 32; \
- u.ieee_nan.mantissa3 = (mant); \
- if ((u.ieee.mantissa0 | u.ieee.mantissa1 \
- | u.ieee.mantissa2 | u.ieee.mantissa3) != 0) \
- (flt) = u.d; \
- } while (0)
#include <strtod_l.c>
Index: b/sysdeps/ieee754/ldbl-128ibm/strtod_nan_ldouble.h
===================================================================
--- /dev/null
+++ b/sysdeps/ieee754/ldbl-128ibm/strtod_nan_ldouble.h
@@ -0,0 +1,30 @@
+/* Convert string for NaN payload to corresponding NaN. For ldbl-128ibm.
+ Copyright (C) 1997-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
+ <http://www.gnu.org/licenses/>. */
+
+#define FLOAT long double
+#define SET_MANTISSA(flt, mant) \
+ do \
+ { \
+ union ibm_extended_long_double u; \
+ u.ld = (flt); \
+ u.d[0].ieee_nan.mantissa0 = (mant) >> 32; \
+ u.d[0].ieee_nan.mantissa1 = (mant); \
+ if ((u.d[0].ieee.mantissa0 | u.d[0].ieee.mantissa1) != 0) \
+ (flt) = u.ld; \
+ } \
+ while (0)
Index: b/sysdeps/ieee754/ldbl-128ibm/strtold_l.c
===================================================================
--- a/sysdeps/ieee754/ldbl-128ibm/strtold_l.c
+++ b/sysdeps/ieee754/ldbl-128ibm/strtold_l.c
@@ -30,25 +30,19 @@ extern long double ____new_wcstold_l (co
# define STRTOF __new_wcstold_l
# define __STRTOF ____new_wcstold_l
# define ____STRTOF_INTERNAL ____wcstold_l_internal
+# define STRTOF_NAN __wcstold_nan
#else
extern long double ____new_strtold_l (const char *, char **, __locale_t);
# define STRTOF __new_strtold_l
# define __STRTOF ____new_strtold_l
# define ____STRTOF_INTERNAL ____strtold_l_internal
+# define STRTOF_NAN __strtold_nan
#endif
extern __typeof (__STRTOF) STRTOF;
libc_hidden_proto (__STRTOF)
libc_hidden_proto (STRTOF)
#define MPN2FLOAT __mpn_construct_long_double
#define FLOAT_HUGE_VAL HUGE_VALL
-# define SET_MANTISSA(flt, mant) \
- do { union ibm_extended_long_double u; \
- u.ld = (flt); \
- u.d[0].ieee_nan.mantissa0 = (mant) >> 32; \
- u.d[0].ieee_nan.mantissa1 = (mant); \
- if ((u.d[0].ieee.mantissa0 | u.d[0].ieee.mantissa1) != 0) \
- (flt) = u.ld; \
- } while (0)
#include <strtod_l.c>
Index: b/sysdeps/ieee754/ldbl-64-128/strtold_l.c
===================================================================
--- a/sysdeps/ieee754/ldbl-64-128/strtold_l.c
+++ b/sysdeps/ieee754/ldbl-64-128/strtold_l.c
@@ -30,28 +30,19 @@ extern long double ____new_wcstold_l (co
# define STRTOF __new_wcstold_l
# define __STRTOF ____new_wcstold_l
# define ____STRTOF_INTERNAL ____wcstold_l_internal
+# define STRTOF_NAN __wcstold_nan
#else
extern long double ____new_strtold_l (const char *, char **, __locale_t);
# define STRTOF __new_strtold_l
# define __STRTOF ____new_strtold_l
# define ____STRTOF_INTERNAL ____strtold_l_internal
+# define STRTOF_NAN __strtold_nan
#endif
extern __typeof (__STRTOF) STRTOF;
libc_hidden_proto (__STRTOF)
libc_hidden_proto (STRTOF)
#define MPN2FLOAT __mpn_construct_long_double
#define FLOAT_HUGE_VAL HUGE_VALL
-#define SET_MANTISSA(flt, mant) \
- do { union ieee854_long_double u; \
- u.d = (flt); \
- u.ieee_nan.mantissa0 = 0; \
- u.ieee_nan.mantissa1 = 0; \
- u.ieee_nan.mantissa2 = (mant) >> 32; \
- u.ieee_nan.mantissa3 = (mant); \
- if ((u.ieee.mantissa0 | u.ieee.mantissa1 \
- | u.ieee.mantissa2 | u.ieee.mantissa3) != 0) \
- (flt) = u.d; \
- } while (0)
#include <strtod_l.c>
Index: b/sysdeps/ieee754/ldbl-96/strtod_nan_ldouble.h
===================================================================
--- /dev/null
+++ b/sysdeps/ieee754/ldbl-96/strtod_nan_ldouble.h
@@ -0,0 +1,30 @@
+/* Convert string for NaN payload to corresponding NaN. For ldbl-96.
+ Copyright (C) 1997-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
+ <http://www.gnu.org/licenses/>. */
+
+#define FLOAT long double
+#define SET_MANTISSA(flt, mant) \
+ do \
+ { \
+ union ieee854_long_double u; \
+ u.d = (flt); \
+ u.ieee_nan.mantissa0 = (mant) >> 32; \
+ u.ieee_nan.mantissa1 = (mant); \
+ if ((u.ieee.mantissa0 | u.ieee.mantissa1) != 0) \
+ (flt) = u.d; \
+ } \
+ while (0)
Index: b/sysdeps/ieee754/ldbl-96/strtold_l.c
===================================================================
--- a/sysdeps/ieee754/ldbl-96/strtold_l.c
+++ b/sysdeps/ieee754/ldbl-96/strtold_l.c
@@ -25,19 +25,13 @@
#ifdef USE_WIDE_CHAR
# define STRTOF wcstold_l
# define __STRTOF __wcstold_l
+# define STRTOF_NAN __wcstold_nan
#else
# define STRTOF strtold_l
# define __STRTOF __strtold_l
+# define STRTOF_NAN __strtold_nan
#endif
#define MPN2FLOAT __mpn_construct_long_double
#define FLOAT_HUGE_VAL HUGE_VALL
-#define SET_MANTISSA(flt, mant) \
- do { union ieee854_long_double u; \
- u.d = (flt); \
- u.ieee_nan.mantissa0 = (mant) >> 32; \
- u.ieee_nan.mantissa1 = (mant); \
- if ((u.ieee.mantissa0 | u.ieee.mantissa1) != 0) \
- (flt) = u.d; \
- } while (0)
#include <stdlib/strtod_l.c>
Index: b/wcsmbs/Makefile
===================================================================
--- a/wcsmbs/Makefile
+++ b/wcsmbs/Makefile
@@ -33,6 +33,7 @@ routines := wcscat wcschr wcscmp wcscpy
wcstol wcstoul wcstoll wcstoull wcstod wcstold wcstof \
wcstol_l wcstoul_l wcstoll_l wcstoull_l \
wcstod_l wcstold_l wcstof_l \
+ wcstod_nan wcstold_nan wcstof_nan \
wcscoll wcsxfrm \
wcwidth wcswidth \
wcscoll_l wcsxfrm_l \
Index: b/wcsmbs/wcstod_l.c
===================================================================
--- a/wcsmbs/wcstod_l.c
+++ b/wcsmbs/wcstod_l.c
@@ -23,9 +23,6 @@
extern double ____wcstod_l_internal (const wchar_t *, wchar_t **, int,
__locale_t);
-extern unsigned long long int ____wcstoull_l_internal (const wchar_t *,
- wchar_t **, int, int,
- __locale_t);
#define USE_WIDE_CHAR 1
Index: b/wcsmbs/wcstod_nan.c
===================================================================
--- /dev/null
+++ b/wcsmbs/wcstod_nan.c
@@ -0,0 +1,23 @@
+/* Convert string for NaN payload to corresponding NaN. Wide strings, double.
+ 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
+ <http://www.gnu.org/licenses/>. */
+
+#include "../stdlib/strtod_nan_wide.h"
+#include "../stdlib/strtod_nan_double.h"
+
+#define STRTOD_NAN __wcstod_nan
+#include "../stdlib/strtod_nan_main.c"
Index: b/wcsmbs/wcstof_l.c
===================================================================
--- a/wcsmbs/wcstof_l.c
+++ b/wcsmbs/wcstof_l.c
@@ -25,8 +25,5 @@
extern float ____wcstof_l_internal (const wchar_t *, wchar_t **, int,
__locale_t);
-extern unsigned long long int ____wcstoull_l_internal (const wchar_t *,
- wchar_t **, int, int,
- __locale_t);
#include <stdlib/strtof_l.c>
Index: b/wcsmbs/wcstof_nan.c
===================================================================
--- /dev/null
+++ b/wcsmbs/wcstof_nan.c
@@ -0,0 +1,23 @@
+/* Convert string for NaN payload to corresponding NaN. Wide strings, float.
+ 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
+ <http://www.gnu.org/licenses/>. */
+
+#include "../stdlib/strtod_nan_wide.h"
+#include "../stdlib/strtod_nan_float.h"
+
+#define STRTOD_NAN __wcstof_nan
+#include "../stdlib/strtod_nan_main.c"
Index: b/wcsmbs/wcstold_l.c
===================================================================
--- a/wcsmbs/wcstold_l.c
+++ b/wcsmbs/wcstold_l.c
@@ -24,8 +24,5 @@
extern long double ____wcstold_l_internal (const wchar_t *, wchar_t **, int,
__locale_t);
-extern unsigned long long int ____wcstoull_l_internal (const wchar_t *,
- wchar_t **, int, int,
- __locale_t);
#include <strtold_l.c>
Index: b/wcsmbs/wcstold_nan.c
===================================================================
--- /dev/null
+++ b/wcsmbs/wcstold_nan.c
@@ -0,0 +1,30 @@
+/* Convert string for NaN payload to corresponding NaN. Wide strings,
+ long double.
+ 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
+ <http://www.gnu.org/licenses/>. */
+
+#include <math.h>
+
+/* This function is unused if long double and double have the same
+ representation. */
+#ifndef __NO_LONG_DOUBLE_MATH
+# include "../stdlib/strtod_nan_wide.h"
+# include <strtod_nan_ldouble.h>
+
+# define STRTOD_NAN __wcstold_nan
+# include "../stdlib/strtod_nan_main.c"
+#endif

223
glibc-rh1300314.patch Normal file
View File

@ -0,0 +1,223 @@
commit 0f58539030e436449f79189b6edab17d7479796e
Author: Paul Pluzhnikov <ppluzhnikov@google.com>
Date: Sat Aug 8 15:53:03 2015 -0700
Fix BZ #17905
commit 0f58539030e436449f79189b6edab17d7479796e
Author: Paul Pluzhnikov <ppluzhnikov@google.com>
Date: Sat Aug 8 15:53:03 2015 -0700
Fix BZ #17905
diff --git a/catgets/Makefile b/catgets/Makefile
index 4624a88..56de38b 100644
--- a/catgets/Makefile
+++ b/catgets/Makefile
@@ -34,6 +34,7 @@ test-srcs = test-gencat
ifeq ($(run-built-tests),yes)
tests-special += $(objpfx)de/libc.cat $(objpfx)test1.cat $(objpfx)test2.cat \
$(objpfx)sample.SJIS.cat $(objpfx)test-gencat.out
+tests-special += $(objpfx)tst-catgets-mem.out
endif
gencat-modules = xmalloc
@@ -50,9 +51,11 @@ catgets-CPPFLAGS := -DNLSPATH='"$(msgcatdir)/%L/%N:$(msgcatdir)/%L/LC_MESSAGES/%
generated += de.msg test1.cat test1.h test2.cat test2.h sample.SJIS.cat \
test-gencat.h
+generated += tst-catgets.mtrace tst-catgets-mem.out
+
generated-dirs += de
-tst-catgets-ENV = NLSPATH="$(objpfx)%l/%N.cat" LANG=de
+tst-catgets-ENV = NLSPATH="$(objpfx)%l/%N.cat" LANG=de MALLOC_TRACE=$(objpfx)tst-catgets.mtrace
ifeq ($(run-built-tests),yes)
# This test just checks whether the program produces any error or not.
@@ -86,4 +89,8 @@ $(objpfx)test-gencat.out: test-gencat.sh $(objpfx)test-gencat \
$(objpfx)sample.SJIS.cat: sample.SJIS $(objpfx)gencat
$(built-program-cmd) -H $(objpfx)test-gencat.h < $(word 1,$^) > $@; \
$(evaluate-test)
+
+$(objpfx)tst-catgets-mem.out: $(objpfx)tst-catgets.out
+ $(common-objpfx)malloc/mtrace $(objpfx)tst-catgets.mtrace > $@; \
+ $(evaluate-test)
endif
diff --git a/catgets/catgets.c b/catgets/catgets.c
index cf93d56..4be452d 100644
--- a/catgets/catgets.c
+++ b/catgets/catgets.c
@@ -16,7 +16,6 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
-#include <alloca.h>
#include <errno.h>
#include <locale.h>
#include <nl_types.h>
@@ -35,6 +34,7 @@ catopen (const char *cat_name, int flag)
__nl_catd result;
const char *env_var = NULL;
const char *nlspath = NULL;
+ char *tmp = NULL;
if (strchr (cat_name, '/') == NULL)
{
@@ -54,7 +54,10 @@ catopen (const char *cat_name, int flag)
{
/* Append the system dependent directory. */
size_t len = strlen (nlspath) + 1 + sizeof NLSPATH;
- char *tmp = alloca (len);
+ tmp = malloc (len);
+
+ if (__glibc_unlikely (tmp == NULL))
+ return (nl_catd) -1;
__stpcpy (__stpcpy (__stpcpy (tmp, nlspath), ":"), NLSPATH);
nlspath = tmp;
@@ -65,16 +68,18 @@ catopen (const char *cat_name, int flag)
result = (__nl_catd) malloc (sizeof (*result));
if (result == NULL)
- /* We cannot get enough memory. */
- return (nl_catd) -1;
-
- if (__open_catalog (cat_name, nlspath, env_var, result) != 0)
+ {
+ /* We cannot get enough memory. */
+ result = (nl_catd) -1;
+ }
+ else if (__open_catalog (cat_name, nlspath, env_var, result) != 0)
{
/* Couldn't open the file. */
free ((void *) result);
- return (nl_catd) -1;
+ result = (nl_catd) -1;
}
+ free (tmp);
return (nl_catd) result;
}
diff --git a/catgets/open_catalog.c b/catgets/open_catalog.c
index e069416..9f4d776 100644
--- a/catgets/open_catalog.c
+++ b/catgets/open_catalog.c
@@ -47,6 +47,7 @@ __open_catalog (const char *cat_name, const char *nlspath, const char *env_var,
size_t tab_size;
const char *lastp;
int result = -1;
+ char *buf = NULL;
if (strchr (cat_name, '/') != NULL || nlspath == NULL)
fd = open_not_cancel_2 (cat_name, O_RDONLY);
@@ -57,23 +58,23 @@ __open_catalog (const char *cat_name, const char *nlspath, const char *env_var,
if (__glibc_unlikely (bufact + (n) >= bufmax)) \
{ \
char *old_buf = buf; \
- bufmax += 256 + (n); \
- buf = (char *) alloca (bufmax); \
- memcpy (buf, old_buf, bufact); \
+ bufmax += (bufmax < 256 + (n)) ? 256 + (n) : bufmax; \
+ buf = realloc (buf, bufmax); \
+ if (__glibc_unlikely (buf == NULL)) \
+ { \
+ free (old_buf); \
+ return -1; \
+ } \
}
/* The RUN_NLSPATH variable contains a colon separated list of
descriptions where we expect to find catalogs. We have to
recognize certain % substitutions and stop when we found the
first existing file. */
- char *buf;
size_t bufact;
- size_t bufmax;
+ size_t bufmax = 0;
size_t len;
- buf = NULL;
- bufmax = 0;
-
fd = -1;
while (*run_nlspath != '\0')
{
@@ -188,7 +189,10 @@ __open_catalog (const char *cat_name, const char *nlspath, const char *env_var,
/* Avoid dealing with directories and block devices */
if (__builtin_expect (fd, 0) < 0)
- return -1;
+ {
+ free (buf);
+ return -1;
+ }
if (__builtin_expect (__fxstat64 (_STAT_VER, fd, &st), 0) < 0)
goto close_unlock_return;
@@ -325,6 +329,7 @@ __open_catalog (const char *cat_name, const char *nlspath, const char *env_var,
/* Release the lock again. */
close_unlock_return:
close_not_cancel_no_status (fd);
+ free (buf);
return result;
}
diff --git a/catgets/tst-catgets.c b/catgets/tst-catgets.c
index a0a4089..140de72 100644
--- a/catgets/tst-catgets.c
+++ b/catgets/tst-catgets.c
@@ -1,7 +1,10 @@
+#include <assert.h>
#include <mcheck.h>
#include <nl_types.h>
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
+#include <sys/resource.h>
static const char *msgs[] =
@@ -12,6 +15,33 @@ static const char *msgs[] =
};
#define nmsgs (sizeof (msgs) / sizeof (msgs[0]))
+
+/* Test for unbounded alloca. */
+static int
+do_bz17905 (void)
+{
+ char *buf;
+ struct rlimit rl;
+ nl_catd result;
+
+ const int sz = 1024 * 1024;
+
+ getrlimit (RLIMIT_STACK, &rl);
+ rl.rlim_cur = sz;
+ setrlimit (RLIMIT_STACK, &rl);
+
+ buf = malloc (sz + 1);
+ memset (buf, 'A', sz);
+ buf[sz] = '\0';
+ setenv ("NLSPATH", buf, 1);
+
+ result = catopen (buf, NL_CAT_LOCALE);
+ assert (result == (nl_catd) -1);
+
+ free (buf);
+ return 0;
+}
+
#define ROUNDS 5
static int
@@ -62,6 +92,7 @@ do_test (void)
}
}
+ result += do_bz17905 ();
return result;
}

453
glibc-rh1307234-1.patch Normal file
View File

@ -0,0 +1,453 @@
commit 985fc132f23dbb83de76c5af9e783ef1b5900148
Author: Florian Weimer <fweimer@redhat.com>
Date: Mon Apr 4 15:18:13 2016 +0200
strfmon_l: Use specified locale for number formatting [BZ #19633]
Index: b/include/printf.h
===================================================================
--- a/include/printf.h
+++ b/include/printf.h
@@ -1,6 +1,7 @@
#ifndef _PRINTF_H
#include <stdio-common/printf.h>
+#include <xlocale.h>
/* Now define the internal interfaces. */
extern int __printf_fphex (FILE *, const struct printf_info *,
@@ -8,5 +9,8 @@ extern int __printf_fphex (FILE *, const
extern int __printf_fp (FILE *, const struct printf_info *,
const void *const *);
libc_hidden_proto (__printf_fp)
+extern int __printf_fp_l (FILE *, locale_t, const struct printf_info *,
+ const void *const *);
+libc_hidden_proto (__printf_fp_l)
#endif
Index: b/locale/localeinfo.h
===================================================================
--- a/locale/localeinfo.h
+++ b/locale/localeinfo.h
@@ -299,6 +299,27 @@ extern __thread struct __locale_data *co
#endif
+/* Extract CATEGORY locale's string for ITEM. */
+static inline const char *
+_nl_lookup (locale_t l, int category, int item)
+{
+ return l->__locales[category]->values[_NL_ITEM_INDEX (item)].string;
+}
+
+/* Extract CATEGORY locale's wide string for ITEM. */
+static inline const wchar_t *
+_nl_lookup_wstr (locale_t l, int category, int item)
+{
+ return (wchar_t *) l->__locales[category]
+ ->values[_NL_ITEM_INDEX (item)].wstr;
+}
+
+/* Extract the CATEGORY locale's word for ITEM. */
+static inline uint32_t
+_nl_lookup_word (locale_t l, int category, int item)
+{
+ return l->__locales[category]->values[_NL_ITEM_INDEX (item)].word;
+}
/* Default search path if no LOCPATH environment variable. */
extern const char _nl_default_locale_path[] attribute_hidden;
Index: b/stdio-common/printf_fp.c
===================================================================
--- a/stdio-common/printf_fp.c
+++ b/stdio-common/printf_fp.c
@@ -209,9 +209,9 @@ hack_digit (struct hack_digit_param *p)
}
int
-___printf_fp (FILE *fp,
- const struct printf_info *info,
- const void *const *args)
+___printf_fp_l (FILE *fp, locale_t loc,
+ const struct printf_info *info,
+ const void *const *args)
{
/* The floating-point value to output. */
union
@@ -263,18 +263,19 @@ ___printf_fp (FILE *fp,
/* Figure out the decimal point character. */
if (info->extra == 0)
{
- decimal = _NL_CURRENT (LC_NUMERIC, DECIMAL_POINT);
- decimalwc = _NL_CURRENT_WORD (LC_NUMERIC, _NL_NUMERIC_DECIMAL_POINT_WC);
+ decimal = _nl_lookup (loc, LC_NUMERIC, DECIMAL_POINT);
+ decimalwc = _nl_lookup_word
+ (loc, LC_NUMERIC, _NL_NUMERIC_DECIMAL_POINT_WC);
}
else
{
- decimal = _NL_CURRENT (LC_MONETARY, MON_DECIMAL_POINT);
+ decimal = _nl_lookup (loc, LC_MONETARY, MON_DECIMAL_POINT);
if (*decimal == '\0')
- decimal = _NL_CURRENT (LC_NUMERIC, DECIMAL_POINT);
- decimalwc = _NL_CURRENT_WORD (LC_MONETARY,
+ decimal = _nl_lookup (loc, LC_NUMERIC, DECIMAL_POINT);
+ decimalwc = _nl_lookup_word (loc, LC_MONETARY,
_NL_MONETARY_DECIMAL_POINT_WC);
if (decimalwc == L'\0')
- decimalwc = _NL_CURRENT_WORD (LC_NUMERIC,
+ decimalwc = _nl_lookup_word (loc, LC_NUMERIC,
_NL_NUMERIC_DECIMAL_POINT_WC);
}
/* The decimal point character must not be zero. */
@@ -284,9 +285,9 @@ ___printf_fp (FILE *fp,
if (info->group)
{
if (info->extra == 0)
- grouping = _NL_CURRENT (LC_NUMERIC, GROUPING);
+ grouping = _nl_lookup (loc, LC_NUMERIC, GROUPING);
else
- grouping = _NL_CURRENT (LC_MONETARY, MON_GROUPING);
+ grouping = _nl_lookup (loc, LC_MONETARY, MON_GROUPING);
if (*grouping <= 0 || *grouping == CHAR_MAX)
grouping = NULL;
@@ -296,19 +297,20 @@ ___printf_fp (FILE *fp,
if (wide)
{
if (info->extra == 0)
- thousands_sepwc =
- _NL_CURRENT_WORD (LC_NUMERIC, _NL_NUMERIC_THOUSANDS_SEP_WC);
+ thousands_sepwc = _nl_lookup_word
+ (loc, LC_NUMERIC, _NL_NUMERIC_THOUSANDS_SEP_WC);
else
thousands_sepwc =
- _NL_CURRENT_WORD (LC_MONETARY,
+ _nl_lookup_word (loc, LC_MONETARY,
_NL_MONETARY_THOUSANDS_SEP_WC);
}
else
{
if (info->extra == 0)
- thousands_sep = _NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP);
+ thousands_sep = _nl_lookup (loc, LC_NUMERIC, THOUSANDS_SEP);
else
- thousands_sep = _NL_CURRENT (LC_MONETARY, MON_THOUSANDS_SEP);
+ thousands_sep = _nl_lookup
+ (loc, LC_MONETARY, MON_THOUSANDS_SEP);
}
if ((wide && thousands_sepwc == L'\0')
@@ -1174,9 +1176,11 @@ ___printf_fp (FILE *fp,
size_t decimal_len;
size_t thousands_sep_len;
wchar_t *copywc;
- size_t factor = (info->i18n
- ? _NL_CURRENT_WORD (LC_CTYPE, _NL_CTYPE_MB_CUR_MAX)
- : 1);
+ size_t factor;
+ if (info->i18n)
+ factor = _nl_lookup_word (loc, LC_CTYPE, _NL_CTYPE_MB_CUR_MAX);
+ else
+ factor = 1;
decimal_len = strlen (decimal);
@@ -1247,8 +1251,18 @@ ___printf_fp (FILE *fp,
}
return done;
}
+ldbl_hidden_def (___printf_fp_l, __printf_fp_l)
+ldbl_strong_alias (___printf_fp_l, __printf_fp_l)
+
+int
+___printf_fp (FILE *fp, const struct printf_info *info,
+ const void *const *args)
+{
+ return ___printf_fp_l (fp, _NL_CURRENT_LOCALE, info, args);
+}
ldbl_hidden_def (___printf_fp, __printf_fp)
ldbl_strong_alias (___printf_fp, __printf_fp)
+
/* Return the number of extra grouping characters that will be inserted
into a number with INTDIG_MAX integer digits. */
Index: b/stdlib/Makefile
===================================================================
--- a/stdlib/Makefile
+++ b/stdlib/Makefile
@@ -76,7 +76,7 @@ tests := tst-strtol tst-strtod testmb t
tst-secure-getenv tst-strtod-overflow tst-strtod-round \
tst-tininess tst-strtod-underflow tst-tls-atexit \
tst-setcontext3 tst-tls-atexit-nodelete \
- tst-strtol-locale tst-strtod-nan-locale
+ tst-strtol-locale tst-strtod-nan-locale tst-strfmon_l
tests-static := tst-secure-getenv
modules-names = tst-tls-atexit-lib
@@ -125,7 +125,8 @@ include ../Rules
ifeq ($(run-built-tests),yes)
LOCALES := cs_CZ.UTF-8 de_DE.UTF-8 en_US.ISO-8859-1 tr_TR.UTF-8 \
- tr_TR.ISO-8859-9
+ tr_TR.ISO-8859-9 tg_TJ.UTF-8 te_IN.UTF-8 bn_IN.UTF-8 \
+ el_GR.UTF-8
include ../gen-locales.mk
$(objpfx)bug-strtod2.out: $(gen-locales)
@@ -136,6 +137,7 @@ $(objpfx)tst-strtod4.out: $(gen-locales)
$(objpfx)tst-strtod5.out: $(gen-locales)
$(objpfx)tst-strtol-locale.out: $(gen-locales)
$(objpfx)tst-strtod-nan-locale.out: $(gen-locales)
+$(objpfx)tst-strfmon_l.out: $(gen-locales)
endif
# Testdir has to be named stdlib and needs to be writable
Index: b/stdlib/strfmon_l.c
===================================================================
--- a/stdlib/strfmon_l.c
+++ b/stdlib/strfmon_l.c
@@ -68,9 +68,6 @@
#define _NL_CURRENT(category, item) \
(current->values[_NL_ITEM_INDEX (item)].string)
-extern int __printf_fp (FILE *, const struct printf_info *,
- const void *const *);
-libc_hidden_proto (__printf_fp)
/* This function determines the number of digit groups in the output.
The definition is in printf_fp.c. */
extern unsigned int __guess_grouping (unsigned int intdig_max,
@@ -532,7 +529,7 @@ __vstrfmon_l (char *s, size_t maxsize, _
info.extra = 1; /* This means use values from LC_MONETARY. */
ptr = &fpnum;
- done = __printf_fp (&f._sbf._f, &info, &ptr);
+ done = __printf_fp_l (&f._sbf._f, loc, &info, &ptr);
if (done < 0)
return -1;
Index: b/stdlib/tst-strfmon_l.c
===================================================================
--- /dev/null
+++ b/stdlib/tst-strfmon_l.c
@@ -0,0 +1,220 @@
+/* Test locale dependence of strfmon_l.
+ Copyright (C) 2016 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
+ <http://www.gnu.org/licenses/>. */
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <monetary.h>
+#include <string.h>
+#include <stdlib.h>
+#include <locale.h>
+
+static const char *const en_us_name = "en_US.ISO-8859-1";
+
+/* Locale value to be used by tests. */
+static locale_t loc;
+static const char *loc_name;
+
+/* Set the global locale to GLOBAL_NAME, and the locale referenced by
+ the loc variable above to LOCAL_NAME. */
+static void
+init_loc (const char *global_name, const char *local_name)
+{
+ loc = newlocale (LC_ALL_MASK, local_name, 0);
+ if (loc == 0)
+ {
+ printf ("error: newlocale (%s): %m\n", local_name);
+ abort ();
+ }
+ loc_name = local_name;
+
+ if (setlocale (LC_ALL, global_name) == NULL)
+ {
+ printf ("error: setlocale (%s): %m\n", global_name);
+ abort ();
+ }
+}
+
+/* Expected strings for a positive or negative value. */
+struct testcase
+{
+ const char *i; /* %i */
+ const char *n; /* %n */
+ const char *i_ungrouped; /* %^i */
+ const char *n_ungrouped; /* %^n */
+};
+
+/* Collected expected strings for both positive and negative
+ values. */
+struct testcase_pair
+{
+ struct testcase positive; /* 1234567.89 */
+ struct testcase negative; /* -1234567.89 */
+};
+
+static bool errors;
+
+/* Test one value using the locale loc. */
+static void
+test_one (const char *format, double value, const char *expected)
+{
+ static char actual[64];
+ int result = strfmon_l (actual, sizeof (actual), loc, format, value);
+ if (result < 0)
+ {
+ printf ("error: locale %s, format \"%s\", value %g: strfmon_l: %m\n",
+ loc_name, format, value);
+ errors = true;
+ }
+ else if (strcmp (actual, expected) != 0)
+ {
+ printf ("error: locale %s, format \"%s\", value %g: mismatch\n",
+ loc_name, format, value);
+ printf ("error: expected: \"%s\"\n", expected);
+ printf ("error: actual: \"%s\"\n", actual);
+ errors = true;
+ }
+}
+
+static void
+test_pair (const struct testcase_pair *pair)
+{
+ double positive = 1234567.89;
+ test_one ("%i", positive, pair->positive.i);
+ test_one ("%n", positive, pair->positive.n);
+ test_one ("%^i", positive, pair->positive.i_ungrouped);
+ test_one ("%^n", positive, pair->positive.n_ungrouped);
+ double negative = -1234567.89;
+ test_one ("%i", negative, pair->negative.i);
+ test_one ("%n", negative, pair->negative.n);
+ test_one ("%^i", negative, pair->negative.i_ungrouped);
+ test_one ("%^n", negative, pair->negative.n_ungrouped);
+}
+
+static const struct testcase_pair en_us =
+ {
+ {
+ "USD 1,234,567.89", "$1,234,567.89",
+ "USD 1234567.89", "$1234567.89"
+ },
+ {
+ "-USD 1,234,567.89", "-$1,234,567.89",
+ "-USD 1234567.89", "-$1234567.89"
+ }
+ };
+
+static void
+test_en_us (const char *other_name)
+{
+ init_loc (other_name, en_us_name);
+ test_pair (&en_us);
+ freelocale (loc);
+}
+
+struct locale_pair
+{
+ const char *locale_name;
+ struct testcase_pair pair;
+};
+
+static const struct locale_pair tests[] =
+ {
+ {
+ "de_DE.UTF-8",
+ {
+ {
+ "1.234.567,89 EUR", "1.234.567,89 \u20ac",
+ "1234567,89 EUR", "1234567,89 \u20ac"
+ },
+ {
+ "-1.234.567,89 EUR", "-1.234.567,89 \u20ac",
+ "-1234567,89 EUR", "-1234567,89 \u20ac"
+ }
+ },
+ },
+ {
+ "tg_TJ.UTF-8",
+ {
+ {
+ "1 234 567.89 TJS", "1 234 567.89 \u0440\u0443\u0431",
+ "1234567.89 TJS", "1234567.89 \u0440\u0443\u0431"
+ },
+ {
+ "-1 234 567.89 TJS", "-1 234 567.89 \u0440\u0443\u0431",
+ "-1234567.89 TJS", "-1234567.89 \u0440\u0443\u0431"
+ }
+ }
+ },
+ {
+ "te_IN.UTF-8",
+ {
+ {
+ "INR12,34,567.89", "\u20b912,34,567.89",
+ "INR1234567.89", "\u20b91234567.89"
+ },
+ {
+ "-INR12,34,567.89", "-\u20b912,34,567.89",
+ "-INR1234567.89", "-\u20b91234567.89"
+ }
+ }
+ },
+ {
+ "bn_IN.UTF-8",
+ {
+ {
+ "INR 12,345,67.89", "\u20b9 12,345,67.89",
+ "INR 1234567.89", "\u20b9 1234567.89"
+ },
+ {
+ "-INR 12,345,67.89", "-\u20b9 12,345,67.89",
+ "-INR 1234567.89", "-\u20b9 1234567.89"
+ }
+ }
+ },
+ {
+ "el_GR.UTF-8",
+ {
+ {
+ "1.234.567,89EUR", "1.234.567,89\u20ac",
+ "1234567,89EUR", "1234567,89\u20ac"
+ },
+ {
+ "-EUR1.234.567,89", "-\u20ac1.234.567,89",
+ "-EUR1234567,89", "-\u20ac1234567,89",
+ }
+ }
+ },
+ {}
+ };
+
+static int
+do_test (void)
+{
+ for (const struct locale_pair *test = tests;
+ test->locale_name != NULL; ++test)
+ {
+ init_loc (en_us_name, test->locale_name);
+ test_pair (&test->pair);
+ freelocale (loc);
+ test_en_us (test->locale_name);
+ }
+
+ return errors;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"

56
glibc-rh1307234-2.patch Normal file
View File

@ -0,0 +1,56 @@
commit b1b8f5d89d06a994773e22ad4b7fe1036b37f8ab
Author: Stefan Liebler <stli@linux.vnet.ibm.com>
Date: Thu Apr 14 12:21:53 2016 +0200
Fix strfmon_l: Use specified locale for number formatting [BZ #19633]
The commit 985fc132f23dbb83de76c5af9e783ef1b5900148
"strfmon_l: Use specified locale for number formatting [BZ #19633]"
introduced an elf/check-abi-libc testfailure due to __printf_fp_l
on architectures which use sysdeps/ieee754/ldbl-opt/math_ldbl_opt.h.
This patch uses libc_hidden_def instead of ldbl_hidden_def.
The ldbl_strong_alias is removed due to the rename of ___printf_fp_l
to __printf_fp_l.
ChangeLog:
* stdio-common/printf_fp.c (__printf_fp_l):
Rename ___printf_fp_l to __printf_fp_l and
remove strong alias. Use libc_hidden_def instead
of ldbl_hidden_def macro.
Index: b/stdio-common/printf_fp.c
===================================================================
--- a/stdio-common/printf_fp.c
+++ b/stdio-common/printf_fp.c
@@ -209,9 +209,9 @@ hack_digit (struct hack_digit_param *p)
}
int
-___printf_fp_l (FILE *fp, locale_t loc,
- const struct printf_info *info,
- const void *const *args)
+__printf_fp_l (FILE *fp, locale_t loc,
+ const struct printf_info *info,
+ const void *const *args)
{
/* The floating-point value to output. */
union
@@ -1251,14 +1251,13 @@ ___printf_fp_l (FILE *fp, locale_t loc,
}
return done;
}
-ldbl_hidden_def (___printf_fp_l, __printf_fp_l)
-ldbl_strong_alias (___printf_fp_l, __printf_fp_l)
+libc_hidden_def (__printf_fp_l)
int
___printf_fp (FILE *fp, const struct printf_info *info,
const void *const *args)
{
- return ___printf_fp_l (fp, _NL_CURRENT_LOCALE, info, args);
+ return __printf_fp_l (fp, _NL_CURRENT_LOCALE, info, args);
}
ldbl_hidden_def (___printf_fp, __printf_fp)
ldbl_strong_alias (___printf_fp, __printf_fp)

46
glibc-rh1310168.patch Normal file
View File

@ -0,0 +1,46 @@
Backport part of this upstream commit:
commit 016495b818cb61df7d0d10e6db54074271b3e3a5
Author: Stefan Liebler <stli@linux.vnet.ibm.com>
Date: Mon Nov 9 16:14:49 2015 +0100
S390: Call direct system calls for socket operations.
this patch calls direct system calls for socket operations in the same way as power does. The system calls were introduced in kernel commit https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=977108f89c989b1eeb5c8d938e1e71913391eb5f.
There are no direct recv, send, accept syscalls available on s390. Thus
recvfrom, sendto, accept4 are called instead of the socketcall by defining __ASSUME_*_FOR_*_SYSCALL macros. See recv.c, send.c, accept.c in sysdeps/unix/sysv/linux/ folder.
The socketcalls in syscalls.list for s390-64 are removed. They were never used on s390x.
The removal is required due to the kernel change because otherwise,
these system calls will be used unconditionally with new kernel
headers.
diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/syscalls.list b/sysdeps/unix/sysv/linux/s390/s390-64/syscalls.list
index 5b8c102..9f03d26 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-64/syscalls.list
+++ b/sysdeps/unix/sysv/linux/s390/s390-64/syscalls.list
@@ -12,22 +12,3 @@ shmget - shmget i:iii __shmget shmget
semop - semop i:ipi __semop semop
semget - semget i:iii __semget semget
semctl - semctl i:iiii __semctl semctl
-
-# proper socket implementations:
-accept - accept Ci:iBN __libc_accept __accept accept
-bind - bind i:ipi __bind bind
-connect - connect Ci:ipi __libc_connect __connect connect
-getpeername - getpeername i:ipp __getpeername getpeername
-getsockname - getsockname i:ipp __getsockname getsockname
-getsockopt - getsockopt i:iiiBN __getsockopt getsockopt
-listen - listen i:ii __listen listen
-recv - recv Ci:ibni __libc_recv __recv recv
-recvfrom - recvfrom Ci:ibniBN __libc_recvfrom __recvfrom recvfrom
-recvmsg - recvmsg Ci:ipi __libc_recvmsg __recvmsg recvmsg
-send - send Ci:ibni __libc_send __send send
-sendmsg - sendmsg Ci:ipi __libc_sendmsg __sendmsg sendmsg
-sendto - sendto Ci:ibnibn __libc_sendto __sendto sendto
-setsockopt - setsockopt i:iiibn __setsockopt setsockopt
-shutdown - shutdown i:ii __shutdown shutdown
-socket - socket i:iii __socket socket
-socketpair - socketpair i:iiif __socketpair socketpair

264
glibc-rh1313404-1.patch Normal file
View File

@ -0,0 +1,264 @@
commit 3c0f7407eedb524c9114bb675cd55b903c71daaa
Author: Florian Weimer <fweimer@redhat.com>
Date: Mon Mar 7 16:00:25 2016 +0100
tst-audit4, tst-audit10: Compile AVX/AVX-512 code separately [BZ #19269]
This ensures that GCC will not use unsupported instructions before
the run-time check to ensure support.
Index: b/sysdeps/x86_64/Makefile
===================================================================
--- a/sysdeps/x86_64/Makefile
+++ b/sysdeps/x86_64/Makefile
@@ -49,7 +49,7 @@ $(objpfx)tst-audit3: $(objpfx)tst-auditm
$(objpfx)tst-audit3.out: $(objpfx)tst-auditmod3b.so
tst-audit3-ENV = LD_AUDIT=$(objpfx)tst-auditmod3b.so
-$(objpfx)tst-audit4: $(objpfx)tst-auditmod4a.so
+$(objpfx)tst-audit4: $(objpfx)tst-audit4-aux.o $(objpfx)tst-auditmod4a.so
$(objpfx)tst-audit4.out: $(objpfx)tst-auditmod4b.so
tst-audit4-ENV = LD_AUDIT=$(objpfx)tst-auditmod4b.so
@@ -66,7 +66,7 @@ $(objpfx)tst-audit7: $(objpfx)tst-auditm
$(objpfx)tst-audit7.out: $(objpfx)tst-auditmod7b.so
tst-audit7-ENV = LD_AUDIT=$(objpfx)tst-auditmod7b.so
-$(objpfx)tst-audit10: $(objpfx)tst-auditmod10a.so
+$(objpfx)tst-audit10: $(objpfx)tst-audit10-aux.o $(objpfx)tst-auditmod10a.so
$(objpfx)tst-audit10.out: $(objpfx)tst-auditmod10b.so
tst-audit10-ENV = LD_AUDIT=$(objpfx)tst-auditmod10b.so
@@ -75,7 +75,7 @@ AVX-CFLAGS=-mavx
ifeq (yes,$(config-cflags-novzeroupper))
AVX-CFLAGS+=-mno-vzeroupper
endif
-CFLAGS-tst-audit4.c += $(AVX-CFLAGS)
+CFLAGS-tst-audit4-aux.c += $(AVX-CFLAGS)
CFLAGS-tst-auditmod4a.c += $(AVX-CFLAGS)
CFLAGS-tst-auditmod4b.c += $(AVX-CFLAGS)
CFLAGS-tst-auditmod6b.c += $(AVX-CFLAGS)
@@ -84,7 +84,7 @@ CFLAGS-tst-auditmod7b.c += $(AVX-CFLAGS)
endif
ifeq (yes,$(config-cflags-avx512))
AVX512-CFLAGS = -mavx512f
-CFLAGS-tst-audit10.c += $(AVX512-CFLAGS)
+CFLAGS-tst-audit10-aux.c += $(AVX512-CFLAGS)
CFLAGS-tst-auditmod10a.c += $(AVX512-CFLAGS)
CFLAGS-tst-auditmod10b.c += $(AVX512-CFLAGS)
endif
Index: b/sysdeps/x86_64/tst-audit10-aux.c
===================================================================
--- /dev/null
+++ b/sysdeps/x86_64/tst-audit10-aux.c
@@ -0,0 +1,41 @@
+/* Test case for preserved AVX512 registers in dynamic linker, -mavx512f part.
+ Copyright (C) 2012-2016 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
+ <http://www.gnu.org/licenses/>. */
+
+#include <immintrin.h>
+#include <stdlib.h>
+#include <string.h>
+
+extern __m512i audit_test (__m512i, __m512i, __m512i, __m512i,
+ __m512i, __m512i, __m512i, __m512i);
+
+int
+tst_audit10_aux (void)
+{
+#ifdef __AVX512F__
+ __m512i zmm = _mm512_setzero_si512 ();
+ __m512i ret = audit_test (zmm, zmm, zmm, zmm, zmm, zmm, zmm, zmm);
+
+ zmm = _mm512_set1_epi64 (0x12349876);
+
+ if (memcmp (&zmm, &ret, sizeof (ret)))
+ abort ();
+ return 0;
+#else /* __AVX512F__ */
+ return 77;
+#endif /* __AVX512F__ */
+}
Index: b/sysdeps/x86_64/tst-audit10.c
===================================================================
--- a/sysdeps/x86_64/tst-audit10.c
+++ b/sysdeps/x86_64/tst-audit10.c
@@ -15,13 +15,9 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
-/* Test case for x86-64 preserved registers in dynamic linker. */
-
-#ifdef __AVX512F__
-#include <stdlib.h>
-#include <string.h>
#include <cpuid.h>
-#include <immintrin.h>
+
+int tst_audit10_aux (void);
static int
avx512_enabled (void)
@@ -42,32 +38,15 @@ avx512_enabled (void)
return (eax & 0xe6) == 0xe6;
}
-
-extern __m512i audit_test (__m512i, __m512i, __m512i, __m512i,
- __m512i, __m512i, __m512i, __m512i);
static int
do_test (void)
{
/* Run AVX512 test only if AVX512 is supported. */
if (avx512_enabled ())
- {
- __m512i zmm = _mm512_setzero_si512 ();
- __m512i ret = audit_test (zmm, zmm, zmm, zmm, zmm, zmm, zmm, zmm);
-
- zmm = _mm512_set1_epi64 (0x12349876);
-
- if (memcmp (&zmm, &ret, sizeof (ret)))
- abort ();
- }
- return 0;
-}
-#else
-static int
-do_test (void)
-{
- return 0;
+ return tst_audit10_aux ();
+ else
+ return 77;
}
-#endif
#define TEST_FUNCTION do_test ()
#include "../../test-skeleton.c"
Index: b/sysdeps/x86_64/tst-audit4-aux.c
===================================================================
--- /dev/null
+++ b/sysdeps/x86_64/tst-audit4-aux.c
@@ -0,0 +1,39 @@
+/* Test case for preserved AVX registers in dynamic linker, -mavx part.
+ Copyright (C) 2009-2016 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
+ <http://www.gnu.org/licenses/>. */
+
+#include <immintrin.h>
+#include <stdlib.h>
+#include <string.h>
+
+extern __m256i audit_test (__m256i, __m256i, __m256i, __m256i,
+ __m256i, __m256i, __m256i, __m256i);
+
+int
+tst_audit4_aux (void)
+{
+#ifdef __AVX__
+ __m256i ymm = _mm256_setzero_si256 ();
+ __m256i ret = audit_test (ymm, ymm, ymm, ymm, ymm, ymm, ymm, ymm);
+ ymm = _mm256_set1_epi32 (0x12349876);
+ if (memcmp (&ymm, &ret, sizeof (ret)))
+ abort ();
+ return 0;
+#else /* __AVX__ */
+ return 77;
+#endif /* __AVX__ */
+}
Index: b/sysdeps/x86_64/tst-audit4.c
===================================================================
--- a/sysdeps/x86_64/tst-audit4.c
+++ b/sysdeps/x86_64/tst-audit4.c
@@ -1,11 +1,24 @@
-/* Test case for x86-64 preserved registers in dynamic linker. */
+/* Test case for preserved AVX registers in dynamic linker.
+ Copyright (C) 2009-2016 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
+ <http://www.gnu.org/licenses/>. */
-#ifdef __AVX__
-#include <stdlib.h>
-#include <string.h>
#include <cpuid.h>
-#include <immintrin.h>
+int tst_audit4_aux (void);
static int
avx_enabled (void)
@@ -22,31 +35,15 @@ avx_enabled (void)
return (eax & 6) == 6;
}
-
-extern __m256i audit_test (__m256i, __m256i, __m256i, __m256i,
- __m256i, __m256i, __m256i, __m256i);
static int
do_test (void)
{
/* Run AVX test only if AVX is supported. */
if (avx_enabled ())
- {
- __m256i ymm = _mm256_setzero_si256 ();
- __m256i ret = audit_test (ymm, ymm, ymm, ymm, ymm, ymm, ymm, ymm);
-
- ymm = _mm256_set1_epi32 (0x12349876);
- if (memcmp (&ymm, &ret, sizeof (ret)))
- abort ();
- }
- return 0;
-}
-#else
-static int
-do_test (void)
-{
- return 0;
+ return tst_audit4_aux ();
+ else
+ return 77;
}
-#endif
#define TEST_FUNCTION do_test ()
#include "../../test-skeleton.c"

39
glibc-rh1313404-2.patch Normal file
View File

@ -0,0 +1,39 @@
commit 3bd80c0de2f8e7ca8020d37739339636d169957e
Author: Roland McGrath <roland@hack.frob.com>
Date: Tue Mar 8 12:31:13 2016 -0800
Fix tst-audit10 build when -mavx512f is not supported.
Index: b/sysdeps/x86_64/tst-audit10-aux.c
===================================================================
--- a/sysdeps/x86_64/tst-audit10-aux.c
+++ b/sysdeps/x86_64/tst-audit10-aux.c
@@ -20,13 +20,13 @@
#include <stdlib.h>
#include <string.h>
-extern __m512i audit_test (__m512i, __m512i, __m512i, __m512i,
- __m512i, __m512i, __m512i, __m512i);
-
int
tst_audit10_aux (void)
{
#ifdef __AVX512F__
+ extern __m512i audit_test (__m512i, __m512i, __m512i, __m512i,
+ __m512i, __m512i, __m512i, __m512i);
+
__m512i zmm = _mm512_setzero_si512 ();
__m512i ret = audit_test (zmm, zmm, zmm, zmm, zmm, zmm, zmm, zmm);
Index: b/sysdeps/x86_64/tst-audit10.c
===================================================================
--- a/sysdeps/x86_64/tst-audit10.c
+++ b/sysdeps/x86_64/tst-audit10.c
@@ -16,6 +16,7 @@
<http://www.gnu.org/licenses/>. */
#include <cpuid.h>
+#include <cpu-features.h>
int tst_audit10_aux (void);

39
glibc-rh1313404-3.patch Normal file
View File

@ -0,0 +1,39 @@
commit f327f5b47be57bc05a4077344b381016c1bb2c11
Author: Florian Weimer <fweimer@redhat.com>
Date: Fri Mar 25 11:11:42 2016 +0100
tst-audit10: Fix compilation on compilers without bit_AVX512F [BZ #19860]
[BZ# 19860]
* sysdeps/x86_64/tst-audit10.c (avx512_enabled): Always return
zero if the compiler does not provide the AVX512F bit.
Index: b/sysdeps/x86_64/tst-audit10.c
===================================================================
--- a/sysdeps/x86_64/tst-audit10.c
+++ b/sysdeps/x86_64/tst-audit10.c
@@ -16,13 +16,13 @@
<http://www.gnu.org/licenses/>. */
#include <cpuid.h>
-#include <cpu-features.h>
int tst_audit10_aux (void);
static int
avx512_enabled (void)
{
+#ifdef bit_AVX512F
unsigned int eax, ebx, ecx, edx;
if (__get_cpuid (1, &eax, &ebx, &ecx, &edx) == 0
@@ -37,6 +37,9 @@ avx512_enabled (void)
/* Verify that ZMM, YMM and XMM states are enabled. */
return (eax & 0xe6) == 0xe6;
+#else
+ return 0;
+#endif
}
static int

213
glibc-rh1315648-1.patch Normal file
View File

@ -0,0 +1,213 @@
commit 137fe72eca6923a00381a3ca9f0e7672c1f85e3f
Author: Florian Weimer <fweimer@redhat.com>
Date: Fri Apr 29 09:33:07 2016 +0200
glob: Simplify the interface for the GLOB_ALTDIRFUNC callback gl_readdir
Previously, application code had to set up the d_namlen member if
the target supported it, involving conditional compilation. After
this change, glob will use the length of the string in d_name instead
of d_namlen to determine the file name length. All glibc targets
provide the d_type and d_ino members, and setting them as needed for
gl_readdir is straightforward.
Changing the behavior with regards to d_ino is left to a future
cleanup.
Index: b/manual/examples/mkdirent.c
===================================================================
--- /dev/null
+++ b/manual/examples/mkdirent.c
@@ -0,0 +1,42 @@
+/* Example for creating a struct dirent object for use with glob.
+ Copyright (C) 2016 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, if not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <dirent.h>
+#include <errno.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+struct dirent *
+mkdirent (const char *name)
+{
+ size_t dirent_size = offsetof (struct dirent, d_name) + 1;
+ size_t name_length = strlen (name);
+ size_t total_size = dirent_size + name_length;
+ if (total_size < dirent_size)
+ {
+ errno = ENOMEM;
+ return NULL;
+ }
+ struct dirent *result = malloc (total_size);
+ if (result == NULL)
+ return NULL;
+ result->d_type = DT_UNKNOWN;
+ result->d_ino = 1; /* Do not skip this entry. */
+ memcpy (result->d_name, name, name_length + 1);
+ return result;
+}
Index: b/manual/pattern.texi
===================================================================
--- a/manual/pattern.texi
+++ b/manual/pattern.texi
@@ -237,7 +237,44 @@ function used to read the contents of a
@code{GLOB_ALTDIRFUNC} bit is set in the flag parameter. The type of
this field is @w{@code{struct dirent *(*) (void *)}}.
-This is a GNU extension.
+An implementation of @code{gl_readdir} needs to initialize the following
+members of the @code{struct dirent} object:
+
+@table @code
+@item d_type
+This member should be set to the file type of the entry if it is known.
+Otherwise, the value @code{DT_UNKNOWN} can be used. The @code{glob}
+function may use the specified file type to avoid callbacks in cases
+where the file type indicates that the data is not required.
+
+@item d_ino
+This member needs to be non-zero, otherwise @code{glob} may skip the
+current entry and call the @code{gl_readdir} callback function again to
+retrieve another entry.
+
+@item d_name
+This member must be set to the name of the entry. It must be
+null-terminated.
+@end table
+
+The example below shows how to allocate a @code{struct dirent} object
+containing a given name.
+
+@smallexample
+@include mkdirent.c.texi
+@end smallexample
+
+The @code{glob} function reads the @code{struct dirent} members listed
+above and makes a copy of the file name in the @code{d_name} member
+immediately after the @code{gl_readdir} callback function returns.
+Future invocations of any of the callback functions may dealloacte or
+reuse the buffer. It is the responsibility of the caller of the
+@code{glob} function to allocate and deallocate the buffer, around the
+call to @code{glob} or using the callback functions. For example, an
+application could allocate the buffer in the @code{gl_readdir} callback
+function, and deallocate it in the @code{gl_closedir} callback function.
+
+The @code{gl_readdir} member is a GNU extension.
@item gl_opendir
The address of an alternative implementation of the @code{opendir}
Index: b/posix/bug-glob2.c
===================================================================
--- a/posix/bug-glob2.c
+++ b/posix/bug-glob2.c
@@ -193,7 +193,7 @@ my_readdir (void *gdir)
return NULL;
}
- dir->d.d_ino = dir->idx;
+ dir->d.d_ino = 1; /* glob should not skip this entry. */
#ifdef _DIRENT_HAVE_D_TYPE
dir->d.d_type = filesystem[dir->idx].type;
Index: b/posix/glob.c
===================================================================
--- a/posix/glob.c
+++ b/posix/glob.c
@@ -57,10 +57,8 @@
#if defined HAVE_DIRENT_H || defined __GNU_LIBRARY__
# include <dirent.h>
-# define NAMLEN(dirent) strlen((dirent)->d_name)
#else
# define dirent direct
-# define NAMLEN(dirent) (dirent)->d_namlen
# ifdef HAVE_SYS_NDIR_H
# include <sys/ndir.h>
# endif
@@ -76,12 +74,6 @@
#endif
-/* In GNU systems, <dirent.h> defines this macro for us. */
-#ifdef _D_NAMLEN
-# undef NAMLEN
-# define NAMLEN(d) _D_NAMLEN(d)
-#endif
-
/* When used in the GNU libc the symbol _DIRENT_HAVE_D_TYPE is available
if the `d_type' member for `struct dirent' is available.
HAVE_STRUCT_DIRENT_D_TYPE plays the same role in GNULIB. */
@@ -105,12 +97,6 @@
/* If the system has the `struct dirent64' type we use it internally. */
#if defined _LIBC && !defined COMPILE_GLOB64
-# if defined HAVE_DIRENT_H || defined __GNU_LIBRARY__
-# define CONVERT_D_NAMLEN(d64, d32)
-# else
-# define CONVERT_D_NAMLEN(d64, d32) \
- (d64)->d_namlen = (d32)->d_namlen;
-# endif
# if (defined POSIX || defined WINDOWS32) && !defined __GNU_LIBRARY__
# define CONVERT_D_INO(d64, d32)
@@ -127,8 +113,7 @@
# endif
# define CONVERT_DIRENT_DIRENT64(d64, d32) \
- memcpy ((d64)->d_name, (d32)->d_name, NAMLEN (d32) + 1); \
- CONVERT_D_NAMLEN (d64, d32) \
+ strcpy ((d64)->d_name, (d32)->d_name); \
CONVERT_D_INO (d64, d32) \
CONVERT_D_TYPE (d64, d32)
#endif
@@ -1562,7 +1547,6 @@ glob_in_dir (const char *pattern, const
while (1)
{
const char *name;
- size_t len;
#if defined _LIBC && !defined COMPILE_GLOB64
struct dirent64 *d;
union
@@ -1630,12 +1614,10 @@ glob_in_dir (const char *pattern, const
names = newnames;
cur = 0;
}
- len = NAMLEN (d);
- names->name[cur] = (char *) malloc (len + 1);
+ names->name[cur] = strdup (d->d_name);
if (names->name[cur] == NULL)
goto memory_error;
- *((char *) mempcpy (names->name[cur++], name, len))
- = '\0';
+ ++cur;
++nfound;
}
}
Index: b/posix/tst-gnuglob.c
===================================================================
--- a/posix/tst-gnuglob.c
+++ b/posix/tst-gnuglob.c
@@ -211,7 +211,7 @@ my_readdir (void *gdir)
return NULL;
}
- dir->d.d_ino = dir->idx;
+ dir->d.d_ino = 1; /* glob should not skip this entry. */
#ifdef _DIRENT_HAVE_D_TYPE
dir->d.d_type = filesystem[dir->idx].type;

370
glibc-rh1315648-2.patch Normal file
View File

@ -0,0 +1,370 @@
commit 5171f3079f2cc53e0548fc4967361f4d1ce9d7ea
Author: Florian Weimer <fweimer@redhat.com>
Date: Wed May 4 12:09:35 2016 +0200
CVE-2016-1234: glob: Do not copy d_name field of struct dirent [BZ #19779]
Instead, we store the data we need from the return value of
readdir in an object of the new type struct readdir_result.
This type is independent of the layout of struct dirent.
Index: b/posix/bug-glob2.c
===================================================================
--- a/posix/bug-glob2.c
+++ b/posix/bug-glob2.c
@@ -40,6 +40,17 @@
# define PRINTF(fmt, args...)
#endif
+#define LONG_NAME \
+ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
+ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
+ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
+ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
+ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
+ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
+ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
+ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
+ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
+ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
static struct
{
@@ -58,6 +69,7 @@ static struct
{ ".", 3, DT_DIR, 0755 },
{ "..", 3, DT_DIR, 0755 },
{ "a", 3, DT_REG, 0644 },
+ { LONG_NAME, 3, DT_REG, 0644 },
{ "unreadable", 2, DT_DIR, 0111 },
{ ".", 3, DT_DIR, 0111 },
{ "..", 3, DT_DIR, 0755 },
@@ -75,7 +87,7 @@ typedef struct
int level;
int idx;
struct dirent d;
- char room_for_dirent[NAME_MAX];
+ char room_for_dirent[sizeof (LONG_NAME)];
} my_DIR;
Index: b/posix/glob.c
===================================================================
--- a/posix/glob.c
+++ b/posix/glob.c
@@ -24,7 +24,9 @@
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
+#include <stdbool.h>
#include <stddef.h>
+#include <stdint.h>
/* Outcomment the following line for production quality code. */
/* #define NDEBUG 1 */
@@ -73,69 +75,8 @@
# endif /* HAVE_VMSDIR_H */
#endif
-
-/* When used in the GNU libc the symbol _DIRENT_HAVE_D_TYPE is available
- if the `d_type' member for `struct dirent' is available.
- HAVE_STRUCT_DIRENT_D_TYPE plays the same role in GNULIB. */
-#if defined _DIRENT_HAVE_D_TYPE || defined HAVE_STRUCT_DIRENT_D_TYPE
-/* True if the directory entry D must be of type T. */
-# define DIRENT_MUST_BE(d, t) ((d)->d_type == (t))
-
-/* True if the directory entry D might be a symbolic link. */
-# define DIRENT_MIGHT_BE_SYMLINK(d) \
- ((d)->d_type == DT_UNKNOWN || (d)->d_type == DT_LNK)
-
-/* True if the directory entry D might be a directory. */
-# define DIRENT_MIGHT_BE_DIR(d) \
- ((d)->d_type == DT_DIR || DIRENT_MIGHT_BE_SYMLINK (d))
-
-#else /* !HAVE_D_TYPE */
-# define DIRENT_MUST_BE(d, t) false
-# define DIRENT_MIGHT_BE_SYMLINK(d) true
-# define DIRENT_MIGHT_BE_DIR(d) true
-#endif /* HAVE_D_TYPE */
-
-/* If the system has the `struct dirent64' type we use it internally. */
-#if defined _LIBC && !defined COMPILE_GLOB64
-
-# if (defined POSIX || defined WINDOWS32) && !defined __GNU_LIBRARY__
-# define CONVERT_D_INO(d64, d32)
-# else
-# define CONVERT_D_INO(d64, d32) \
- (d64)->d_ino = (d32)->d_ino;
-# endif
-
-# ifdef _DIRENT_HAVE_D_TYPE
-# define CONVERT_D_TYPE(d64, d32) \
- (d64)->d_type = (d32)->d_type;
-# else
-# define CONVERT_D_TYPE(d64, d32)
-# endif
-
-# define CONVERT_DIRENT_DIRENT64(d64, d32) \
- strcpy ((d64)->d_name, (d32)->d_name); \
- CONVERT_D_INO (d64, d32) \
- CONVERT_D_TYPE (d64, d32)
-#endif
-
-
-#if (defined POSIX || defined WINDOWS32) && !defined __GNU_LIBRARY__
-/* Posix does not require that the d_ino field be present, and some
- systems do not provide it. */
-# define REAL_DIR_ENTRY(dp) 1
-#else
-# define REAL_DIR_ENTRY(dp) (dp->d_ino != 0)
-#endif /* POSIX */
-
#include <stdlib.h>
#include <string.h>
-
-/* NAME_MAX is usually defined in <dirent.h> or <limits.h>. */
-#include <limits.h>
-#ifndef NAME_MAX
-# define NAME_MAX (sizeof (((struct dirent *) 0)->d_name))
-#endif
-
#include <alloca.h>
#ifdef _LIBC
@@ -180,8 +121,111 @@
static const char *next_brace_sub (const char *begin, int flags) __THROWNL;
+/* A representation of a directory entry which does not depend on the
+ layout of struct dirent, or the size of ino_t. */
+struct readdir_result
+{
+ const char *name;
+# if defined _DIRENT_HAVE_D_TYPE || defined HAVE_STRUCT_DIRENT_D_TYPE
+ uint8_t type;
+# endif
+ bool skip_entry;
+};
+
+# if defined _DIRENT_HAVE_D_TYPE || defined HAVE_STRUCT_DIRENT_D_TYPE
+/* Initializer based on the d_type member of struct dirent. */
+# define D_TYPE_TO_RESULT(source) (source)->d_type,
+
+/* True if the directory entry D might be a symbolic link. */
+static bool
+readdir_result_might_be_symlink (struct readdir_result d)
+{
+ return d.type == DT_UNKNOWN || d.type == DT_LNK;
+}
+
+/* True if the directory entry D might be a directory. */
+static bool
+readdir_result_might_be_dir (struct readdir_result d)
+{
+ return d.type == DT_DIR || readdir_result_might_be_symlink (d);
+}
+# else /* defined _DIRENT_HAVE_D_TYPE || defined HAVE_STRUCT_DIRENT_D_TYPE */
+# define D_TYPE_TO_RESULT(source)
+
+/* If we do not have type information, symbolic links and directories
+ are always a possibility. */
+
+static bool
+readdir_result_might_be_symlink (struct readdir_result d)
+{
+ return true;
+}
+
+static bool
+readdir_result_might_be_dir (struct readdir_result d)
+{
+ return true;
+}
+
+# endif /* defined _DIRENT_HAVE_D_TYPE || defined HAVE_STRUCT_DIRENT_D_TYPE */
+
+# if (defined POSIX || defined WINDOWS32) && !defined __GNU_LIBRARY__
+/* Initializer for skip_entry. POSIX does not require that the d_ino
+ field be present, and some systems do not provide it. */
+# define D_INO_TO_RESULT(source) false,
+# else
+# define D_INO_TO_RESULT(source) (source)->d_ino == 0,
+# endif
+
+/* Construct an initializer for a struct readdir_result object from a
+ struct dirent *. No copy of the name is made. */
+#define READDIR_RESULT_INITIALIZER(source) \
+ { \
+ source->d_name, \
+ D_TYPE_TO_RESULT (source) \
+ D_INO_TO_RESULT (source) \
+ }
+
#endif /* !defined _LIBC || !defined GLOB_ONLY_P */
+/* Call gl_readdir on STREAM. This macro can be overridden to reduce
+ type safety if an old interface version needs to be supported. */
+#ifndef GL_READDIR
+# define GL_READDIR(pglob, stream) ((pglob)->gl_readdir (stream))
+#endif
+
+/* Extract name and type from directory entry. No copy of the name is
+ made. If SOURCE is NULL, result name is NULL. Keep in sync with
+ convert_dirent64 below. */
+static struct readdir_result
+convert_dirent (const struct dirent *source)
+{
+ if (source == NULL)
+ {
+ struct readdir_result result = { NULL, };
+ return result;
+ }
+ struct readdir_result result = READDIR_RESULT_INITIALIZER (source);
+ return result;
+}
+
+#ifndef COMPILE_GLOB64
+/* Like convert_dirent, but works on struct dirent64 instead. Keep in
+ sync with convert_dirent above. */
+static struct readdir_result
+convert_dirent64 (const struct dirent64 *source)
+{
+ if (source == NULL)
+ {
+ struct readdir_result result = { NULL, };
+ return result;
+ }
+ struct readdir_result result = READDIR_RESULT_INITIALIZER (source);
+ return result;
+}
+#endif
+
+
#ifndef attribute_hidden
# define attribute_hidden
#endif
@@ -1546,55 +1590,36 @@ glob_in_dir (const char *pattern, const
while (1)
{
- const char *name;
-#if defined _LIBC && !defined COMPILE_GLOB64
- struct dirent64 *d;
- union
- {
- struct dirent64 d64;
- char room [offsetof (struct dirent64, d_name[0])
- + NAME_MAX + 1];
- }
- d64buf;
-
- if (__glibc_unlikely (flags & GLOB_ALTDIRFUNC))
- {
- struct dirent *d32 = (*pglob->gl_readdir) (stream);
- if (d32 != NULL)
- {
- CONVERT_DIRENT_DIRENT64 (&d64buf.d64, d32);
- d = &d64buf.d64;
- }
- else
- d = NULL;
- }
- else
- d = __readdir64 (stream);
+ struct readdir_result d;
+ {
+ if (__builtin_expect (flags & GLOB_ALTDIRFUNC, 0))
+ d = convert_dirent (GL_READDIR (pglob, stream));
+ else
+ {
+#ifdef COMPILE_GLOB64
+ d = convert_dirent (__readdir (stream));
#else
- struct dirent *d = (__builtin_expect (flags & GLOB_ALTDIRFUNC, 0)
- ? ((struct dirent *)
- (*pglob->gl_readdir) (stream))
- : __readdir (stream));
+ d = convert_dirent64 (__readdir64 (stream));
#endif
- if (d == NULL)
+ }
+ }
+ if (d.name == NULL)
break;
- if (! REAL_DIR_ENTRY (d))
+ if (d.skip_entry)
continue;
/* If we shall match only directories use the information
provided by the dirent call if possible. */
- if ((flags & GLOB_ONLYDIR) && !DIRENT_MIGHT_BE_DIR (d))
+ if ((flags & GLOB_ONLYDIR) && !readdir_result_might_be_dir (d))
continue;
- name = d->d_name;
-
- if (fnmatch (pattern, name, fnm_flags) == 0)
+ if (fnmatch (pattern, d.name, fnm_flags) == 0)
{
/* If the file we found is a symlink we have to
make sure the target file exists. */
- if (!DIRENT_MIGHT_BE_SYMLINK (d)
- || link_exists_p (dfd, directory, dirlen, name, pglob,
- flags))
+ if (!readdir_result_might_be_symlink (d)
+ || link_exists_p (dfd, directory, dirlen, d.name,
+ pglob, flags))
{
if (cur == names->count)
{
@@ -1614,7 +1639,7 @@ glob_in_dir (const char *pattern, const
names = newnames;
cur = 0;
}
- names->name[cur] = strdup (d->d_name);
+ names->name[cur] = strdup (d.name);
if (names->name[cur] == NULL)
goto memory_error;
++cur;
Index: b/sysdeps/unix/sysv/linux/i386/glob64.c
===================================================================
--- a/sysdeps/unix/sysv/linux/i386/glob64.c
+++ b/sysdeps/unix/sysv/linux/i386/glob64.c
@@ -1,3 +1,21 @@
+/* Two glob variants with 64-bit support, for dirent64 and __olddirent64.
+ Copyright (C) 1998-2016 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
+ <http://www.gnu.org/licenses/>. */
+
#include <dirent.h>
#include <glob.h>
#include <sys/stat.h>
@@ -38,11 +56,15 @@ int __old_glob64 (const char *__pattern,
#undef dirent
#define dirent __old_dirent64
+#undef GL_READDIR
+# define GL_READDIR(pglob, stream) \
+ ((struct __old_dirent64 *) (pglob)->gl_readdir (stream))
#undef __readdir
#define __readdir(dirp) __old_readdir64 (dirp)
#undef glob
#define glob(pattern, flags, errfunc, pglob) \
__old_glob64 (pattern, flags, errfunc, pglob)
+#define convert_dirent __old_convert_dirent
#define glob_in_dir __old_glob_in_dir
#define GLOB_ATTRIBUTE attribute_compat_text_section

117
glibc-rh1316972-2.patch Normal file
View File

@ -0,0 +1,117 @@
commit b9bdfa7c8fa22c944bb5f21a673dfd1f91b71c56
Author: Florian Weimer <fweimer@redhat.com>
Date: Wed Apr 27 14:26:47 2016 +0200
resolv: Always set *resplen2 out parameter in send_vc [BZ #19825]
In various error scenarios (for example, if the server closes the
TCP connection before sending the full response), send_vc can return
without resetting the *resplen2 value. This can pass uninitialized
or unexpected data to the caller.
Index: b/resolv/res_send.c
===================================================================
--- a/resolv/res_send.c
+++ b/resolv/res_send.c
@@ -796,8 +796,6 @@ send_vc(res_state statp,
u_short len2;
u_char *cp;
- if (resplen2 != NULL)
- *resplen2 = 0;
connreset = 0;
same_ns:
truncating = 0;
@@ -823,6 +821,8 @@ send_vc(res_state statp,
if (statp->_vcsock < 0) {
*terrno = errno;
Perror(statp, stderr, "socket(vc)", errno);
+ if (resplen2 != NULL)
+ *resplen2 = 0;
return (-1);
}
__set_errno (0);
@@ -833,8 +833,7 @@ send_vc(res_state statp,
*terrno = errno;
Aerror(statp, stderr, "connect/vc", errno,
(struct sockaddr *) nsap);
- __res_iclose(statp, false);
- return (0);
+ return close_and_return_error (statp, resplen2);
}
statp->_flags |= RES_F_VC;
}
@@ -857,8 +856,7 @@ send_vc(res_state statp,
if (TEMP_FAILURE_RETRY (writev(statp->_vcsock, iov, niov)) != explen) {
*terrno = errno;
Perror(statp, stderr, "write failed", errno);
- __res_iclose(statp, false);
- return (0);
+ return close_and_return_error (statp, resplen2);
}
/*
* Receive length & response
@@ -880,7 +878,6 @@ send_vc(res_state statp,
if (n <= 0) {
*terrno = errno;
Perror(statp, stderr, "read failed", errno);
- __res_iclose(statp, false);
/*
* A long running process might get its TCP
* connection reset if the remote server was
@@ -890,11 +887,13 @@ send_vc(res_state statp,
* instead of failing. We only allow one reset
* per query to prevent looping.
*/
- if (*terrno == ECONNRESET && !connreset) {
- connreset = 1;
- goto same_ns;
- }
- return (0);
+ if (*terrno == ECONNRESET && !connreset)
+ {
+ __res_iclose (statp, false);
+ connreset = 1;
+ goto same_ns;
+ }
+ return close_and_return_error (statp, resplen2);
}
int rlen = ntohs (rlen16);
@@ -926,11 +925,11 @@ send_vc(res_state statp,
/* Always allocate MAXPACKET, callers expect
this specific size. */
u_char *newp = malloc (MAXPACKET);
- if (newp == NULL) {
- *terrno = ENOMEM;
- __res_iclose(statp, false);
- return (0);
- }
+ if (newp == NULL)
+ {
+ *terrno = ENOMEM;
+ return close_and_return_error (statp, resplen2);
+ }
*thisanssizp = MAXPACKET;
*thisansp = newp;
if (thisansp == ansp2)
@@ -957,8 +956,7 @@ send_vc(res_state statp,
Dprint(statp->options & RES_DEBUG,
(stdout, ";; undersized: %d\n", len));
*terrno = EMSGSIZE;
- __res_iclose(statp, false);
- return (0);
+ return close_and_return_error (statp, resplen2);
}
cp = *thisansp;
@@ -969,8 +967,7 @@ send_vc(res_state statp,
if (__glibc_unlikely (n <= 0)) {
*terrno = errno;
Perror(statp, stderr, "read(vc)", errno);
- __res_iclose(statp, false);
- return (0);
+ return close_and_return_error (statp, resplen2);
}
if (__glibc_unlikely (truncating)) {
/*

216
glibc-rh1316972.patch Normal file
View File

@ -0,0 +1,216 @@
commit b66d837bb5398795c6b0f651bd5a5d66091d8577
Author: Florian Weimer <fweimer@redhat.com>
Date: Fri Mar 25 11:49:51 2016 +0100
resolv: Always set *resplen2 out parameter in send_dg [BZ #19791]
Since commit 44d20bca52ace85850012b0ead37b360e3ecd96e (Implement
second fallback mode for DNS requests), there is a code path which
returns early, before *resplen2 is initialized. This happens if the
name server address is immediately recognized as invalid (because of
lack of protocol support, or if it is a broadcast address such
255.255.255.255, or another invalid address).
If this happens and *resplen2 was non-zero (which is the case if a
previous query resulted in a failure), __libc_res_nquery would reuse
an existing second answer buffer. This answer has been previously
identified as unusable (for example, it could be an NXDOMAIN
response). Due to the presence of a second answer, no name server
switching will occur. The result is a name resolution failure,
although a successful resolution would have been possible if name
servers have been switched and queries had proceeded along the search
path.
The above paragraph still simplifies the situation. Before glibc
2.23, if the second answer needed malloc, the stub resolver would
still attempt to reuse the second answer, but this is not possible
because __libc_res_nsearch has freed it, after the unsuccessful call
to __libc_res_nquerydomain, and set the buffer pointer to NULL. This
eventually leads to an assertion failure in __libc_res_nquery:
/* Make sure both hp and hp2 are defined */
assert((hp != NULL) && (hp2 != NULL));
If assertions are disabled, the consequence is a NULL pointer
dereference on the next line.
Starting with glibc 2.23, as a result of commit
e9db92d3acfe1822d56d11abcea5bfc4c41cf6ca (CVE-2015-7547: getaddrinfo()
stack-based buffer overflow (Bug 18665)), the second answer is always
allocated with malloc. This means that the assertion failure happens
with small responses as well because there is no buffer to reuse, as
soon as there is a name resolution failure which triggers a search for
an answer along the search path.
This commit addresses the issue by ensuring that *resplen2 is
initialized before the send_dg function returns.
This commit also addresses a bug where an invalid second reply is
incorrectly returned as a valid to the caller.
Index: b/resolv/res_send.c
===================================================================
--- a/resolv/res_send.c
+++ b/resolv/res_send.c
@@ -679,6 +679,18 @@ libresolv_hidden_def (res_nsend)
/* Private */
+/* Close the resolver structure, assign zero to *RESPLEN2 if RESPLEN2
+ is not NULL, and return zero. */
+static int
+__attribute__ ((warn_unused_result))
+close_and_return_error (res_state statp, int *resplen2)
+{
+ __res_iclose(statp, false);
+ if (resplen2 != NULL)
+ *resplen2 = 0;
+ return 0;
+}
+
/* The send_vc function is responsible for sending a DNS query over TCP
to the nameserver numbered NS from the res_state STATP i.e.
EXT(statp).nssocks[ns]. The function supports sending both IPv4 and
@@ -1183,7 +1195,11 @@ send_dg(res_state statp,
retry_reopen:
retval = reopen (statp, terrno, ns);
if (retval <= 0)
- return retval;
+ {
+ if (resplen2 != NULL)
+ *resplen2 = 0;
+ return retval;
+ }
retry:
evNowTime(&now);
evConsTime(&timeout, seconds, 0);
@@ -1196,8 +1212,6 @@ send_dg(res_state statp,
int recvresp2 = buf2 == NULL;
pfd[0].fd = EXT(statp).nssocks[ns];
pfd[0].events = POLLOUT;
- if (resplen2 != NULL)
- *resplen2 = 0;
wait:
if (need_recompute) {
recompute_resend:
@@ -1205,9 +1219,7 @@ send_dg(res_state statp,
if (evCmpTime(finish, now) <= 0) {
poll_err_out:
Perror(statp, stderr, "poll", errno);
- err_out:
- __res_iclose(statp, false);
- return (0);
+ return close_and_return_error (statp, resplen2);
}
evSubTime(&timeout, &finish, &now);
need_recompute = 0;
@@ -1254,7 +1266,9 @@ send_dg(res_state statp,
}
*gotsomewhere = 1;
- return (0);
+ if (resplen2 != NULL)
+ *resplen2 = 0;
+ return 0;
}
if (n < 0) {
if (errno == EINTR)
@@ -1322,7 +1336,7 @@ send_dg(res_state statp,
fail_sendmmsg:
Perror(statp, stderr, "sendmmsg", errno);
- goto err_out;
+ return close_and_return_error (statp, resplen2);
}
}
else
@@ -1340,7 +1354,7 @@ send_dg(res_state statp,
if (errno == EINTR || errno == EAGAIN)
goto recompute_resend;
Perror(statp, stderr, "send", errno);
- goto err_out;
+ return close_and_return_error (statp, resplen2);
}
just_one:
if (nwritten != 0 || buf2 == NULL || single_request)
@@ -1418,7 +1432,7 @@ send_dg(res_state statp,
goto wait;
}
Perror(statp, stderr, "recvfrom", errno);
- goto err_out;
+ return close_and_return_error (statp, resplen2);
}
*gotsomewhere = 1;
if (__glibc_unlikely (*thisresplenp < HFIXEDSZ)) {
@@ -1429,7 +1443,7 @@ send_dg(res_state statp,
(stdout, ";; undersized: %d\n",
*thisresplenp));
*terrno = EMSGSIZE;
- goto err_out;
+ return close_and_return_error (statp, resplen2);
}
if ((recvresp1 || hp->id != anhp->id)
&& (recvresp2 || hp2->id != anhp->id)) {
@@ -1478,7 +1492,7 @@ send_dg(res_state statp,
? *thisanssizp : *thisresplenp);
/* record the error */
statp->_flags |= RES_F_EDNS0ERR;
- goto err_out;
+ return close_and_return_error (statp, resplen2);
}
#endif
if (!(statp->options & RES_INSECURE2)
@@ -1530,10 +1544,10 @@ send_dg(res_state statp,
goto wait;
}
- __res_iclose(statp, false);
/* don't retry if called from dig */
if (!statp->pfcode)
- return (0);
+ return close_and_return_error (statp, resplen2);
+ __res_iclose(statp, false);
}
if (anhp->rcode == NOERROR && anhp->ancount == 0
&& anhp->aa == 0 && anhp->ra == 0 && anhp->arcount == 0) {
@@ -1555,6 +1569,8 @@ send_dg(res_state statp,
__res_iclose(statp, false);
// XXX if we have received one reply we could
// XXX use it and not repeat it over TCP...
+ if (resplen2 != NULL)
+ *resplen2 = 0;
return (1);
}
/* Mark which reply we received. */
@@ -1570,21 +1586,22 @@ send_dg(res_state statp,
__res_iclose (statp, false);
retval = reopen (statp, terrno, ns);
if (retval <= 0)
- return retval;
+ {
+ if (resplen2 != NULL)
+ *resplen2 = 0;
+ return retval;
+ }
pfd[0].fd = EXT(statp).nssocks[ns];
}
}
goto wait;
}
- /*
- * All is well, or the error is fatal. Signal that the
- * next nameserver ought not be tried.
- */
+ /* All is well. We have received both responses (if
+ two responses were requested). */
return (resplen);
- } else if (pfd[0].revents & (POLLERR | POLLHUP | POLLNVAL)) {
- /* Something went wrong. We can stop trying. */
- goto err_out;
- }
+ } else if (pfd[0].revents & (POLLERR | POLLHUP | POLLNVAL))
+ /* Something went wrong. We can stop trying. */
+ return close_and_return_error (statp, resplen2);
else {
/* poll should not have returned > 0 in this case. */
abort ();

17
glibc-rh1321372.patch Normal file
View File

@ -0,0 +1,17 @@
Partial backport of 0a410e76f551c6e6cf6d128f618208049d6a952c
(localedata: CLDRv29: update LC_TIME week/first_week,workday fields)
to fix just the es_CL locale.
Index: b/localedata/locales/es_CL
===================================================================
--- a/localedata/locales/es_CL
+++ b/localedata/locales/es_CL
@@ -118,6 +118,8 @@ t_fmt_ampm ""
date_fmt "<U0025><U0061><U0020><U0025><U0062><U0020><U0025><U0065>/
<U0020><U0025><U0048><U003A><U0025><U004D><U003A><U0025><U0053><U0020>/
<U0025><U005A><U0020><U0025><U0059>"
+week 7;19971130;1
+first_weekday 2
END LC_TIME
LC_PAPER

36
glibc-rh1321861.patch Normal file
View File

@ -0,0 +1,36 @@
commit a6033052d08027f745867e5e346852da1959226c
Author: Florian Weimer <fweimer@redhat.com>
Date: Tue Mar 29 11:27:32 2016 +0200
nss_db: Propagate ERANGE error if parse_line fails [BZ #19837]
Reproducer (needs to run as root):
perl -e \
'print "large:x:999:" . join(",", map {"user$_"} (1 .. 135))."\n"' \
>> /etc/group
cd /var/db
make
getent -s db group
After the fix, the last command should list the "large" group.
The magic number 135 has been chosen so that the line is shorter than
1024 bytes, but the pointers required to encode the member array will
cross the threshold, triggering the bug.
diff --git a/nss/nss_db/db-XXX.c b/nss/nss_db/db-XXX.c
index 03c18d7..125a5e9 100644
--- a/nss/nss_db/db-XXX.c
+++ b/nss/nss_db/db-XXX.c
@@ -288,8 +288,8 @@ CONCAT(_nss_db_get,ENTNAME_r) (struct STRUCTURE *result, char *buffer,
}
if (err < 0)
{
- H_ERRNO_SET (HOST_NOT_FOUND);
- status = NSS_STATUS_NOTFOUND;
+ H_ERRNO_SET (NETDB_INTERNAL);
+ status = NSS_STATUS_TRYAGAIN;
break;
}

32
glibc-rh1321954.patch Normal file
View File

@ -0,0 +1,32 @@
commit 317b199b4aff8cfa27f2302ab404d2bb5032b9a4
Author: Florian Weimer <fweimer@redhat.com>
Date: Tue Mar 29 12:57:56 2016 +0200
CVE-2016-3075: Stack overflow in _nss_dns_getnetbyname_r [BZ #19879]
The defensive copy is not needed because the name may not alias the
output buffer.
diff --git a/resolv/nss_dns/dns-network.c b/resolv/nss_dns/dns-network.c
index 2eb2f67..8f301a7 100644
--- a/resolv/nss_dns/dns-network.c
+++ b/resolv/nss_dns/dns-network.c
@@ -118,17 +118,14 @@ _nss_dns_getnetbyname_r (const char *name, struct netent *result,
} net_buffer;
querybuf *orig_net_buffer;
int anslen;
- char *qbuf;
enum nss_status status;
if (__res_maybe_init (&_res, 0) == -1)
return NSS_STATUS_UNAVAIL;
- qbuf = strdupa (name);
-
net_buffer.buf = orig_net_buffer = (querybuf *) alloca (1024);
- anslen = __libc_res_nsearch (&_res, qbuf, C_IN, T_PTR, net_buffer.buf->buf,
+ anslen = __libc_res_nsearch (&_res, name, C_IN, T_PTR, net_buffer.buf->buf,
1024, &net_buffer.ptr, NULL, NULL, NULL, NULL);
if (anslen < 0)
{

73
glibc-rh1326903.patch Normal file
View File

@ -0,0 +1,73 @@
commit f06f3f05b48c72e2c9b0fa78671f94fd22d67da8
Author: Florian Weimer <fweimer@redhat.com>
Date: Wed Jun 1 07:14:42 2016 +0200
fork in libpthread cannot use IFUNC resolver [BZ #19861]
This commit only addresses the fork case, the vfork case has to be a
tail call, which is why the generic code needs an IFUNC resolver
there.
diff --git a/nptl/pt-fork.c b/nptl/pt-fork.c
index b65d6b4..db9b61d 100644
--- a/nptl/pt-fork.c
+++ b/nptl/pt-fork.c
@@ -25,33 +25,14 @@
the historical ABI requires it. For static linking, there is no need to
provide anything here--the libc version will be linked in. For shared
library ABI compatibility, there must be __fork and fork symbols in
- libpthread.so; so we define them using IFUNC to redirect to the libc
- function. */
+ libpthread.so.
-#if SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_22)
-
-# if HAVE_IFUNC
-
-static __typeof (fork) *
-__attribute__ ((used))
-fork_resolve (void)
-{
- return &__libc_fork;
-}
+ With an IFUNC resolver, it would be possible to avoid the
+ indirection, but the IFUNC resolver might run before the
+ __libc_fork symbol has been relocated, in which case the IFUNC
+ resolver would not be able to provide the correct address. */
-# ifdef HAVE_ASM_SET_DIRECTIVE
-# define DEFINE_FORK(name) \
- asm (".set " #name ", fork_resolve\n" \
- ".globl " #name "\n" \
- ".type " #name ", %gnu_indirect_function");
-# else
-# define DEFINE_FORK(name) \
- asm (#name " = fork_resolve\n" \
- ".globl " #name "\n" \
- ".type " #name ", %gnu_indirect_function");
-# endif
-
-# else /* !HAVE_IFUNC */
+#if SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_22)
static pid_t __attribute__ ((used))
fork_compat (void)
@@ -59,14 +40,10 @@ fork_compat (void)
return __libc_fork ();
}
-# define DEFINE_FORK(name) strong_alias (fork_compat, name)
-
-# endif /* HAVE_IFUNC */
-
-DEFINE_FORK (fork_ifunc)
-compat_symbol (libpthread, fork_ifunc, fork, GLIBC_2_0);
+strong_alias (fork_compat, fork_alias)
+compat_symbol (libpthread, fork_alias, fork, GLIBC_2_0);
-DEFINE_FORK (__fork_ifunc)
-compat_symbol (libpthread, __fork_ifunc, __fork, GLIBC_2_0);
+strong_alias (fork_compat, __fork_alias)
+compat_symbol (libpthread, __fork_alias, __fork, GLIBC_2_0);
#endif

193
glibc-rh1330888.patch Normal file
View File

@ -0,0 +1,193 @@
commit 4ab2ab03d4351914ee53248dc5aef4a8c88ff8b9
Author: Florian Weimer <fweimer@redhat.com>
Date: Fri Apr 29 10:35:34 2016 +0200
CVE-2016-3706: getaddrinfo: stack overflow in hostent conversion [BZ #20010]
When converting a struct hostent response to struct gaih_addrtuple, the
gethosts macro (which is called from gaih_inet) used alloca, without
malloc fallback for large responses. This commit changes this code to
use calloc unconditionally.
This commit also consolidated a second hostent-to-gaih_addrtuple
conversion loop (in gaih_inet) to use the new conversion function.
commit 4ab2ab03d4351914ee53248dc5aef4a8c88ff8b9
Author: Florian Weimer <fweimer@redhat.com>
Date: Fri Apr 29 10:35:34 2016 +0200
CVE-2016-3706: getaddrinfo: stack overflow in hostent conversion [BZ #20010]
When converting a struct hostent response to struct gaih_addrtuple, the
gethosts macro (which is called from gaih_inet) used alloca, without
malloc fallback for large responses. This commit changes this code to
use calloc unconditionally.
This commit also consolidated a second hostent-to-gaih_addrtuple
conversion loop (in gaih_inet) to use the new conversion function.
diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c
index 1ef3f20..fed2d3b 100644
--- a/sysdeps/posix/getaddrinfo.c
+++ b/sysdeps/posix/getaddrinfo.c
@@ -168,9 +168,58 @@ gaih_inet_serv (const char *servicename, const struct gaih_typeproto *tp,
return 0;
}
+/* Convert struct hostent to a list of struct gaih_addrtuple objects.
+ h_name is not copied, and the struct hostent object must not be
+ deallocated prematurely. *RESULT must be NULL or a pointer to an
+ object allocated using malloc, which is freed. */
+static bool
+convert_hostent_to_gaih_addrtuple (const struct addrinfo *req,
+ int family,
+ struct hostent *h,
+ struct gaih_addrtuple **result)
+{
+ free (*result);
+ *result = NULL;
+
+ /* Count the number of addresses in h->h_addr_list. */
+ size_t count = 0;
+ for (char **p = h->h_addr_list; *p != NULL; ++p)
+ ++count;
+
+ /* Report no data if no addresses are available, or if the incoming
+ address size is larger than what we can store. */
+ if (count == 0 || h->h_length > sizeof (((struct gaih_addrtuple) {}).addr))
+ return true;
+
+ struct gaih_addrtuple *array = calloc (count, sizeof (*array));
+ if (array == NULL)
+ return false;
+
+ for (size_t i = 0; i < count; ++i)
+ {
+ if (family == AF_INET && req->ai_family == AF_INET6)
+ {
+ /* Perform address mapping. */
+ array[i].family = AF_INET6;
+ memcpy(array[i].addr + 3, h->h_addr_list[i], sizeof (uint32_t));
+ array[i].addr[2] = htonl (0xffff);
+ }
+ else
+ {
+ array[i].family = family;
+ memcpy (array[i].addr, h->h_addr_list[i], h->h_length);
+ }
+ array[i].next = array + i + 1;
+ }
+ array[0].name = h->h_name;
+ array[count - 1].next = NULL;
+
+ *result = array;
+ return true;
+}
+
#define gethosts(_family, _type) \
{ \
- int i; \
int herrno; \
struct hostent th; \
struct hostent *h; \
@@ -219,36 +268,23 @@ gaih_inet_serv (const char *servicename, const struct gaih_typeproto *tp,
} \
else if (h != NULL) \
{ \
- for (i = 0; h->h_addr_list[i]; i++) \
+ /* Make sure that addrmem can be freed. */ \
+ if (!malloc_addrmem) \
+ addrmem = NULL; \
+ if (!convert_hostent_to_gaih_addrtuple (req, _family,h, &addrmem)) \
{ \
- if (*pat == NULL) \
- { \
- *pat = __alloca (sizeof (struct gaih_addrtuple)); \
- (*pat)->scopeid = 0; \
- } \
- uint32_t *addr = (*pat)->addr; \
- (*pat)->next = NULL; \
- (*pat)->name = i == 0 ? strdupa (h->h_name) : NULL; \
- if (_family == AF_INET && req->ai_family == AF_INET6) \
- { \
- (*pat)->family = AF_INET6; \
- addr[3] = *(uint32_t *) h->h_addr_list[i]; \
- addr[2] = htonl (0xffff); \
- addr[1] = 0; \
- addr[0] = 0; \
- } \
- else \
- { \
- (*pat)->family = _family; \
- memcpy (addr, h->h_addr_list[i], sizeof(_type)); \
- } \
- pat = &((*pat)->next); \
+ _res.options |= old_res_options & RES_USE_INET6; \
+ result = -EAI_SYSTEM; \
+ goto free_and_return; \
} \
+ *pat = addrmem; \
+ /* The conversion uses malloc unconditionally. */ \
+ malloc_addrmem = true; \
\
if (localcanon != NULL && canon == NULL) \
canon = strdupa (localcanon); \
\
- if (_family == AF_INET6 && i > 0) \
+ if (_family == AF_INET6 && *pat != NULL) \
got_ipv6 = true; \
} \
}
@@ -612,44 +648,16 @@ gaih_inet (const char *name, const struct gaih_service *service,
{
if (h != NULL)
{
- int i;
- /* We found data, count the number of addresses. */
- for (i = 0; h->h_addr_list[i]; ++i)
- ;
- if (i > 0 && *pat != NULL)
- --i;
-
- if (__libc_use_alloca (alloca_used
- + i * sizeof (struct gaih_addrtuple)))
- addrmem = alloca_account (i * sizeof (struct gaih_addrtuple),
- alloca_used);
- else
- {
- addrmem = malloc (i
- * sizeof (struct gaih_addrtuple));
- if (addrmem == NULL)
- {
- result = -EAI_MEMORY;
- goto free_and_return;
- }
- malloc_addrmem = true;
- }
-
- /* Now convert it into the list. */
- struct gaih_addrtuple *addrfree = addrmem;
- for (i = 0; h->h_addr_list[i]; ++i)
+ /* We found data, convert it. */
+ if (!convert_hostent_to_gaih_addrtuple
+ (req, AF_INET, h, &addrmem))
{
- if (*pat == NULL)
- {
- *pat = addrfree++;
- (*pat)->scopeid = 0;
- }
- (*pat)->next = NULL;
- (*pat)->family = AF_INET;
- memcpy ((*pat)->addr, h->h_addr_list[i],
- h->h_length);
- pat = &((*pat)->next);
+ result = -EAI_MEMORY;
+ goto free_and_return;
}
+ *pat = addrmem;
+ /* The conversion uses malloc unconditionally. */
+ malloc_addrmem = true;
}
}
else

19
glibc-rh1332912.patch Normal file
View File

@ -0,0 +1,19 @@
commit 8a03ccbb77f52ec4b55062eeedddb8daec1a33e4
Author: Florian Weimer <fweimer@redhat.com>
Date: Mon May 2 16:04:32 2016 +0200
hesiod: Avoid heap overflow in get_txt_records [BZ #20031]
Index: b/hesiod/hesiod.c
===================================================================
--- a/hesiod/hesiod.c
+++ b/hesiod/hesiod.c
@@ -421,7 +421,7 @@ get_txt_records(struct hesiod_p *ctx, in
cp += INT16SZ + INT32SZ; /* skip the ttl, too */
rr.dlen = ns_get16(cp);
cp += INT16SZ;
- if (cp + rr.dlen > eom) {
+ if (rr.dlen == 0 || cp + rr.dlen > eom) {
__set_errno(EMSGSIZE);
goto cleanup;
}

24
glibc-rh1332914-1.patch Normal file
View File

@ -0,0 +1,24 @@
commit d29fb41f4431ca35ea360498ef9d37558ce90d76
Author: Florian Weimer <fweimer@redhat.com>
Date: Mon Apr 11 10:55:43 2016 +0200
nss_dns: Fix assertion failure in _nss_dns_getcanonname_r [BZ #19865]
diff --git a/resolv/nss_dns/dns-canon.c b/resolv/nss_dns/dns-canon.c
index 27255fd..fd73f19 100644
--- a/resolv/nss_dns/dns-canon.c
+++ b/resolv/nss_dns/dns-canon.c
@@ -144,6 +144,13 @@ _nss_dns_getcanonname_r (const char *name, char *buffer, size_t buflen,
ptr += sizeof (uint16_t) + __ns_get16 (ptr);
}
}
+
+ /* Restore original buffer before retry. */
+ if (ansp.ptr != buf)
+ {
+ free (ansp.ptr);
+ ansp.ptr = buf;
+ }
}
out:

78
glibc-rh1332914-2.patch Normal file
View File

@ -0,0 +1,78 @@
commit f749498fa53df9ead81e291cd9378d67483c2452
Author: Florian Weimer <fweimer@redhat.com>
Date: Wed Apr 27 15:11:41 2016 +0200
nss_dns: Validate RDATA length against packet length [BZ #19830]
In _nss_dns_getcanonname_r, a check for the availability of RR metadata
was missing as well.
diff --git a/resolv/nss_dns/dns-canon.c b/resolv/nss_dns/dns-canon.c
index fd73f19..072104f 100644
--- a/resolv/nss_dns/dns-canon.c
+++ b/resolv/nss_dns/dns-canon.c
@@ -103,6 +103,11 @@ _nss_dns_getcanonname_r (const char *name, char *buffer, size_t buflen,
ptr += s;
+ /* Check that there are enough bytes for the RR
+ metadata. */
+ if (endptr - ptr < 10)
+ goto unavail;
+
/* Check whether type and class match. */
uint_fast16_t type;
NS_GET16 (type, ptr);
@@ -137,11 +142,16 @@ _nss_dns_getcanonname_r (const char *name, char *buffer, size_t buflen,
if (__ns_get16 (ptr) != ns_c_in)
goto unavail;
- /* Also skip over the TTL. */
+ /* Also skip over class and TTL. */
ptr += sizeof (uint16_t) + sizeof (uint32_t);
- /* Skip over the data length and data. */
- ptr += sizeof (uint16_t) + __ns_get16 (ptr);
+ /* Skip over RDATA length and RDATA itself. */
+ uint16_t rdatalen = __ns_get16 (ptr);
+ ptr += sizeof (uint16_t);
+ /* Not enough room for RDATA. */
+ if (endptr - ptr < rdatalen)
+ goto unavail;
+ ptr += rdatalen;
}
}
diff --git a/resolv/nss_dns/dns-host.c b/resolv/nss_dns/dns-host.c
index 8599f4c..4bb0e62 100644
--- a/resolv/nss_dns/dns-host.c
+++ b/resolv/nss_dns/dns-host.c
@@ -751,6 +751,14 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype,
cp += INT32SZ; /* TTL */
n = __ns_get16 (cp);
cp += INT16SZ; /* len */
+
+ if (end_of_message - cp < n)
+ {
+ /* RDATA extends beyond the end of the packet. */
+ ++had_error;
+ continue;
+ }
+
if (__glibc_unlikely (class != C_IN))
{
/* XXX - debug? syslog? */
@@ -1077,6 +1085,13 @@ gaih_getanswer_slice (const querybuf *answer, int anslen, const char *qname,
n = __ns_get16 (cp);
cp += INT16SZ; /* len */
+ if (end_of_message - cp < n)
+ {
+ /* RDATA extends beyond the end of the packet. */
+ ++had_error;
+ continue;
+ }
+
if (class != C_IN)
{
cp += n;

148
glibc-rh1332914-3.patch Normal file
View File

@ -0,0 +1,148 @@
commit b9b026c9c00db1a1b5b4a3caa28162655a04a882
Author: Florian Weimer <fweimer@redhat.com>
Date: Wed Apr 27 16:12:32 2016 +0200
resolv, nss_dns: Remove remaining syslog logging [BZ #19862]
The fix for bug 14841 only removed part of the logging.
Index: b/resolv/gethnamaddr.c
===================================================================
--- a/resolv/gethnamaddr.c
+++ b/resolv/gethnamaddr.c
@@ -70,7 +70,6 @@ static char sccsid[] = "@(#)gethostnamad
#include <resolv.h>
#include <ctype.h>
#include <errno.h>
-#include <syslog.h>
#define RESOLVSORT
@@ -100,9 +99,6 @@ static char sccsid[] = "@(#)gethostnamad
#define MAXALIASES 35
#define MAXADDRS 35
-static const char AskedForGot[] =
- "gethostby*.getanswer: asked for \"%s\", got \"%s\"";
-
static char *h_addr_ptrs[MAXADDRS + 1];
static struct hostent host;
@@ -337,20 +333,12 @@ getanswer (const querybuf *answer, int a
* uses many different types in responses that do not
* match QTYPE.
*/
- if ((_res.options & RES_USE_DNSSEC) == 0) {
- syslog(LOG_NOTICE|LOG_AUTH,
- "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"",
- qname, p_class(C_IN), p_type(qtype),
- p_type(type));
- }
cp += n;
continue; /* XXX - had_error++ ? */
}
switch (type) {
case T_PTR:
if (strcasecmp(tname, bp) != 0) {
- syslog(LOG_NOTICE|LOG_AUTH,
- AskedForGot, qname, bp);
cp += n;
continue; /* XXX - had_error++ ? */
}
@@ -399,8 +387,6 @@ getanswer (const querybuf *answer, int a
case T_A:
case T_AAAA:
if (strcasecmp(host.h_name, bp) != 0) {
- syslog(LOG_NOTICE|LOG_AUTH,
- AskedForGot, host.h_name, bp);
cp += n;
continue; /* XXX - had_error++ ? */
}
@@ -748,9 +734,6 @@ gethostbyaddr(addr, len, af)
_res.options &= ~RES_DNSRCH;
_res.options |= RES_DEFNAMES;
if (!(rhp = gethostbyname(hname2))) {
- syslog(LOG_NOTICE|LOG_AUTH,
- "gethostbyaddr: No A record for %s (verifying [%s])",
- hname2, inet_ntoa(*((struct in_addr *)addr)));
_res.options = old_options;
__set_h_errno (HOST_NOT_FOUND);
return (NULL);
@@ -760,9 +743,6 @@ gethostbyaddr(addr, len, af)
if (!memcmp(*haddr, addr, INADDRSZ))
break;
if (!*haddr) {
- syslog(LOG_NOTICE|LOG_AUTH,
- "gethostbyaddr: A record of %s != PTR record [%s]",
- hname2, inet_ntoa(*((struct in_addr *)addr)));
__set_h_errno (HOST_NOT_FOUND);
return (NULL);
}
Index: b/resolv/nss_dns/dns-host.c
===================================================================
--- a/resolv/nss_dns/dns-host.c
+++ b/resolv/nss_dns/dns-host.c
@@ -78,7 +78,6 @@
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
-#include <sys/syslog.h>
#include "nsswitch.h"
@@ -99,10 +98,6 @@
#endif
#define MAXHOSTNAMELEN 256
-static const char AskedForGot[] = "\
-gethostby*.getanswer: asked for \"%s\", got \"%s\"";
-
-
/* We need this time later. */
typedef union querybuf
{
@@ -838,14 +833,6 @@ getanswer_r (const querybuf *answer, int
have_to_map = 1;
else if (__glibc_unlikely (type != qtype))
{
- /* Log a low priority message if we get an unexpected record, but
- skip it if we are using DNSSEC since it uses many different types
- in responses that do not match QTYPE. */
- if ((_res.options & RES_USE_DNSSEC) == 0)
- syslog (LOG_NOTICE | LOG_AUTH,
- "gethostby*.getanswer: asked for \"%s %s %s\", "
- "got type \"%s\"",
- qname, p_class (C_IN), p_type (qtype), p_type (type));
cp += n;
continue; /* XXX - had_error++ ? */
}
@@ -855,7 +842,6 @@ getanswer_r (const querybuf *answer, int
case T_PTR:
if (__glibc_unlikely (strcasecmp (tname, bp) != 0))
{
- syslog (LOG_NOTICE | LOG_AUTH, AskedForGot, qname, bp);
cp += n;
continue; /* XXX - had_error++ ? */
}
@@ -899,7 +885,6 @@ getanswer_r (const querybuf *answer, int
case T_AAAA:
if (__builtin_expect (strcasecmp (result->h_name, bp), 0) != 0)
{
- syslog (LOG_NOTICE | LOG_AUTH, AskedForGot, result->h_name, bp);
cp += n;
continue; /* XXX - had_error++ ? */
}
@@ -1152,13 +1137,6 @@ gaih_getanswer_slice (const querybuf *an
|| __builtin_expect (type == T_DNAME, 0))
#endif
{
- /* We don't support DNSSEC yet. For now, ignore the record
- and send a low priority message to syslog.
-
- We also don't expect T_PTR or T_DNAME messages. */
- syslog (LOG_DEBUG | LOG_AUTH,
- "getaddrinfo*.gaih_getanswer: got type \"%s\"",
- p_type (type));
cp += n;
continue;
}

109
glibc-rh1332914-4.patch Normal file
View File

@ -0,0 +1,109 @@
commit 5e0c421cc07e2d06945b863ed3bb92395472705d
Author: Florian Weimer <fweimer@redhat.com>
Date: Wed Apr 27 16:39:12 2016 +0200
nss_dns: Check address length before creating addrinfo result [BZ #19831]
Previously, we allocated room in the result space before the check,
leaving uninitialized data there in case the check failed.
This also consolidates the behavior between single (A or AAAA) and
dual (A and AAAA in parallel) queries. Single queries checked
the record length against the QTYPE, not the RRTYPE.
diff --git a/resolv/nss_dns/dns-host.c b/resolv/nss_dns/dns-host.c
index fb1d21c..403a005 100644
--- a/resolv/nss_dns/dns-host.c
+++ b/resolv/nss_dns/dns-host.c
@@ -134,6 +134,22 @@ extern enum nss_status _nss_dns_gethostbyname3_r (const char *name, int af,
char **canonp);
hidden_proto (_nss_dns_gethostbyname3_r)
+/* Return the expected RDATA length for an address record type (A or
+ AAAA). */
+static int
+rrtype_to_rdata_length (int type)
+{
+ switch (type)
+ {
+ case T_A:
+ return INADDRSZ;
+ case T_AAAA:
+ return IN6ADDRSZ;
+ default:
+ return -1;
+ }
+}
+
enum nss_status
_nss_dns_gethostbyname3_r (const char *name, int af, struct hostent *result,
char *buffer, size_t buflen, int *errnop,
@@ -888,6 +904,15 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype,
cp += n;
continue; /* XXX - had_error++ ? */
}
+
+ /* Stop parsing at a record whose length is incorrect. */
+ if (n != rrtype_to_rdata_length (type))
+ {
+ ++had_error;
+ break;
+ }
+
+ /* Skip records of the wrong type. */
if (n != result->h_length)
{
cp += n;
@@ -1124,25 +1149,25 @@ gaih_getanswer_slice (const querybuf *answer, int anslen, const char *qname,
}
continue;
}
-#if 1
- // We should not see any types other than those explicitly listed
- // below. Some types sent by server seem missing, though. Just
- // collect the data for now.
- if (__glibc_unlikely (type != T_A && type != T_AAAA))
-#else
- if (__builtin_expect (type == T_SIG, 0)
- || __builtin_expect (type == T_KEY, 0)
- || __builtin_expect (type == T_NXT, 0)
- || __builtin_expect (type == T_PTR, 0)
- || __builtin_expect (type == T_DNAME, 0))
-#endif
+
+ /* Stop parsing if we encounter a record with incorrect RDATA
+ length. */
+ if (type == T_A || type == T_AAAA)
+ {
+ if (n != rrtype_to_rdata_length (type))
+ {
+ ++had_error;
+ continue;
+ }
+ }
+ else
{
+ /* Skip unknown records. */
cp += n;
continue;
}
- if (type != T_A && type != T_AAAA)
- abort ();
+ assert (type == T_A || type == T_AAAA);
if (*pat == NULL)
{
uintptr_t pad = (-(uintptr_t) buffer
@@ -1176,12 +1201,6 @@ gaih_getanswer_slice (const querybuf *answer, int anslen, const char *qname,
}
(*pat)->family = type == T_A ? AF_INET : AF_INET6;
- if (__builtin_expect ((type == T_A && n != INADDRSZ)
- || (type == T_AAAA && n != IN6ADDRSZ), 0))
- {
- ++had_error;
- continue;
- }
memcpy ((*pat)->addr, cp, n);
cp += n;
(*pat)->scopeid = 0;

57
glibc-rh1332914-5.patch Normal file
View File

@ -0,0 +1,57 @@
commit a12f9431b3808e78b9ed397e4fce7de69410d94d
Author: Florian Weimer <fweimer@redhat.com>
Date: Wed Apr 27 17:15:57 2016 +0200
nss_dns: Skip over non-PTR records in the netent code [BZ #19868]
This requires additional checks for the RDATA length and the
availability of record metadata.
Index: b/resolv/nss_dns/dns-network.c
===================================================================
--- a/resolv/nss_dns/dns-network.c
+++ b/resolv/nss_dns/dns-network.c
@@ -345,10 +345,23 @@ getanswer_r (const querybuf *answer, int
if (n < 0 || res_dnok (bp) == 0)
break;
cp += n;
+
+ if (end_of_message - cp < 10)
+ {
+ __set_h_errno (NO_RECOVERY);
+ return NSS_STATUS_UNAVAIL;
+ }
+
GETSHORT (type, cp);
GETSHORT (class, cp);
cp += INT32SZ; /* TTL */
- GETSHORT (n, cp);
+ uint16_t rdatalen;
+ GETSHORT (rdatalen, cp);
+ if (end_of_message - cp < rdatalen)
+ {
+ __set_h_errno (NO_RECOVERY);
+ return NSS_STATUS_UNAVAIL;
+ }
if (class == C_IN && type == T_PTR)
{
@@ -370,7 +383,7 @@ getanswer_r (const querybuf *answer, int
cp += n;
return NSS_STATUS_UNAVAIL;
}
- cp += n;
+ cp += rdatalen;
if (alias_pointer + 2 < &net_data->aliases[MAX_NR_ALIASES])
{
*alias_pointer++ = bp;
@@ -381,6 +394,9 @@ getanswer_r (const querybuf *answer, int
++have_answer;
}
}
+ else
+ /* Skip over unknown record data. */
+ cp += rdatalen;
}
if (have_answer)

82
glibc-rh1332917-1.patch Normal file
View File

@ -0,0 +1,82 @@
commit 59eda029a8a35e5f4e5cd7be0f84c6629e48ec6e
Author: Florian Weimer <fweimer@redhat.com>
Date: Fri Feb 19 17:07:45 2016 +0100
malloc: Remove NO_THREADS
No functional change. It was not possible to build without
threading support before.
Index: b/malloc/arena.c
===================================================================
--- a/malloc/arena.c
+++ b/malloc/arena.c
@@ -135,8 +135,6 @@ int __malloc_initialized = -1;
/**************************************************************************/
-#ifndef NO_THREADS
-
/* atfork support. */
static void *(*save_malloc_hook)(size_t __size, const void *);
@@ -341,7 +339,6 @@ ptmalloc_unlock_all2 (void)
# define ptmalloc_unlock_all2 ptmalloc_unlock_all
# endif
-#endif /* !NO_THREADS */
/* Initialization routine. */
#include <string.h>
Index: b/malloc/malloc.c
===================================================================
--- a/malloc/malloc.c
+++ b/malloc/malloc.c
@@ -1074,10 +1074,8 @@ static void* realloc_check(void* oldme
const void *caller);
static void* memalign_check(size_t alignment, size_t bytes,
const void *caller);
-#ifndef NO_THREADS
static void* malloc_atfork(size_t sz, const void *caller);
static void free_atfork(void* mem, const void *caller);
-#endif
/* ------------------ MMAP support ------------------ */
Index: b/sysdeps/generic/malloc-machine.h
===================================================================
--- a/sysdeps/generic/malloc-machine.h
+++ b/sysdeps/generic/malloc-machine.h
@@ -22,30 +22,9 @@
#include <atomic.h>
-#ifndef mutex_init /* No threads, provide dummy macros */
+#ifndef mutex_init
-# define NO_THREADS
-
-/* The mutex functions used to do absolutely nothing, i.e. lock,
- trylock and unlock would always just return 0. However, even
- without any concurrently active threads, a mutex can be used
- legitimately as an `in use' flag. To make the code that is
- protected by a mutex async-signal safe, these macros would have to
- be based on atomic test-and-set operations, for example. */
-typedef int mutex_t;
-
-# define mutex_init(m) (*(m) = 0)
-# define mutex_lock(m) ({ *(m) = 1; 0; })
-# define mutex_trylock(m) (*(m) ? 1 : ((*(m) = 1), 0))
-# define mutex_unlock(m) (*(m) = 0)
-# define MUTEX_INITIALIZER (0)
-
-typedef void *tsd_key_t;
-# define tsd_key_create(key, destr) do {} while(0)
-# define tsd_setspecific(key, data) ((key) = (data))
-# define tsd_getspecific(key, vptr) (vptr = (key))
-
-# define thread_atfork(prepare, parent, child) do {} while(0)
+#error NO_THREADS no longer supported
#endif /* !defined mutex_init */

554
glibc-rh1332917-2.patch Normal file
View File

@ -0,0 +1,554 @@
commit 29d794863cd6e03115d3670707cc873a9965ba92
Author: Florian Weimer <fweimer@redhat.com>
Date: Thu Apr 14 09:17:02 2016 +0200
malloc: Run fork handler as late as possible [BZ #19431]
Previously, a thread M invoking fork would acquire locks in this order:
(M1) malloc arena locks (in the registered fork handler)
(M2) libio list lock
A thread F invoking flush (NULL) would acquire locks in this order:
(F1) libio list lock
(F2) individual _IO_FILE locks
A thread G running getdelim would use this order:
(G1) _IO_FILE lock
(G2) malloc arena lock
After executing (M1), (F1), (G1), none of the threads can make progress.
This commit changes the fork lock order to:
(M'1) libio list lock
(M'2) malloc arena locks
It explicitly encodes the lock order in the implementations of fork,
and does not rely on the registration order, thus avoiding the deadlock.
Index: b/malloc/arena.c
===================================================================
--- a/malloc/arena.c
+++ b/malloc/arena.c
@@ -141,10 +141,6 @@ static void *(*save_malloc_hook)(size_t
static void (*save_free_hook) (void *__ptr, const void *);
static void *save_arena;
-# ifdef ATFORK_MEM
-ATFORK_MEM;
-# endif
-
/* Magic value for the thread-specific arena pointer when
malloc_atfork() is in use. */
@@ -214,14 +210,14 @@ free_atfork (void *mem, const void *call
/* Counter for number of times the list is locked by the same thread. */
static unsigned int atfork_recursive_cntr;
-/* The following two functions are registered via thread_atfork() to
- make sure that the mutexes remain in a consistent state in the
- fork()ed version of a thread. Also adapt the malloc and free hooks
- temporarily, because the `atfork' handler mechanism may use
- malloc/free internally (e.g. in LinuxThreads). */
+/* The following three functions are called around fork from a
+ multi-threaded process. We do not use the general fork handler
+ mechanism to make sure that our handlers are the last ones being
+ called, so that other fork handlers can use the malloc
+ subsystem. */
-static void
-ptmalloc_lock_all (void)
+void
+__malloc_fork_lock_parent (void)
{
mstate ar_ptr;
@@ -229,7 +225,7 @@ ptmalloc_lock_all (void)
return;
/* We do not acquire free_list_lock here because we completely
- reconstruct free_list in ptmalloc_unlock_all2. */
+ reconstruct free_list in __malloc_fork_unlock_child. */
if (mutex_trylock (&list_lock))
{
@@ -256,7 +252,7 @@ ptmalloc_lock_all (void)
__free_hook = free_atfork;
/* Only the current thread may perform malloc/free calls now.
save_arena will be reattached to the current thread, in
- ptmalloc_lock_all, so save_arena->attached_threads is not
+ __malloc_fork_lock_parent, so save_arena->attached_threads is not
updated. */
tsd_getspecific (arena_key, save_arena);
tsd_setspecific (arena_key, ATFORK_ARENA_PTR);
@@ -264,8 +260,8 @@ out:
++atfork_recursive_cntr;
}
-static void
-ptmalloc_unlock_all (void)
+void
+__malloc_fork_unlock_parent (void)
{
mstate ar_ptr;
@@ -276,8 +272,8 @@ ptmalloc_unlock_all (void)
return;
/* Replace ATFORK_ARENA_PTR with save_arena.
- save_arena->attached_threads was not changed in ptmalloc_lock_all
- and is still correct. */
+ save_arena->attached_threads was not changed in
+ __malloc_fork_lock_parent and is still correct. */
tsd_setspecific (arena_key, save_arena);
__malloc_hook = save_malloc_hook;
__free_hook = save_free_hook;
@@ -291,15 +287,8 @@ ptmalloc_unlock_all (void)
(void) mutex_unlock (&list_lock);
}
-# ifdef __linux__
-
-/* In NPTL, unlocking a mutex in the child process after a
- fork() is currently unsafe, whereas re-initializing it is safe and
- does not leak resources. Therefore, a special atfork handler is
- installed for the child. */
-
-static void
-ptmalloc_unlock_all2 (void)
+void
+__malloc_fork_unlock_child (void)
{
mstate ar_ptr;
@@ -335,11 +324,6 @@ ptmalloc_unlock_all2 (void)
atfork_recursive_cntr = 0;
}
-# else
-
-# define ptmalloc_unlock_all2 ptmalloc_unlock_all
-# endif
-
/* Initialization routine. */
#include <string.h>
extern char **_environ;
@@ -409,7 +393,6 @@ ptmalloc_init (void)
tsd_key_create (&arena_key, NULL);
tsd_setspecific (arena_key, (void *) &main_arena);
- thread_atfork (ptmalloc_lock_all, ptmalloc_unlock_all, ptmalloc_unlock_all2);
const char *s = NULL;
if (__glibc_likely (_environ != NULL))
{
@@ -484,14 +467,6 @@ ptmalloc_init (void)
__malloc_initialized = 1;
}
-/* There are platforms (e.g. Hurd) with a link-time hook mechanism. */
-#ifdef thread_atfork_static
-thread_atfork_static (ptmalloc_lock_all, ptmalloc_unlock_all, \
- ptmalloc_unlock_all2)
-#endif
-
-
-
/* Managing heaps and arenas (for concurrent threads) */
#if MALLOC_DEBUG > 1
@@ -838,7 +813,8 @@ _int_new_arena (size_t size)
limit is reached). At this point, some arena has to be attached
to two threads. We could acquire the arena lock before list_lock
to make it less likely that reused_arena picks this new arena,
- but this could result in a deadlock with ptmalloc_lock_all. */
+ but this could result in a deadlock with
+ __malloc_fork_lock_parent. */
(void) mutex_lock (&a->mutex);
Index: b/malloc/malloc-internal.h
===================================================================
--- /dev/null
+++ b/malloc/malloc-internal.h
@@ -0,0 +1,32 @@
+/* Internal declarations for malloc, for use within libc.
+ Copyright (C) 2016 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; see the file COPYING.LIB. If
+ not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef _MALLOC_PRIVATE_H
+#define _MALLOC_PRIVATE_H
+
+/* Called in the parent process before a fork. */
+void __malloc_fork_lock_parent (void) internal_function attribute_hidden;
+
+/* Called in the parent process after a fork. */
+void __malloc_fork_unlock_parent (void) internal_function attribute_hidden;
+
+/* Called in the child process after a fork. */
+void __malloc_fork_unlock_child (void) internal_function attribute_hidden;
+
+
+#endif /* _MALLOC_PRIVATE_H */
Index: b/malloc/malloc.c
===================================================================
--- a/malloc/malloc.c
+++ b/malloc/malloc.c
@@ -244,6 +244,7 @@
/* For ALIGN_UP. */
#include <libc-internal.h>
+#include <malloc/malloc-internal.h>
/*
Debugging:
Index: b/malloc/tst-malloc-fork-deadlock.c
===================================================================
--- /dev/null
+++ b/malloc/tst-malloc-fork-deadlock.c
@@ -0,0 +1,220 @@
+/* Test concurrent fork, getline, and fflush (NULL).
+ Copyright (C) 2016 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; see the file COPYING.LIB. If
+ not, see <http://www.gnu.org/licenses/>. */
+
+#include <sys/wait.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdio.h>
+#include <pthread.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <malloc.h>
+#include <time.h>
+#include <string.h>
+#include <signal.h>
+
+static int do_test (void);
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
+
+enum {
+ /* Number of threads which call fork. */
+ fork_thread_count = 4,
+ /* Number of threads which call getline (and, indirectly,
+ malloc). */
+ read_thread_count = 8,
+};
+
+static bool termination_requested;
+
+static void *
+fork_thread_function (void *closure)
+{
+ while (!__atomic_load_n (&termination_requested, __ATOMIC_RELAXED))
+ {
+ pid_t pid = fork ();
+ if (pid < 0)
+ {
+ printf ("error: fork: %m\n");
+ abort ();
+ }
+ else if (pid == 0)
+ _exit (17);
+
+ int status;
+ if (waitpid (pid, &status, 0) < 0)
+ {
+ printf ("error: waitpid: %m\n");
+ abort ();
+ }
+ if (!WIFEXITED (status) || WEXITSTATUS (status) != 17)
+ {
+ printf ("error: waitpid returned invalid status: %d\n", status);
+ abort ();
+ }
+ }
+ return NULL;
+}
+
+static char *file_to_read;
+
+static void *
+read_thread_function (void *closure)
+{
+ FILE *f = fopen (file_to_read, "r");
+ if (f == NULL)
+ {
+ printf ("error: fopen (%s): %m\n", file_to_read);
+ abort ();
+ }
+
+ while (!__atomic_load_n (&termination_requested, __ATOMIC_RELAXED))
+ {
+ rewind (f);
+ char *line = NULL;
+ size_t line_allocated = 0;
+ ssize_t ret = getline (&line, &line_allocated, f);
+ if (ret < 0)
+ {
+ printf ("error: getline: %m\n");
+ abort ();
+ }
+ free (line);
+ }
+ fclose (f);
+
+ return NULL;
+}
+
+static void *
+flushall_thread_function (void *closure)
+{
+ while (!__atomic_load_n (&termination_requested, __ATOMIC_RELAXED))
+ if (fflush (NULL) != 0)
+ {
+ printf ("error: fflush (NULL): %m\n");
+ abort ();
+ }
+ return NULL;
+}
+
+static void
+create_threads (pthread_t *threads, size_t count, void *(*func) (void *))
+{
+ for (size_t i = 0; i < count; ++i)
+ {
+ int ret = pthread_create (threads + i, NULL, func, NULL);
+ if (ret != 0)
+ {
+ errno = ret;
+ printf ("error: pthread_create: %m\n");
+ abort ();
+ }
+ }
+}
+
+static void
+join_threads (pthread_t *threads, size_t count)
+{
+ for (size_t i = 0; i < count; ++i)
+ {
+ int ret = pthread_join (threads[i], NULL);
+ if (ret != 0)
+ {
+ errno = ret;
+ printf ("error: pthread_join: %m\n");
+ abort ();
+ }
+ }
+}
+
+/* Create a file which consists of a single long line, and assigns
+ file_to_read. The hope is that this triggers an allocation in
+ getline which needs a lock. */
+static void
+create_file_with_large_line (void)
+{
+ int fd = create_temp_file ("bug19431-large-line", &file_to_read);
+ if (fd < 0)
+ {
+ printf ("error: create_temp_file: %m\n");
+ abort ();
+ }
+ FILE *f = fdopen (fd, "w+");
+ if (f == NULL)
+ {
+ printf ("error: fdopen: %m\n");
+ abort ();
+ }
+ for (int i = 0; i < 50000; ++i)
+ fputc ('x', f);
+ fputc ('\n', f);
+ if (ferror (f))
+ {
+ printf ("error: fputc: %m\n");
+ abort ();
+ }
+ if (fclose (f) != 0)
+ {
+ printf ("error: fclose: %m\n");
+ abort ();
+ }
+}
+
+static int
+do_test (void)
+{
+ /* Make sure that we do not exceed the arena limit with the number
+ of threads we configured. */
+ if (mallopt (M_ARENA_MAX, 400) == 0)
+ {
+ printf ("error: mallopt (M_ARENA_MAX) failed\n");
+ return 1;
+ }
+
+ /* Leave some room for shutting down all threads gracefully. */
+ int timeout = 3;
+ if (timeout > TIMEOUT)
+ timeout = TIMEOUT - 1;
+
+ create_file_with_large_line ();
+
+ pthread_t fork_threads[fork_thread_count];
+ create_threads (fork_threads, fork_thread_count, fork_thread_function);
+ pthread_t read_threads[read_thread_count];
+ create_threads (read_threads, read_thread_count, read_thread_function);
+ pthread_t flushall_threads[1];
+ create_threads (flushall_threads, 1, flushall_thread_function);
+
+ struct timespec ts = {timeout, 0};
+ if (nanosleep (&ts, NULL))
+ {
+ printf ("error: error: nanosleep: %m\n");
+ abort ();
+ }
+
+ __atomic_store_n (&termination_requested, true, __ATOMIC_RELAXED);
+
+ join_threads (flushall_threads, 1);
+ join_threads (read_threads, read_thread_count);
+ join_threads (fork_threads, fork_thread_count);
+
+ free (file_to_read);
+
+ return 0;
+}
Index: b/manual/memory.texi
===================================================================
--- a/manual/memory.texi
+++ b/manual/memory.texi
@@ -1055,14 +1055,6 @@ systems that do not support @w{ISO C11}.
@c _dl_addr_inside_object ok
@c determine_info ok
@c __rtld_lock_unlock_recursive (dl_load_lock) @aculock
-@c thread_atfork @asulock @aculock @acsfd @acsmem
-@c __register_atfork @asulock @aculock @acsfd @acsmem
-@c lll_lock (__fork_lock) @asulock @aculock
-@c fork_handler_alloc @asulock @aculock @acsfd @acsmem
-@c calloc dup @asulock @aculock @acsfd @acsmem
-@c __linkin_atfork ok
-@c catomic_compare_and_exchange_bool_acq ok
-@c lll_unlock (__fork_lock) @aculock
@c *_environ @mtsenv
@c next_env_entry ok
@c strcspn dup ok
Index: b/sysdeps/mach/hurd/fork.c
===================================================================
--- a/sysdeps/mach/hurd/fork.c
+++ b/sysdeps/mach/hurd/fork.c
@@ -26,6 +26,7 @@
#include <assert.h>
#include "hurdmalloc.h" /* XXX */
#include <tls.h>
+#include <malloc/malloc-internal.h>
#undef __fork
@@ -107,6 +108,12 @@ __fork (void)
/* Run things that prepare for forking before we create the task. */
RUN_HOOK (_hurd_fork_prepare_hook, ());
+ /* Acquire malloc locks. This needs to come last because fork
+ handlers may use malloc, and the libio list lock has an
+ indirect malloc dependency as well (via the getdelim
+ function). */
+ __malloc_fork_lock_parent ();
+
/* Lock things that want to be locked before we fork. */
{
void *const *p;
@@ -608,6 +615,9 @@ __fork (void)
nthreads * sizeof (*threads));
}
+ /* Release malloc locks. */
+ __malloc_fork_unlock_parent ();
+
/* Run things that want to run in the parent to restore it to
normality. Usually prepare hooks and parent hooks are
symmetrical: the prepare hook arrests state in some way for the
@@ -659,6 +669,9 @@ __fork (void)
/* Forking clears the trace flag. */
__sigemptyset (&_hurdsig_traced);
+ /* Release malloc locks. */
+ __malloc_fork_unlock_child ();
+
/* Run things that want to run in the child task to set up. */
RUN_HOOK (_hurd_fork_child_hook, ());
Index: b/sysdeps/nptl/fork.c
===================================================================
--- a/sysdeps/nptl/fork.c
+++ b/sysdeps/nptl/fork.c
@@ -31,7 +31,7 @@
#include <fork.h>
#include <arch-fork.h>
#include <futex-internal.h>
-
+#include <malloc/malloc-internal.h>
static void
fresetlockfiles (void)
@@ -111,6 +111,11 @@ __libc_fork (void)
_IO_list_lock ();
+ /* Acquire malloc locks. This needs to come last because fork
+ handlers may use malloc, and the libio list lock has an indirect
+ malloc dependency as well (via the getdelim function). */
+ __malloc_fork_lock_parent ();
+
#ifndef NDEBUG
pid_t ppid = THREAD_GETMEM (THREAD_SELF, tid);
#endif
@@ -168,6 +173,9 @@ __libc_fork (void)
# endif
#endif
+ /* Release malloc locks. */
+ __malloc_fork_unlock_child ();
+
/* Reset the file list. These are recursive mutexes. */
fresetlockfiles ();
@@ -209,6 +217,9 @@ __libc_fork (void)
/* Restore the PID value. */
THREAD_SETMEM (THREAD_SELF, pid, parentpid);
+ /* Release malloc locks, parent process variant. */
+ __malloc_fork_unlock_parent ();
+
/* We execute this even if the 'fork' call failed. */
_IO_list_unlock ();

218
glibc-rh1332917-3.patch Normal file
View File

@ -0,0 +1,218 @@
commit 8a727af925be63aa6ea0f5f90e16751fd541626b
Author: Florian Weimer <fweimer@redhat.com>
Date: Thu Apr 14 09:18:30 2016 +0200
malloc: Remove malloc hooks from fork handler
The fork handler now runs so late that there is no risk anymore that
other fork handlers in the same thread use malloc, so it is no
longer necessary to install malloc hooks which made a subset
of malloc functionality available to the thread that called fork.
Index: b/malloc/arena.c
===================================================================
--- a/malloc/arena.c
+++ b/malloc/arena.c
@@ -137,79 +137,6 @@ int __malloc_initialized = -1;
/* atfork support. */
-static void *(*save_malloc_hook)(size_t __size, const void *);
-static void (*save_free_hook) (void *__ptr, const void *);
-static void *save_arena;
-
-/* Magic value for the thread-specific arena pointer when
- malloc_atfork() is in use. */
-
-# define ATFORK_ARENA_PTR ((void *) -1)
-
-/* The following hooks are used while the `atfork' handling mechanism
- is active. */
-
-static void *
-malloc_atfork (size_t sz, const void *caller)
-{
- void *vptr = NULL;
- void *victim;
-
- tsd_getspecific (arena_key, vptr);
- if (vptr == ATFORK_ARENA_PTR)
- {
- /* We are the only thread that may allocate at all. */
- if (save_malloc_hook != malloc_check)
- {
- return _int_malloc (&main_arena, sz);
- }
- else
- {
- if (top_check () < 0)
- return 0;
-
- victim = _int_malloc (&main_arena, sz + 1);
- return mem2mem_check (victim, sz);
- }
- }
- else
- {
- /* Suspend the thread until the `atfork' handlers have completed.
- By that time, the hooks will have been reset as well, so that
- mALLOc() can be used again. */
- (void) mutex_lock (&list_lock);
- (void) mutex_unlock (&list_lock);
- return __libc_malloc (sz);
- }
-}
-
-static void
-free_atfork (void *mem, const void *caller)
-{
- void *vptr = NULL;
- mstate ar_ptr;
- mchunkptr p; /* chunk corresponding to mem */
-
- if (mem == 0) /* free(0) has no effect */
- return;
-
- p = mem2chunk (mem); /* do not bother to replicate free_check here */
-
- if (chunk_is_mmapped (p)) /* release mmapped memory. */
- {
- munmap_chunk (p);
- return;
- }
-
- ar_ptr = arena_for_chunk (p);
- tsd_getspecific (arena_key, vptr);
- _int_free (ar_ptr, p, vptr == ATFORK_ARENA_PTR);
-}
-
-
-/* Counter for number of times the list is locked by the same thread. */
-static unsigned int atfork_recursive_cntr;
-
/* The following three functions are called around fork from a
multi-threaded process. We do not use the general fork handler
mechanism to make sure that our handlers are the last ones being
@@ -219,65 +146,29 @@ static unsigned int atfork_recursive_cnt
void
__malloc_fork_lock_parent (void)
{
- mstate ar_ptr;
-
if (__malloc_initialized < 1)
return;
/* We do not acquire free_list_lock here because we completely
reconstruct free_list in __malloc_fork_unlock_child. */
- if (mutex_trylock (&list_lock))
- {
- void *my_arena;
- tsd_getspecific (arena_key, my_arena);
- if (my_arena == ATFORK_ARENA_PTR)
- /* This is the same thread which already locks the global list.
- Just bump the counter. */
- goto out;
-
- /* This thread has to wait its turn. */
- (void) mutex_lock (&list_lock);
- }
- for (ar_ptr = &main_arena;; )
+ (void) mutex_lock (&list_lock);
+ for (mstate ar_ptr = &main_arena;; )
{
(void) mutex_lock (&ar_ptr->mutex);
ar_ptr = ar_ptr->next;
if (ar_ptr == &main_arena)
break;
}
- save_malloc_hook = __malloc_hook;
- save_free_hook = __free_hook;
- __malloc_hook = malloc_atfork;
- __free_hook = free_atfork;
- /* Only the current thread may perform malloc/free calls now.
- save_arena will be reattached to the current thread, in
- __malloc_fork_lock_parent, so save_arena->attached_threads is not
- updated. */
- tsd_getspecific (arena_key, save_arena);
- tsd_setspecific (arena_key, ATFORK_ARENA_PTR);
-out:
- ++atfork_recursive_cntr;
}
void
__malloc_fork_unlock_parent (void)
{
- mstate ar_ptr;
-
if (__malloc_initialized < 1)
return;
- if (--atfork_recursive_cntr != 0)
- return;
-
- /* Replace ATFORK_ARENA_PTR with save_arena.
- save_arena->attached_threads was not changed in
- __malloc_fork_lock_parent and is still correct. */
- tsd_setspecific (arena_key, save_arena);
- __malloc_hook = save_malloc_hook;
- __free_hook = save_free_hook;
- for (ar_ptr = &main_arena;; )
+ for (mstate ar_ptr = &main_arena;; )
{
(void) mutex_unlock (&ar_ptr->mutex);
ar_ptr = ar_ptr->next;
@@ -290,25 +181,22 @@ __malloc_fork_unlock_parent (void)
void
__malloc_fork_unlock_child (void)
{
- mstate ar_ptr;
-
if (__malloc_initialized < 1)
return;
- tsd_setspecific (arena_key, save_arena);
- __malloc_hook = save_malloc_hook;
- __free_hook = save_free_hook;
+ void *vptr = NULL;
+ mstate current_arena = tsd_getspecific (arena_key, vptr);
- /* Push all arenas to the free list, except save_arena, which is
+ /* Push all arenas to the free list, except current_arena, which is
attached to the current thread. */
mutex_init (&free_list_lock);
- if (save_arena != NULL)
- ((mstate) save_arena)->attached_threads = 1;
+ if (current_arena != NULL)
+ current_arena->attached_threads = 1;
free_list = NULL;
- for (ar_ptr = &main_arena;; )
+ for (mstate ar_ptr = &main_arena;; )
{
mutex_init (&ar_ptr->mutex);
- if (ar_ptr != save_arena)
+ if (ar_ptr != current_arena)
{
/* This arena is no longer attached to any thread. */
ar_ptr->attached_threads = 0;
@@ -321,7 +209,6 @@ __malloc_fork_unlock_child (void)
}
mutex_init (&list_lock);
- atfork_recursive_cntr = 0;
}
/* Initialization routine. */
Index: b/malloc/malloc.c
===================================================================
--- a/malloc/malloc.c
+++ b/malloc/malloc.c
@@ -1075,8 +1075,6 @@ static void* realloc_check(void* oldme
const void *caller);
static void* memalign_check(size_t alignment, size_t bytes,
const void *caller);
-static void* malloc_atfork(size_t sz, const void *caller);
-static void free_atfork(void* mem, const void *caller);
/* ------------------ MMAP support ------------------ */

36
glibc-rh1332917-4.patch Normal file
View File

@ -0,0 +1,36 @@
commit 186fe877f3df0b84d57dfbf0386f6332c6aa69bc
Author: Florian Weimer <fweimer@redhat.com>
Date: Thu Apr 14 12:53:03 2016 +0200
malloc: Add missing internal_function attributes on function definitions
Fixes build on i386 after commit 29d794863cd6e03115d3670707cc873a9965ba92.
Index: b/malloc/arena.c
===================================================================
--- a/malloc/arena.c
+++ b/malloc/arena.c
@@ -144,6 +144,7 @@ int __malloc_initialized = -1;
subsystem. */
void
+internal_function
__malloc_fork_lock_parent (void)
{
if (__malloc_initialized < 1)
@@ -163,6 +164,7 @@ __malloc_fork_lock_parent (void)
}
void
+internal_function
__malloc_fork_unlock_parent (void)
{
if (__malloc_initialized < 1)
@@ -179,6 +181,7 @@ __malloc_fork_unlock_parent (void)
}
void
+internal_function
__malloc_fork_unlock_child (void)
{
if (__malloc_initialized < 1)

27
glibc-rh1332917-5.patch Normal file
View File

@ -0,0 +1,27 @@
commit 66355680f840f336eb83e7f46a873556a1bdedcc
Author: Florian Weimer <fweimer@redhat.com>
Date: Wed May 4 15:25:39 2016 +0200
malloc: Adjust header file guard in malloc-internal.h
diff --git a/malloc/malloc-internal.h b/malloc/malloc-internal.h
index b830d3f..98afd14 100644
--- a/malloc/malloc-internal.h
+++ b/malloc/malloc-internal.h
@@ -16,8 +16,8 @@
License along with the GNU C Library; see the file COPYING.LIB. If
not, see <http://www.gnu.org/licenses/>. */
-#ifndef _MALLOC_PRIVATE_H
-#define _MALLOC_PRIVATE_H
+#ifndef _MALLOC_INTERNAL_H
+#define _MALLOC_INTERNAL_H
/* Called in the parent process before a fork. */
void __malloc_fork_lock_parent (void) internal_function attribute_hidden;
@@ -29,4 +29,4 @@ void __malloc_fork_unlock_parent (void) internal_function attribute_hidden;
void __malloc_fork_unlock_child (void) internal_function attribute_hidden;
-#endif /* _MALLOC_PRIVATE_H */
+#endif /* _MALLOC_INTERNAL_H */

54
glibc-rh1333901-1.patch Normal file
View File

@ -0,0 +1,54 @@
commit 2b54cbce2c363ab6ae89d10657d7465858116d7a
Author: Florian Weimer <fweimer@redhat.com>
Date: Thu Apr 28 17:41:49 2016 +0200
getnameinfo: Do not preserve errno
POSIX does not require it, the companion getaddrinfo implementation
does not do it, and this behavior is not documented in the manual
page, either.
diff --git a/inet/getnameinfo.c b/inet/getnameinfo.c
index 40f67f0..9b1847b 100644
--- a/inet/getnameinfo.c
+++ b/inet/getnameinfo.c
@@ -175,7 +175,6 @@ getnameinfo (const struct sockaddr *sa, socklen_t addrlen, char *host,
socklen_t hostlen, char *serv, socklen_t servlen,
int flags)
{
- int serrno = errno;
int herrno;
struct hostent th;
int ok = 0;
@@ -326,10 +325,7 @@ getnameinfo (const struct sockaddr *sa, socklen_t addrlen, char *host,
if (!ok)
{
if (flags & NI_NAMEREQD)
- {
- __set_errno (serrno);
- return EAI_NONAME;
- }
+ return EAI_NONAME;
else
{
const char *c;
@@ -406,10 +402,7 @@ getnameinfo (const struct sockaddr *sa, socklen_t addrlen, char *host,
};
if (flags & NI_NAMEREQD)
- {
- __set_errno (serrno);
- return EAI_NONAME;
- }
+ return EAI_NONAME;
strncpy (host, "localhost", hostlen);
break;
@@ -463,7 +456,6 @@ getnameinfo (const struct sockaddr *sa, socklen_t addrlen, char *host,
host[hostlen-1] = 0;
if (serv && (servlen > 0))
serv[servlen-1] = 0;
- errno = serrno;
return 0;
}
libc_hidden_def (getnameinfo)

634
glibc-rh1333901-2.patch Normal file
View File

@ -0,0 +1,634 @@
commit 2dce81a319601e1ee110f7316f705b48c5686e72
Author: Florian Weimer <fweimer@redhat.com>
Date: Fri Apr 29 17:08:06 2016 +0200
getnameinfo: Refactor and fix memory leak [BZ #19642]
Split getnameinfo into separate functions for host and service
lookups, and for different address families.
diff --git a/inet/getnameinfo.c b/inet/getnameinfo.c
index 9b1847b..ce05dda 100644
--- a/inet/getnameinfo.c
+++ b/inet/getnameinfo.c
@@ -1,3 +1,21 @@
+/* Convert socket address to string using Name Service Switch modules.
+ Copyright (C) 1997-2016 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
+ <http://www.gnu.org/licenses/>. */
+
/* The Inner Net License, Version 2.00
The author(s) grant permission for redistribution and use in source and
@@ -169,19 +187,323 @@ nrl_domainname (void)
return domain;
};
+/* Convert host name, AF_INET/AF_INET6 case, name only. */
+static int
+gni_host_inet_name (struct scratch_buffer *tmpbuf,
+ const struct sockaddr *sa, socklen_t addrlen,
+ char *host, socklen_t hostlen, int flags)
+{
+ int herrno;
+ struct hostent th;
+ struct hostent *h = NULL;
+ if (sa->sa_family == AF_INET6)
+ {
+ while (__gethostbyaddr_r ((const void *) &(((const struct sockaddr_in6 *) sa)->sin6_addr),
+ sizeof(struct in6_addr),
+ AF_INET6, &th,
+ tmpbuf->data, tmpbuf->length,
+ &h, &herrno))
+ if (herrno == NETDB_INTERNAL && errno == ERANGE)
+ {
+ if (!scratch_buffer_grow (tmpbuf))
+ {
+ __set_h_errno (herrno);
+ return EAI_MEMORY;
+ }
+ }
+ else
+ break;
+ }
+ else
+ {
+ while (__gethostbyaddr_r ((const void *) &(((const struct sockaddr_in *)sa)->sin_addr),
+ sizeof(struct in_addr),
+ AF_INET, &th,
+ tmpbuf->data, tmpbuf->length,
+ &h, &herrno))
+ if (herrno == NETDB_INTERNAL && errno == ERANGE)
+ {
+ if (!scratch_buffer_grow (tmpbuf))
+ {
+ __set_h_errno (herrno);
+ return EAI_MEMORY;
+ }
+ }
+ else
+ break;
+ }
+
+ if (h == NULL)
+ {
+ if (herrno == NETDB_INTERNAL)
+ {
+ __set_h_errno (herrno);
+ return EAI_SYSTEM;
+ }
+ if (herrno == TRY_AGAIN)
+ {
+ __set_h_errno (herrno);
+ return EAI_AGAIN;
+ }
+ }
+
+ if (h)
+ {
+ char *c;
+ if ((flags & NI_NOFQDN)
+ && (c = nrl_domainname ())
+ && (c = strstr (h->h_name, c))
+ && (c != h->h_name) && (*(--c) == '.'))
+ /* Terminate the string after the prefix. */
+ *c = '\0';
+
+#ifdef HAVE_LIBIDN
+ /* If requested, convert from the IDN format. */
+ if (flags & NI_IDN)
+ {
+ int idn_flags = 0;
+ if (flags & NI_IDN_ALLOW_UNASSIGNED)
+ idn_flags |= IDNA_ALLOW_UNASSIGNED;
+ if (flags & NI_IDN_USE_STD3_ASCII_RULES)
+ idn_flags |= IDNA_USE_STD3_ASCII_RULES;
+
+ char *out;
+ int rc = __idna_to_unicode_lzlz (h->h_name, &out,
+ idn_flags);
+ if (rc != IDNA_SUCCESS)
+ {
+ if (rc == IDNA_MALLOC_ERROR)
+ return EAI_MEMORY;
+ if (rc == IDNA_DLOPEN_ERROR)
+ return EAI_SYSTEM;
+ return EAI_IDN_ENCODE;
+ }
+
+ if (out != h->h_name)
+ {
+ h->h_name = strdupa (out);
+ free (out);
+ }
+ }
+#endif
+
+ size_t len = strlen (h->h_name) + 1;
+ if (len > hostlen)
+ return EAI_OVERFLOW;
+
+ memcpy (host, h->h_name, len);
+
+ return 0;
+ }
+
+ return EAI_NONAME;
+}
+
+/* Convert host name, AF_INET/AF_INET6 case, numeric conversion. */
+static int
+gni_host_inet_numeric (struct scratch_buffer *tmpbuf,
+ const struct sockaddr *sa, socklen_t addrlen,
+ char *host, socklen_t hostlen, int flags)
+{
+ const char *c;
+ if (sa->sa_family == AF_INET6)
+ {
+ const struct sockaddr_in6 *sin6p;
+ uint32_t scopeid;
+
+ sin6p = (const struct sockaddr_in6 *) sa;
+
+ c = inet_ntop (AF_INET6,
+ (const void *) &sin6p->sin6_addr, host, hostlen);
+ scopeid = sin6p->sin6_scope_id;
+ if (scopeid != 0)
+ {
+ /* Buffer is >= IFNAMSIZ+1. */
+ char scopebuf[IFNAMSIZ + 1];
+ char *scopeptr;
+ int ni_numericscope = 0;
+ size_t real_hostlen = __strnlen (host, hostlen);
+ size_t scopelen = 0;
+
+ scopebuf[0] = SCOPE_DELIMITER;
+ scopebuf[1] = '\0';
+ scopeptr = &scopebuf[1];
+
+ if (IN6_IS_ADDR_LINKLOCAL (&sin6p->sin6_addr)
+ || IN6_IS_ADDR_MC_LINKLOCAL (&sin6p->sin6_addr))
+ {
+ if (if_indextoname (scopeid, scopeptr) == NULL)
+ ++ni_numericscope;
+ else
+ scopelen = strlen (scopebuf);
+ }
+ else
+ ++ni_numericscope;
+
+ if (ni_numericscope)
+ scopelen = 1 + __snprintf (scopeptr,
+ (scopebuf
+ + sizeof scopebuf
+ - scopeptr),
+ "%u", scopeid);
+
+ if (real_hostlen + scopelen + 1 > hostlen)
+ /* Signal the buffer is too small. This is
+ what inet_ntop does. */
+ c = NULL;
+ else
+ memcpy (host + real_hostlen, scopebuf, scopelen + 1);
+ }
+ }
+ else
+ c = inet_ntop (AF_INET,
+ (const void *) &(((const struct sockaddr_in *) sa)->sin_addr),
+ host, hostlen);
+ if (c == NULL)
+ return EAI_OVERFLOW;
+ return 0;
+}
+
+static int
+gni_host_inet (struct scratch_buffer *tmpbuf,
+ const struct sockaddr *sa, socklen_t addrlen,
+ char *host, socklen_t hostlen, int flags)
+{
+ if (!(flags & NI_NUMERICHOST))
+ {
+ int result = gni_host_inet_name
+ (tmpbuf, sa, addrlen, host, hostlen, flags);
+ if (result != EAI_NONAME)
+ return result;
+ }
+
+ if (flags & NI_NAMEREQD)
+ return EAI_NONAME;
+ else
+ return gni_host_inet_numeric
+ (tmpbuf, sa, addrlen, host, hostlen, flags);
+}
+
+static int
+gni_host_local (struct scratch_buffer *tmpbuf,
+ const struct sockaddr *sa, socklen_t addrlen,
+ char *host, socklen_t hostlen, int flags)
+{
+
+ if (!(flags & NI_NUMERICHOST))
+ {
+ struct utsname utsname;
+
+ if (!uname (&utsname))
+ {
+ strncpy (host, utsname.nodename, hostlen);
+ return 0;
+ }
+ }
+
+ if (flags & NI_NAMEREQD)
+ return EAI_NONAME;
+
+ strncpy (host, "localhost", hostlen);
+ return 0;
+}
+
+static int
+gni_host (struct scratch_buffer *tmpbuf,
+ const struct sockaddr *sa, socklen_t addrlen,
+ char *host, socklen_t hostlen, int flags)
+{
+ switch (sa->sa_family)
+ {
+ case AF_INET:
+ case AF_INET6:
+ return gni_host_inet (tmpbuf, sa, addrlen, host, hostlen, flags);
+
+ case AF_LOCAL:
+ return gni_host_local (tmpbuf, sa, addrlen, host, hostlen, flags);
+
+ default:
+ return EAI_FAMILY;
+ }
+}
+
+/* Convert service to string, AF_INET and AF_INET6 variant. */
+static int
+gni_serv_inet (struct scratch_buffer *tmpbuf,
+ const struct sockaddr *sa, socklen_t addrlen,
+ char *serv, socklen_t servlen, int flags)
+{
+ _Static_assert
+ (offsetof (struct sockaddr_in, sin_port)
+ == offsetof (struct sockaddr_in6, sin6_port)
+ && sizeof (((struct sockaddr_in) {}).sin_port) == sizeof (in_port_t)
+ && sizeof (((struct sockaddr_in6) {}).sin6_port) == sizeof (in_port_t),
+ "AF_INET and AF_INET6 port consistency");
+ if (!(flags & NI_NUMERICSERV))
+ {
+ struct servent *s, ts;
+ int e;
+ while ((e = __getservbyport_r (((const struct sockaddr_in *) sa)->sin_port,
+ ((flags & NI_DGRAM)
+ ? "udp" : "tcp"), &ts,
+ tmpbuf->data, tmpbuf->length, &s)))
+ {
+ if (e == ERANGE)
+ {
+ if (!scratch_buffer_grow (tmpbuf))
+ return EAI_MEMORY;
+ }
+ else
+ break;
+ }
+ if (s)
+ {
+ strncpy (serv, s->s_name, servlen);
+ return 0;
+ }
+ /* Fall through to numeric conversion. */
+ }
+ if (__snprintf (serv, servlen, "%d",
+ ntohs (((const struct sockaddr_in *) sa)->sin_port))
+ + 1 > servlen)
+ return EAI_OVERFLOW;
+ return 0;
+}
+
+/* Convert service to string, AF_LOCAL variant. */
+static int
+gni_serv_local (struct scratch_buffer *tmpbuf,
+ const struct sockaddr *sa, socklen_t addrlen,
+ char *serv, socklen_t servlen, int flags)
+{
+ strncpy (serv, ((const struct sockaddr_un *) sa)->sun_path, servlen);
+ return 0;
+}
+
+/* Convert service to string, dispatching to the implementations
+ above. */
+static int
+gni_serv (struct scratch_buffer *tmpbuf,
+ const struct sockaddr *sa, socklen_t addrlen,
+ char *serv, socklen_t servlen, int flags)
+{
+ switch (sa->sa_family)
+ {
+ case AF_INET:
+ case AF_INET6:
+ return gni_serv_inet (tmpbuf, sa, addrlen, serv, servlen, flags);
+ case AF_LOCAL:
+ return gni_serv_local (tmpbuf, sa, addrlen, serv, servlen, flags);
+ default:
+ return EAI_FAMILY;
+ }
+}
int
getnameinfo (const struct sockaddr *sa, socklen_t addrlen, char *host,
socklen_t hostlen, char *serv, socklen_t servlen,
int flags)
{
- int herrno;
- struct hostent th;
- int ok = 0;
- struct scratch_buffer tmpbuf;
-
- scratch_buffer_init (&tmpbuf);
-
if (flags & ~(NI_NUMERICHOST|NI_NUMERICSERV|NI_NOFQDN|NI_NAMEREQD|NI_DGRAM
#ifdef HAVE_LIBIDN
|NI_IDN|NI_IDN_ALLOW_UNASSIGNED|NI_IDN_USE_STD3_ASCII_RULES
@@ -213,249 +535,34 @@ getnameinfo (const struct sockaddr *sa, socklen_t addrlen, char *host,
return EAI_FAMILY;
}
- if (host != NULL && hostlen > 0)
- switch (sa->sa_family)
- {
- case AF_INET:
- case AF_INET6:
- if (!(flags & NI_NUMERICHOST))
- {
- struct hostent *h = NULL;
- if (sa->sa_family == AF_INET6)
- {
- while (__gethostbyaddr_r ((const void *) &(((const struct sockaddr_in6 *) sa)->sin6_addr),
- sizeof(struct in6_addr),
- AF_INET6, &th,
- tmpbuf.data, tmpbuf.length,
- &h, &herrno))
- if (herrno == NETDB_INTERNAL && errno == ERANGE)
- {
- if (!scratch_buffer_grow (&tmpbuf))
- {
- __set_h_errno (herrno);
- return EAI_MEMORY;
- }
- }
- else
- break;
- }
- else
- {
- while (__gethostbyaddr_r ((const void *) &(((const struct sockaddr_in *)sa)->sin_addr),
- sizeof(struct in_addr),
- AF_INET, &th,
- tmpbuf.data, tmpbuf.length,
- &h, &herrno))
- if (herrno == NETDB_INTERNAL && errno == ERANGE)
- {
- if (!scratch_buffer_grow (&tmpbuf))
- {
- __set_h_errno (herrno);
- return EAI_MEMORY;
- }
- }
- else
- break;
- }
-
- if (h == NULL)
- {
- if (herrno == NETDB_INTERNAL)
- {
- __set_h_errno (herrno);
- return EAI_SYSTEM;
- }
- if (herrno == TRY_AGAIN)
- {
- __set_h_errno (herrno);
- return EAI_AGAIN;
- }
- }
-
- if (h)
- {
- char *c;
- if ((flags & NI_NOFQDN)
- && (c = nrl_domainname ())
- && (c = strstr (h->h_name, c))
- && (c != h->h_name) && (*(--c) == '.'))
- /* Terminate the string after the prefix. */
- *c = '\0';
-
-#ifdef HAVE_LIBIDN
- /* If requested, convert from the IDN format. */
- if (flags & NI_IDN)
- {
- int idn_flags = 0;
- if (flags & NI_IDN_ALLOW_UNASSIGNED)
- idn_flags |= IDNA_ALLOW_UNASSIGNED;
- if (flags & NI_IDN_USE_STD3_ASCII_RULES)
- idn_flags |= IDNA_USE_STD3_ASCII_RULES;
-
- char *out;
- int rc = __idna_to_unicode_lzlz (h->h_name, &out,
- idn_flags);
- if (rc != IDNA_SUCCESS)
- {
- if (rc == IDNA_MALLOC_ERROR)
- return EAI_MEMORY;
- if (rc == IDNA_DLOPEN_ERROR)
- return EAI_SYSTEM;
- return EAI_IDN_ENCODE;
- }
-
- if (out != h->h_name)
- {
- h->h_name = strdupa (out);
- free (out);
- }
- }
-#endif
-
- size_t len = strlen (h->h_name) + 1;
- if (len > hostlen)
- return EAI_OVERFLOW;
-
- memcpy (host, h->h_name, len);
-
- ok = 1;
- }
- }
-
- if (!ok)
- {
- if (flags & NI_NAMEREQD)
- return EAI_NONAME;
- else
- {
- const char *c;
- if (sa->sa_family == AF_INET6)
- {
- const struct sockaddr_in6 *sin6p;
- uint32_t scopeid;
-
- sin6p = (const struct sockaddr_in6 *) sa;
-
- c = inet_ntop (AF_INET6,
- (const void *) &sin6p->sin6_addr, host, hostlen);
- scopeid = sin6p->sin6_scope_id;
- if (scopeid != 0)
- {
- /* Buffer is >= IFNAMSIZ+1. */
- char scopebuf[IFNAMSIZ + 1];
- char *scopeptr;
- int ni_numericscope = 0;
- size_t real_hostlen = __strnlen (host, hostlen);
- size_t scopelen = 0;
-
- scopebuf[0] = SCOPE_DELIMITER;
- scopebuf[1] = '\0';
- scopeptr = &scopebuf[1];
-
- if (IN6_IS_ADDR_LINKLOCAL (&sin6p->sin6_addr)
- || IN6_IS_ADDR_MC_LINKLOCAL (&sin6p->sin6_addr))
- {
- if (if_indextoname (scopeid, scopeptr) == NULL)
- ++ni_numericscope;
- else
- scopelen = strlen (scopebuf);
- }
- else
- ++ni_numericscope;
-
- if (ni_numericscope)
- scopelen = 1 + __snprintf (scopeptr,
- (scopebuf
- + sizeof scopebuf
- - scopeptr),
- "%u", scopeid);
-
- if (real_hostlen + scopelen + 1 > hostlen)
- /* Signal the buffer is too small. This is
- what inet_ntop does. */
- c = NULL;
- else
- memcpy (host + real_hostlen, scopebuf, scopelen + 1);
- }
- }
- else
- c = inet_ntop (AF_INET,
- (const void *) &(((const struct sockaddr_in *) sa)->sin_addr),
- host, hostlen);
- if (c == NULL)
- return EAI_OVERFLOW;
- }
- ok = 1;
- }
- break;
-
- case AF_LOCAL:
- if (!(flags & NI_NUMERICHOST))
- {
- struct utsname utsname;
-
- if (!uname (&utsname))
- {
- strncpy (host, utsname.nodename, hostlen);
- break;
- };
- };
-
- if (flags & NI_NAMEREQD)
- return EAI_NONAME;
-
- strncpy (host, "localhost", hostlen);
- break;
+ struct scratch_buffer tmpbuf;
+ scratch_buffer_init (&tmpbuf);
- default:
- return EAI_FAMILY;
+ if (host != NULL && hostlen > 0)
+ {
+ int result = gni_host (&tmpbuf, sa, addrlen, host, hostlen, flags);
+ if (result != 0)
+ {
+ scratch_buffer_free (&tmpbuf);
+ return result;
+ }
}
if (serv && (servlen > 0))
- switch (sa->sa_family)
- {
- case AF_INET:
- case AF_INET6:
- if (!(flags & NI_NUMERICSERV))
- {
- struct servent *s, ts;
- int e;
- while ((e = __getservbyport_r (((const struct sockaddr_in *) sa)->sin_port,
- ((flags & NI_DGRAM)
- ? "udp" : "tcp"), &ts,
- tmpbuf.data, tmpbuf.length, &s)))
- {
- if (e == ERANGE)
- {
- if (!scratch_buffer_grow (&tmpbuf))
- return EAI_MEMORY;
- }
- else
- break;
- }
- if (s)
- {
- strncpy (serv, s->s_name, servlen);
- break;
- }
- }
-
- if (__snprintf (serv, servlen, "%d",
- ntohs (((const struct sockaddr_in *) sa)->sin_port))
- + 1 > servlen)
- return EAI_OVERFLOW;
-
- break;
-
- case AF_LOCAL:
- strncpy (serv, ((const struct sockaddr_un *) sa)->sun_path, servlen);
- break;
+ {
+ int result = gni_serv (&tmpbuf, sa, addrlen, serv, servlen, flags);
+ if (result != 0)
+ {
+ scratch_buffer_free (&tmpbuf);
+ return result;
+ }
}
if (host && (hostlen > 0))
host[hostlen-1] = 0;
if (serv && (servlen > 0))
serv[servlen-1] = 0;
+ scratch_buffer_free (&tmpbuf);
return 0;
}
libc_hidden_def (getnameinfo)

116
glibc-rh1333901-3.patch Normal file
View File

@ -0,0 +1,116 @@
commit c9b0e6a432e827b61f12eb52c2aaeadc77b64461
Author: Florian Weimer <fweimer@redhat.com>
Date: Wed May 4 14:35:12 2016 +0200
getnameinfo: Reduce line length and add missing comments
diff --git a/inet/getnameinfo.c b/inet/getnameinfo.c
index ce05dda..c649c49 100644
--- a/inet/getnameinfo.c
+++ b/inet/getnameinfo.c
@@ -198,10 +198,9 @@ gni_host_inet_name (struct scratch_buffer *tmpbuf,
struct hostent *h = NULL;
if (sa->sa_family == AF_INET6)
{
- while (__gethostbyaddr_r ((const void *) &(((const struct sockaddr_in6 *) sa)->sin6_addr),
- sizeof(struct in6_addr),
- AF_INET6, &th,
- tmpbuf->data, tmpbuf->length,
+ const struct sockaddr_in6 *sin6p = (const struct sockaddr_in6 *) sa;
+ while (__gethostbyaddr_r (&sin6p->sin6_addr, sizeof(struct in6_addr),
+ AF_INET6, &th, tmpbuf->data, tmpbuf->length,
&h, &herrno))
if (herrno == NETDB_INTERNAL && errno == ERANGE)
{
@@ -216,10 +215,9 @@ gni_host_inet_name (struct scratch_buffer *tmpbuf,
}
else
{
- while (__gethostbyaddr_r ((const void *) &(((const struct sockaddr_in *)sa)->sin_addr),
- sizeof(struct in_addr),
- AF_INET, &th,
- tmpbuf->data, tmpbuf->length,
+ const struct sockaddr_in *sinp = (const struct sockaddr_in *) sa;
+ while (__gethostbyaddr_r (&sinp->sin_addr, sizeof(struct in_addr),
+ AF_INET, &th, tmpbuf->data, tmpbuf->length,
&h, &herrno))
if (herrno == NETDB_INTERNAL && errno == ERANGE)
{
@@ -308,14 +306,10 @@ gni_host_inet_numeric (struct scratch_buffer *tmpbuf,
const char *c;
if (sa->sa_family == AF_INET6)
{
- const struct sockaddr_in6 *sin6p;
- uint32_t scopeid;
-
- sin6p = (const struct sockaddr_in6 *) sa;
-
+ const struct sockaddr_in6 *sin6p = (const struct sockaddr_in6 *) sa;
c = inet_ntop (AF_INET6,
(const void *) &sin6p->sin6_addr, host, hostlen);
- scopeid = sin6p->sin6_scope_id;
+ uint32_t scopeid = sin6p->sin6_scope_id;
if (scopeid != 0)
{
/* Buffer is >= IFNAMSIZ+1. */
@@ -356,14 +350,16 @@ gni_host_inet_numeric (struct scratch_buffer *tmpbuf,
}
}
else
- c = inet_ntop (AF_INET,
- (const void *) &(((const struct sockaddr_in *) sa)->sin_addr),
- host, hostlen);
+ {
+ const struct sockaddr_in *sinp = (const struct sockaddr_in *) sa;
+ c = inet_ntop (AF_INET, &sinp->sin_addr, host, hostlen);
+ }
if (c == NULL)
return EAI_OVERFLOW;
return 0;
}
+/* Convert AF_INET or AF_INET6 socket address, host part. */
static int
gni_host_inet (struct scratch_buffer *tmpbuf,
const struct sockaddr *sa, socklen_t addrlen,
@@ -384,6 +380,7 @@ gni_host_inet (struct scratch_buffer *tmpbuf,
(tmpbuf, sa, addrlen, host, hostlen, flags);
}
+/* Convert AF_LOCAL socket address, host part. */
static int
gni_host_local (struct scratch_buffer *tmpbuf,
const struct sockaddr *sa, socklen_t addrlen,
@@ -408,6 +405,7 @@ gni_host_local (struct scratch_buffer *tmpbuf,
return 0;
}
+/* Convert the host part of an AF_LOCAK socket address. */
static int
gni_host (struct scratch_buffer *tmpbuf,
const struct sockaddr *sa, socklen_t addrlen,
@@ -439,11 +437,12 @@ gni_serv_inet (struct scratch_buffer *tmpbuf,
&& sizeof (((struct sockaddr_in) {}).sin_port) == sizeof (in_port_t)
&& sizeof (((struct sockaddr_in6) {}).sin6_port) == sizeof (in_port_t),
"AF_INET and AF_INET6 port consistency");
+ const struct sockaddr_in *sinp = (const struct sockaddr_in *) sa;
if (!(flags & NI_NUMERICSERV))
{
struct servent *s, ts;
int e;
- while ((e = __getservbyport_r (((const struct sockaddr_in *) sa)->sin_port,
+ while ((e = __getservbyport_r (sinp->sin_port,
((flags & NI_DGRAM)
? "udp" : "tcp"), &ts,
tmpbuf->data, tmpbuf->length, &s)))
@@ -463,9 +462,7 @@ gni_serv_inet (struct scratch_buffer *tmpbuf,
}
/* Fall through to numeric conversion. */
}
- if (__snprintf (serv, servlen, "%d",
- ntohs (((const struct sockaddr_in *) sa)->sin_port))
- + 1 > servlen)
+ if (__snprintf (serv, servlen, "%d", ntohs (sinp->sin_port)) + 1 > servlen)
return EAI_OVERFLOW;
return 0;
}

52
glibc-rh1333901-4.patch Normal file
View File

@ -0,0 +1,52 @@
commit 1c3490d4b29fc5b3f30dd6b13082046aee94443d
Author: Florian Weimer <fweimer@redhat.com>
Date: Wed May 4 14:35:23 2016 +0200
getnameinfo: Avoid calling strnlen on uninitialized buffer
In the numeric AF_INET/AF_INET6 case, if inet_ntop fails
as the result of a short host buffer, we used to call strnlen
on the uninitialized host buffer.
diff --git a/inet/getnameinfo.c b/inet/getnameinfo.c
index c649c49..c8de163 100644
--- a/inet/getnameinfo.c
+++ b/inet/getnameinfo.c
@@ -303,12 +303,12 @@ gni_host_inet_numeric (struct scratch_buffer *tmpbuf,
const struct sockaddr *sa, socklen_t addrlen,
char *host, socklen_t hostlen, int flags)
{
- const char *c;
if (sa->sa_family == AF_INET6)
{
const struct sockaddr_in6 *sin6p = (const struct sockaddr_in6 *) sa;
- c = inet_ntop (AF_INET6,
- (const void *) &sin6p->sin6_addr, host, hostlen);
+ if (inet_ntop (AF_INET6, &sin6p->sin6_addr, host, hostlen) == NULL)
+ return EAI_OVERFLOW;
+
uint32_t scopeid = sin6p->sin6_scope_id;
if (scopeid != 0)
{
@@ -344,7 +344,7 @@ gni_host_inet_numeric (struct scratch_buffer *tmpbuf,
if (real_hostlen + scopelen + 1 > hostlen)
/* Signal the buffer is too small. This is
what inet_ntop does. */
- c = NULL;
+ return EAI_OVERFLOW;
else
memcpy (host + real_hostlen, scopebuf, scopelen + 1);
}
@@ -352,10 +352,9 @@ gni_host_inet_numeric (struct scratch_buffer *tmpbuf,
else
{
const struct sockaddr_in *sinp = (const struct sockaddr_in *) sa;
- c = inet_ntop (AF_INET, &sinp->sin_addr, host, hostlen);
+ if (inet_ntop (AF_INET, &sinp->sin_addr, host, hostlen) == NULL)
+ return EAI_OVERFLOW;
}
- if (c == NULL)
- return EAI_OVERFLOW;
return 0;
}

175
glibc-rh1333901-5.patch Normal file
View File

@ -0,0 +1,175 @@
commit 066746783d6c6c0f61b39c741177e24a9b398a20
Author: Florian Weimer <fweimer@redhat.com>
Date: Wed May 4 14:45:17 2016 +0200
getnameinfo: Return EAI_OVERFLOW in more cases [BZ #19787]
The AF_LOCAL and AF_INET/AF_INET6 non-numerci service conversion
did not return EAI_OVERFLOW if the supplied buffer was too small,
silently returning truncated data. In the AF_INET/AF_INET6
numeric cases, the snprintf return value checking was incorrect.
diff --git a/inet/getnameinfo.c b/inet/getnameinfo.c
index c8de163..283da55 100644
--- a/inet/getnameinfo.c
+++ b/inet/getnameinfo.c
@@ -187,6 +187,39 @@ nrl_domainname (void)
return domain;
};
+/* Copy a string to a destination buffer with length checking. Return
+ EAI_OVERFLOW if the buffer is not large enough, and 0 on
+ success. */
+static int
+checked_copy (char *dest, size_t destlen, const char *source)
+{
+ size_t source_length = strlen (source);
+ if (source_length + 1 > destlen)
+ return EAI_OVERFLOW;
+ memcpy (dest, source, source_length + 1);
+ return 0;
+}
+
+/* Helper function for CHECKED_SNPRINTF below. */
+static int
+check_sprintf_result (int result, size_t destlen)
+{
+ if (result < 0)
+ return EAI_SYSTEM;
+ if ((size_t) result >= destlen)
+ /* If ret == destlen, there was no room for the terminating NUL
+ character. */
+ return EAI_OVERFLOW;
+ return 0;
+}
+
+/* Format a string in the destination buffer. Return 0 on success,
+ EAI_OVERFLOW in case the buffer is too small, or EAI_SYSTEM on any
+ other error. */
+#define CHECKED_SNPRINTF(dest, destlen, format, ...) \
+ check_sprintf_result \
+ (__snprintf (dest, destlen, format, __VA_ARGS__), destlen)
+
/* Convert host name, AF_INET/AF_INET6 case, name only. */
static int
gni_host_inet_name (struct scratch_buffer *tmpbuf,
@@ -312,41 +345,22 @@ gni_host_inet_numeric (struct scratch_buffer *tmpbuf,
uint32_t scopeid = sin6p->sin6_scope_id;
if (scopeid != 0)
{
- /* Buffer is >= IFNAMSIZ+1. */
- char scopebuf[IFNAMSIZ + 1];
- char *scopeptr;
- int ni_numericscope = 0;
- size_t real_hostlen = __strnlen (host, hostlen);
- size_t scopelen = 0;
-
- scopebuf[0] = SCOPE_DELIMITER;
- scopebuf[1] = '\0';
- scopeptr = &scopebuf[1];
+ size_t used_hostlen = __strnlen (host, hostlen);
+ /* Location of the scope string in the host buffer. */
+ char *scope_start = host + used_hostlen;
+ size_t scope_length = hostlen - used_hostlen;
if (IN6_IS_ADDR_LINKLOCAL (&sin6p->sin6_addr)
|| IN6_IS_ADDR_MC_LINKLOCAL (&sin6p->sin6_addr))
{
- if (if_indextoname (scopeid, scopeptr) == NULL)
- ++ni_numericscope;
- else
- scopelen = strlen (scopebuf);
+ char scopebuf[IFNAMSIZ];
+ if (if_indextoname (scopeid, scopebuf) != NULL)
+ return CHECKED_SNPRINTF
+ (scope_start, scope_length,
+ "%c%s", SCOPE_DELIMITER, scopebuf);
}
- else
- ++ni_numericscope;
-
- if (ni_numericscope)
- scopelen = 1 + __snprintf (scopeptr,
- (scopebuf
- + sizeof scopebuf
- - scopeptr),
- "%u", scopeid);
-
- if (real_hostlen + scopelen + 1 > hostlen)
- /* Signal the buffer is too small. This is
- what inet_ntop does. */
- return EAI_OVERFLOW;
- else
- memcpy (host + real_hostlen, scopebuf, scopelen + 1);
+ return CHECKED_SNPRINTF
+ (scope_start, scope_length, "%c%u", SCOPE_DELIMITER, scopeid);
}
}
else
@@ -385,23 +399,17 @@ gni_host_local (struct scratch_buffer *tmpbuf,
const struct sockaddr *sa, socklen_t addrlen,
char *host, socklen_t hostlen, int flags)
{
-
if (!(flags & NI_NUMERICHOST))
{
struct utsname utsname;
-
- if (!uname (&utsname))
- {
- strncpy (host, utsname.nodename, hostlen);
- return 0;
- }
+ if (uname (&utsname) == 0)
+ return checked_copy (host, hostlen, utsname.nodename);
}
if (flags & NI_NAMEREQD)
return EAI_NONAME;
- strncpy (host, "localhost", hostlen);
- return 0;
+ return checked_copy (host, hostlen, "localhost");
}
/* Convert the host part of an AF_LOCAK socket address. */
@@ -455,15 +463,10 @@ gni_serv_inet (struct scratch_buffer *tmpbuf,
break;
}
if (s)
- {
- strncpy (serv, s->s_name, servlen);
- return 0;
- }
+ return checked_copy (serv, servlen, s->s_name);
/* Fall through to numeric conversion. */
}
- if (__snprintf (serv, servlen, "%d", ntohs (sinp->sin_port)) + 1 > servlen)
- return EAI_OVERFLOW;
- return 0;
+ return CHECKED_SNPRINTF (serv, servlen, "%d", ntohs (sinp->sin_port));
}
/* Convert service to string, AF_LOCAL variant. */
@@ -472,8 +475,8 @@ gni_serv_local (struct scratch_buffer *tmpbuf,
const struct sockaddr *sa, socklen_t addrlen,
char *serv, socklen_t servlen, int flags)
{
- strncpy (serv, ((const struct sockaddr_un *) sa)->sun_path, servlen);
- return 0;
+ return checked_copy
+ (serv, servlen, ((const struct sockaddr_un *) sa)->sun_path);
}
/* Convert service to string, dispatching to the implementations
@@ -554,10 +557,6 @@ getnameinfo (const struct sockaddr *sa, socklen_t addrlen, char *host,
}
}
- if (host && (hostlen > 0))
- host[hostlen-1] = 0;
- if (serv && (servlen > 0))
- serv[servlen-1] = 0;
scratch_buffer_free (&tmpbuf);
return 0;
}

33
glibc-rh1333940.patch Normal file
View File

@ -0,0 +1,33 @@
commit 3cc652e951c71785032019fec82e3b8543d85305
Author: Mike Frysinger <vapier@gentoo.org>
Date: Fri Sep 18 13:49:08 2015 -0400
timezone: fix parallel check failures
The XT testdata install rules expect the testdata dir to already exist in
the build tree, but it doesn't actually create it. Instead, it relies on
the build-testdata define happening to be executed before it (which runs
zic which creates the dir). When we run in parallel though, it's easy to
hit a failure:
$ cd timezone
$ rm -rf $objdir/timezone/testdata
$ make check -j
...
cp testdata/XT1 .../timezone/testdata/XT1
cp: cannot create regular file '.../timezone/testdata/XT1': No such file or directory
Makefile:116: recipe for target '.../timezone/testdata/XT1' failed
make: *** [.../timezone/testdata/XT1] Error 1
make: *** Waiting for unfinished jobs....
Index: b/timezone/Makefile
===================================================================
--- a/timezone/Makefile
+++ b/timezone/Makefile
@@ -123,6 +123,7 @@ $(testdata)/Asia/Tokyo: asia $(zic-deps)
$(build-testdata)
$(testdata)/XT%: testdata/XT%
+ $(make-target-directory)
cp $< $@
$(objpfx)tzselect: tzselect.ksh $(common-objpfx)config.make

48
glibc-rh1337140.patch Normal file
View File

@ -0,0 +1,48 @@
commit bc779a1a5b3035133024b21e2f339fe4219fb11c
Author: Florian Weimer <fweimer@redhat.com>
Date: Mon May 23 20:18:34 2016 +0200
CVE-2016-4429: sunrpc: Do not use alloca in clntudp_call [BZ #20112]
The call is technically in a loop, and under certain circumstances
(which are quite difficult to reproduce in a test case), alloca
can be invoked repeatedly during a single call to clntudp_call.
As a result, the available stack space can be exhausted (even
though individual alloca sizes are bounded implicitly by what
can fit into a UDP packet, as a side effect of the earlier
successful send operation).
Index: b/sunrpc/clnt_udp.c
===================================================================
--- a/sunrpc/clnt_udp.c
+++ b/sunrpc/clnt_udp.c
@@ -420,9 +420,15 @@ send_again:
struct sock_extended_err *e;
struct sockaddr_in err_addr;
struct iovec iov;
- char *cbuf = (char *) alloca (outlen + 256);
+ char *cbuf = malloc (outlen + 256);
int ret;
+ if (cbuf == NULL)
+ {
+ cu->cu_error.re_errno = errno;
+ return (cu->cu_error.re_status = RPC_CANTRECV);
+ }
+
iov.iov_base = cbuf + 256;
iov.iov_len = outlen;
msg.msg_name = (void *) &err_addr;
@@ -447,10 +453,12 @@ send_again:
cmsg = CMSG_NXTHDR (&msg, cmsg))
if (cmsg->cmsg_level == SOL_IP && cmsg->cmsg_type == IP_RECVERR)
{
+ free (cbuf);
e = (struct sock_extended_err *) CMSG_DATA(cmsg);
cu->cu_error.re_errno = e->ee_errno;
return (cu->cu_error.re_status = RPC_CANTRECV);
}
+ free (cbuf);
}
#endif
do

324
glibc-rh1337291.patch Normal file
View File

@ -0,0 +1,324 @@
commit f2225475118c8804b1b31731bdfb3f76eb179e6d
Author: Florian Weimer <fweimer@redhat.com>
Date: Mon May 23 19:43:09 2016 +0200
Make padding in struct sockaddr_storage explicit [BZ #20111]
This avoids aliasing issues with GCC 6 in -fno-strict-aliasing
mode. (With implicit padding, not all data is copied.)
This change makes it explicit that struct sockaddr_storage is
only 126 bytes large on m68k (unlike elsewhere, where we end up
with the requested 128 bytes). The new test case makes sure that
this does not happen on other architectures.
(cherry picked from commit 3375cfafa7961c6ae0e509c31c3b3cef9ad1f03d)
diff --git a/bits/sockaddr.h b/bits/sockaddr.h
index e91f837..0af58c9 100644
--- a/bits/sockaddr.h
+++ b/bits/sockaddr.h
@@ -36,4 +36,7 @@ typedef unsigned short int sa_family_t;
#define __SOCKADDR_COMMON_SIZE (sizeof (unsigned short int))
+/* Size of struct sockaddr_storage. */
+#define _SS_SIZE 128
+
#endif /* bits/sockaddr.h */
diff --git a/bits/socket.h b/bits/socket.h
index ab9f242..a22fd56 100644
--- a/bits/socket.h
+++ b/bits/socket.h
@@ -152,20 +152,20 @@ struct sockaddr
/* Structure large enough to hold any socket address (with the historical
- exception of AF_UNIX). We reserve 128 bytes. */
+ exception of AF_UNIX). */
#if ULONG_MAX > 0xffffffff
# define __ss_aligntype __uint64_t
#else
# define __ss_aligntype __uint32_t
#endif
-#define _SS_SIZE 128
-#define _SS_PADSIZE (_SS_SIZE - (2 * sizeof (__ss_aligntype)))
+#define _SS_PADSIZE \
+ (_SS_SIZE - __SOCKADDR_COMMON_SIZE - sizeof (__ss_aligntype))
struct sockaddr_storage
{
__SOCKADDR_COMMON (ss_); /* Address family, etc. */
- __ss_aligntype __ss_align; /* Force desired alignment. */
char __ss_padding[_SS_PADSIZE];
+ __ss_aligntype __ss_align; /* Force desired alignment. */
};
diff --git a/inet/Makefile b/inet/Makefile
index 0e7a3c3..2207b93 100644
--- a/inet/Makefile
+++ b/inet/Makefile
@@ -50,7 +50,7 @@ aux := check_pf check_native ifreq
tests := htontest test_ifindex tst-ntoa tst-ether_aton tst-network \
tst-gethnm test-ifaddrs bug-if1 test-inet6_opt tst-ether_line \
- tst-getni1 tst-getni2 tst-inet6_rth tst-checks
+ tst-getni1 tst-getni2 tst-inet6_rth tst-checks tst-sockaddr
include ../Rules
@@ -84,6 +84,8 @@ CFLAGS-either_hton.c = -fexceptions
CFLAGS-getnetgrent.c = -fexceptions
CFLAGS-getnetgrent_r.c = -fexceptions
+CFLAGS-tst-sockaddr.c = -fno-strict-aliasing
+
endif
ifeq ($(build-static-nss),yes)
diff --git a/inet/tst-sockaddr.c b/inet/tst-sockaddr.c
new file mode 100644
index 0000000..fe0307b
--- /dev/null
+++ b/inet/tst-sockaddr.c
@@ -0,0 +1,125 @@
+/* Tests for socket address type definitions.
+ Copyright (C) 2016 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; see the file COPYING.LIB. If
+ not, see <http://www.gnu.org/licenses/>. */
+
+#include <netinet/in.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+/* This is a copy of the previous definition of struct
+ sockaddr_storage. It is not equal to the old value of _SS_SIZE
+ (128) on all architectures. We must stay compatible with the old
+ definition. */
+
+#define OLD_REFERENCE_SIZE 128
+#define OLD_PADSIZE (OLD_REFERENCE_SIZE - (2 * sizeof (__ss_aligntype)))
+struct sockaddr_storage_old
+ {
+ __SOCKADDR_COMMON (old_);
+ __ss_aligntype old_align;
+ char old_padding[OLD_PADSIZE];
+ };
+
+static bool errors;
+
+static void
+check (bool ok, const char *message)
+{
+ if (!ok)
+ {
+ printf ("error: failed check: %s\n", message);
+ errors = true;
+ }
+}
+
+static int
+do_test (void)
+{
+ check (OLD_REFERENCE_SIZE >= _SS_SIZE,
+ "old target size is not smaller than actual size");
+ check (sizeof (struct sockaddr_storage_old)
+ == sizeof (struct sockaddr_storage),
+ "old and new sizes match");
+ check (__alignof (struct sockaddr_storage_old)
+ == __alignof (struct sockaddr_storage),
+ "old and new alignment matches");
+ check (offsetof (struct sockaddr_storage_old, old_family)
+ == offsetof (struct sockaddr_storage, ss_family),
+ "old and new family offsets match");
+ check (sizeof (struct sockaddr_storage) == _SS_SIZE,
+ "struct sockaddr_storage size");
+
+ /* Check for lack of holes in the struct definition. */
+ check (offsetof (struct sockaddr_storage, __ss_padding)
+ == __SOCKADDR_COMMON_SIZE,
+ "implicit padding before explicit padding");
+ check (offsetof (struct sockaddr_storage, __ss_align)
+ == __SOCKADDR_COMMON_SIZE
+ + sizeof (((struct sockaddr_storage) {}).__ss_padding),
+ "implicit padding before explicit padding");
+
+ /* Check for POSIX compatibility requirements between struct
+ sockaddr_storage and struct sockaddr_un. */
+ check (sizeof (struct sockaddr_storage) >= sizeof (struct sockaddr_un),
+ "sockaddr_storage is at least as large as sockaddr_un");
+ check (__alignof (struct sockaddr_storage)
+ >= __alignof (struct sockaddr_un),
+ "sockaddr_storage is at least as aligned as sockaddr_un");
+ check (offsetof (struct sockaddr_storage, ss_family)
+ == offsetof (struct sockaddr_un, sun_family),
+ "family offsets match");
+
+ /* Check that the compiler preserves bit patterns in aggregate
+ copies. Based on <https://gcc.gnu.org/PR71120>. */
+ check (sizeof (struct sockaddr_storage) >= sizeof (struct sockaddr_in),
+ "sockaddr_storage is at least as large as sockaddr_in");
+ {
+ struct sockaddr_storage addr;
+ memset (&addr, 0, sizeof (addr));
+ {
+ struct sockaddr_in *sinp = (struct sockaddr_in *)&addr;
+ sinp->sin_family = AF_INET;
+ sinp->sin_addr.s_addr = htonl (INADDR_LOOPBACK);
+ sinp->sin_port = htons (80);
+ }
+ struct sockaddr_storage copy;
+ copy = addr;
+
+ struct sockaddr_storage *p = malloc (sizeof (*p));
+ if (p == NULL)
+ {
+ printf ("error: malloc: %m\n");
+ return 1;
+ }
+ *p = copy;
+ const struct sockaddr_in *sinp = (const struct sockaddr_in *)p;
+ check (sinp->sin_family == AF_INET, "sin_family");
+ check (sinp->sin_addr.s_addr == htonl (INADDR_LOOPBACK), "sin_addr");
+ check (sinp->sin_port == htons (80), "sin_port");
+ free (p);
+ }
+
+ return errors;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/sysdeps/mach/hurd/bits/socket.h b/sysdeps/mach/hurd/bits/socket.h
index 02c5dac..257e438 100644
--- a/sysdeps/mach/hurd/bits/socket.h
+++ b/sysdeps/mach/hurd/bits/socket.h
@@ -156,20 +156,20 @@ struct sockaddr
/* Structure large enough to hold any socket address (with the historical
- exception of AF_UNIX). We reserve 128 bytes. */
+ exception of AF_UNIX). */
#if ULONG_MAX > 0xffffffff
# define __ss_aligntype __uint64_t
#else
# define __ss_aligntype __uint32_t
#endif
-#define _SS_SIZE 128
-#define _SS_PADSIZE (_SS_SIZE - (2 * sizeof (__ss_aligntype)))
+#define _SS_PADSIZE \
+ (_SS_SIZE - __SOCKADDR_COMMON_SIZE - sizeof (__ss_aligntype))
struct sockaddr_storage
{
__SOCKADDR_COMMON (ss_); /* Address family, etc. */
- __ss_aligntype __ss_align; /* Force desired alignment. */
char __ss_padding[_SS_PADSIZE];
+ __ss_aligntype __ss_align; /* Force desired alignment. */
};
diff --git a/sysdeps/unix/bsd/bits/sockaddr.h b/sysdeps/unix/bsd/bits/sockaddr.h
index aa12768..f5900f9 100644
--- a/sysdeps/unix/bsd/bits/sockaddr.h
+++ b/sysdeps/unix/bsd/bits/sockaddr.h
@@ -39,4 +39,7 @@ typedef unsigned char sa_family_t;
#define _HAVE_SA_LEN 1 /* We have the sa_len field. */
+/* Size of struct sockaddr_storage. */
+#define _SS_SIZE 128
+
#endif /* bits/sockaddr.h */
diff --git a/sysdeps/unix/sysv/linux/bits/socket.h b/sysdeps/unix/sysv/linux/bits/socket.h
index 0581c79..50bfbc3 100644
--- a/sysdeps/unix/sysv/linux/bits/socket.h
+++ b/sysdeps/unix/sysv/linux/bits/socket.h
@@ -158,16 +158,16 @@ struct sockaddr
/* Structure large enough to hold any socket address (with the historical
- exception of AF_UNIX). We reserve 128 bytes. */
+ exception of AF_UNIX). */
#define __ss_aligntype unsigned long int
-#define _SS_SIZE 128
-#define _SS_PADSIZE (_SS_SIZE - (2 * sizeof (__ss_aligntype)))
+#define _SS_PADSIZE \
+ (_SS_SIZE - __SOCKADDR_COMMON_SIZE - sizeof (__ss_aligntype))
struct sockaddr_storage
{
__SOCKADDR_COMMON (ss_); /* Address family, etc. */
- __ss_aligntype __ss_align; /* Force desired alignment. */
char __ss_padding[_SS_PADSIZE];
+ __ss_aligntype __ss_align; /* Force desired alignment. */
};
diff --git a/sysdeps/unix/sysv/linux/m68k/bits/sockaddr.h b/sysdeps/unix/sysv/linux/m68k/bits/sockaddr.h
new file mode 100644
index 0000000..5721f99
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/m68k/bits/sockaddr.h
@@ -0,0 +1,42 @@
+/* Definition of struct sockaddr_* members and sizes, Linux/m68k version.
+ Copyright (C) 1995-2016 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
+ <http://www.gnu.org/licenses/>. */
+
+/*
+ * Never include this file directly; use <sys/socket.h> instead.
+ */
+
+#ifndef _BITS_SOCKADDR_H
+#define _BITS_SOCKADDR_H 1
+
+
+/* POSIX.1g specifies this type name for the `sa_family' member. */
+typedef unsigned short int sa_family_t;
+
+/* This macro is used to declare the initial common members
+ of the data types used for socket addresses, `struct sockaddr',
+ `struct sockaddr_in', `struct sockaddr_un', etc. */
+
+#define __SOCKADDR_COMMON(sa_prefix) \
+ sa_family_t sa_prefix##family
+
+#define __SOCKADDR_COMMON_SIZE (sizeof (unsigned short int))
+
+/* Size of struct sockaddr_storage. */
+#define _SS_SIZE 126
+
+#endif /* bits/sockaddr.h */

43
glibc-rh1344480.patch Normal file
View File

@ -0,0 +1,43 @@
commit 809cde4a640032f2f87319c9358be4fee8d6d7d5
Author: Florian Weimer <fweimer@redhat.com>
Date: Sat Jun 11 12:12:56 2016 +0200
nss_db: Fix initialization of iteration position [BZ #20237]
When get*ent is called without a preceding set*ent, we need
to set the initial iteration position in get*ent.
Reproducer: Add “services: db files” to /etc/nsswitch.conf, then run
“perl -e getservent”. It will segfault before this change, and exit
silently after it.
(cherry picked from commit 31d0a4fa646db8b8c97ce24e0ec0a7b73de4fca1)
diff --git a/nss/nss_db/db-XXX.c b/nss/nss_db/db-XXX.c
index 4a0766a..70b58be 100644
--- a/nss/nss_db/db-XXX.c
+++ b/nss/nss_db/db-XXX.c
@@ -77,7 +77,7 @@ CONCAT(_nss_db_set,ENTNAME) (int stayopen)
keep_db |= stayopen;
/* Reset the sequential index. */
- entidx = (const char *) state.header + state.header->valstroffset;
+ entidx = NULL;
}
__libc_lock_unlock (lock);
@@ -253,8 +253,14 @@ CONCAT(_nss_db_get,ENTNAME_r) (struct STRUCTURE *result, char *buffer,
H_ERRNO_SET (NETDB_INTERNAL);
goto out;
}
+ entidx = NULL;
}
+ /* Start from the beginning if freshly initialized or reset
+ requested by set*ent. */
+ if (entidx == NULL)
+ entidx = (const char *) state.header + state.header->valstroffset;
+
status = NSS_STATUS_UNAVAIL;
if (state.header != MAP_FAILED)
{

36
glibc-rh1348620.patch Normal file
View File

@ -0,0 +1,36 @@
commit 60022fbfba872422993caf6130ad4b92e74bb356
Author: Florian Weimer <fweimer@redhat.com>
Date: Tue Jun 21 21:29:21 2016 +0200
malloc: Avoid premature fallback to mmap [BZ #20284]
Before this change, the while loop in reused_arena which avoids
returning a corrupt arena would never execute its body if the selected
arena were not corrupt. As a result, result == begin after the loop,
and the function returns NULL, triggering fallback to mmap.
(cherry picked from commit a3b473373ee43a292f5ec68a7fda6b9cfb26a9b0)
diff --git a/malloc/arena.c b/malloc/arena.c
index 7c52633..5350992 100644
--- a/malloc/arena.c
+++ b/malloc/arena.c
@@ -938,14 +938,12 @@ reused_arena (mstate avoid_arena)
{
result = result->next;
if (result == begin)
- break;
+ /* We looped around the arena list. We could not find any
+ arena that was either not corrupted or not the one we
+ wanted to avoid. */
+ return NULL;
}
- /* We could not find any arena that was either not corrupted or not the one
- we wanted to avoid. */
- if (result == begin || result == avoid_arena)
- return NULL;
-
/* No arena available without contention. Wait for the next in line. */
LIBC_PROBE (memory_arena_reuse_wait, 3, &result->mutex, result, avoid_arena);
(void) mutex_lock (&result->mutex);

166
glibc-rh1352625.patch Normal file
View File

@ -0,0 +1,166 @@
commit 21ed68033a6732e4478926de06dd091ee7f1d4c1
Author: Florian Weimer <fweimer@redhat.com>
Date: Wed Aug 17 14:57:00 2016 +0200
Do not override objects in libc.a in other static libraries [BZ #20452]
With this change, we no longer add sysdep.o and similar objects which
are present in libc.a to other static libraries.
(cherry picked from commit d9067fca40b8aac156d73cfa44d6875813555a6c)
diff --git a/sysdeps/ia64/nptl/Makefile b/sysdeps/ia64/nptl/Makefile
index fd8abbc..84e0b8b 100644
--- a/sysdeps/ia64/nptl/Makefile
+++ b/sysdeps/ia64/nptl/Makefile
@@ -21,4 +21,5 @@ endif
ifeq ($(subdir),nptl)
libpthread-routines += ptw-sysdep ptw-sigblock ptw-sigprocmask
+libpthread-shared-only-routines += ptw-sysdep ptw-sigblock ptw-sigprocmask
endif
diff --git a/sysdeps/mips/Makefile b/sysdeps/mips/Makefile
index 463b121..4dfaaa8 100644
--- a/sysdeps/mips/Makefile
+++ b/sysdeps/mips/Makefile
@@ -9,6 +9,7 @@ endif
ifeq ($(subdir),rt)
librt-sysdep_routines += rt-sysdep
+librt-shared-only-routines += rt-sysdep
endif
ifeq ($(subdir),debug)
diff --git a/sysdeps/mips/nptl/Makefile b/sysdeps/mips/nptl/Makefile
index 46baad5..4a710ee 100644
--- a/sysdeps/mips/nptl/Makefile
+++ b/sysdeps/mips/nptl/Makefile
@@ -21,4 +21,5 @@ endif
ifeq ($(subdir),nptl)
libpthread-sysdep_routines += nptl-sysdep
+libpthread-shared-only-routines += nptl-sysdep
endif
diff --git a/sysdeps/s390/nptl/Makefile b/sysdeps/s390/nptl/Makefile
index 1333260..d105648 100644
--- a/sysdeps/s390/nptl/Makefile
+++ b/sysdeps/s390/nptl/Makefile
@@ -21,4 +21,5 @@ endif
ifeq ($(subdir),nptl)
libpthread-routines += ptw-sysdep
+libpthread-shared-only-routines += ptw-sysdep
endif
diff --git a/sysdeps/unix/alpha/Makefile b/sysdeps/unix/alpha/Makefile
index 441aa02..0660847 100644
--- a/sysdeps/unix/alpha/Makefile
+++ b/sysdeps/unix/alpha/Makefile
@@ -1,3 +1,4 @@
ifeq ($(subdir),rt)
librt-sysdep_routines += rt-sysdep
+librt-shared-only-routines += rt-sysdep
endif
diff --git a/sysdeps/unix/sysv/linux/alpha/Makefile b/sysdeps/unix/sysv/linux/alpha/Makefile
index 3769bef..6e56125 100644
--- a/sysdeps/unix/sysv/linux/alpha/Makefile
+++ b/sysdeps/unix/sysv/linux/alpha/Makefile
@@ -41,4 +41,5 @@ endif # math
ifeq ($(subdir),nptl)
# pull in __syscall_error routine, __sigprocmask, __syscall_rt_sigaction
libpthread-routines += ptw-sysdep ptw-sigprocmask ptw-rt_sigaction
+libpthread-shared-only-routines += ptw-sysdep ptw-sigprocmask ptw-rt_sigaction
endif
diff --git a/sysdeps/unix/sysv/linux/i386/Makefile b/sysdeps/unix/sysv/linux/i386/Makefile
index 80da593..b365c97 100644
--- a/sysdeps/unix/sysv/linux/i386/Makefile
+++ b/sysdeps/unix/sysv/linux/i386/Makefile
@@ -18,6 +18,7 @@ endif
# libpthread uses six-argument inline syscalls.
ifeq ($(subdir),nptl)
libpthread-sysdep_routines += libc-do-syscall
+libpthread-shared-only-routines += libc-do-syscall
endif
ifeq ($(subdir),resource)
diff --git a/sysdeps/unix/sysv/linux/ia64/Makefile b/sysdeps/unix/sysv/linux/ia64/Makefile
index 1de62c5..4d6766d 100644
--- a/sysdeps/unix/sysv/linux/ia64/Makefile
+++ b/sysdeps/unix/sysv/linux/ia64/Makefile
@@ -19,6 +19,7 @@ endif
ifeq ($(subdir),rt)
librt-routines += rt-sysdep
+librt-shared-only-routines += rt-sysdep
endif
ifeq ($(subdir),nptl)
diff --git a/sysdeps/unix/sysv/linux/microblaze/Makefile b/sysdeps/unix/sysv/linux/microblaze/Makefile
index 44a838f..d178bc6 100644
--- a/sysdeps/unix/sysv/linux/microblaze/Makefile
+++ b/sysdeps/unix/sysv/linux/microblaze/Makefile
@@ -5,4 +5,5 @@ endif
ifeq ($(subdir),nptl)
# pull in __syscall_error routine
libpthread-routines += sysdep
-endif
\ No newline at end of file
+libpthread-shared-only-routines += sysdep
+endif
diff --git a/sysdeps/unix/sysv/linux/powerpc/Makefile b/sysdeps/unix/sysv/linux/powerpc/Makefile
index c89ed9e..2cfb46e 100644
--- a/sysdeps/unix/sysv/linux/powerpc/Makefile
+++ b/sysdeps/unix/sysv/linux/powerpc/Makefile
@@ -8,6 +8,7 @@ abi-64-v2-condition := __WORDSIZE == 64 && _CALL_ELF == 2
ifeq ($(subdir),rt)
librt-routines += rt-sysdep
+librt-shared-only-routines += rt-sysdep
endif
ifeq ($(subdir),stdlib)
@@ -34,4 +35,5 @@ ifeq ($(subdir),nptl)
libpthread-routines += sysdep
libpthread-sysdep_routines += elision-lock elision-unlock elision-timed \
elision-trylock
+libpthread-shared-only-routines += sysdep
endif
diff --git a/sysdeps/unix/sysv/linux/s390/Makefile b/sysdeps/unix/sysv/linux/s390/Makefile
index 497ffd5..f8ed013 100644
--- a/sysdeps/unix/sysv/linux/s390/Makefile
+++ b/sysdeps/unix/sysv/linux/s390/Makefile
@@ -6,6 +6,7 @@ abi-64-condition := __WORDSIZE == 64
ifeq ($(subdir),rt)
librt-routines += rt-sysdep
+librt-shared-only-routines += rt-sysdep
endif
ifeq ($(subdir),stdlib)
diff --git a/sysdeps/unix/sysv/linux/sparc/Makefile b/sysdeps/unix/sysv/linux/sparc/Makefile
index e67aecf..a67d199 100644
--- a/sysdeps/unix/sysv/linux/sparc/Makefile
+++ b/sysdeps/unix/sysv/linux/sparc/Makefile
@@ -6,6 +6,7 @@ abi-64-condition := __WORDSIZE == 64
ifeq ($(subdir),rt)
librt-routines += rt-sysdep
+librt-shared-only-routines += rt-sysdep
endif
ifeq ($(subdir),sysvipc)
@@ -15,4 +16,5 @@ endif
ifeq ($(subdir),nptl)
# pull in __syscall_error routine
libpthread-routines += sysdep
+libpthread-shared-only-routines += sysdep
endif
diff --git a/sysdeps/unix/sysv/linux/tile/Makefile b/sysdeps/unix/sysv/linux/tile/Makefile
index 1c1cfff..43acea3 100644
--- a/sysdeps/unix/sysv/linux/tile/Makefile
+++ b/sysdeps/unix/sysv/linux/tile/Makefile
@@ -25,4 +25,5 @@ endif
ifeq ($(subdir),nptl)
# pull in __syscall_error routine
libpthread-routines += sysdep
+libpthread-shared-only-routines += sysdep
endif

125
glibc-rh1366830.patch Normal file
View File

@ -0,0 +1,125 @@
commit 718da076cbb4675b1d7ae735bc1f3698618cccec
Author: Florian Weimer <fweimer@redhat.com>
Date: Thu Aug 18 11:15:42 2016 +0200
argp: Do not override GCC keywords with macros [BZ #16907]
glibc provides fallback definitions already. It is not necessary to
suppress warnings for unknown attributes because GCC does this
automatically for system headers.
This commit does not sync with gnulib because gnulib has started to use
_GL_* macros in the header file, which are arguably in the gnulib
implementation space and not suitable for an installed glibc header
file.
(cherry picked from commit 2c820533c61fed175390bc6058afbbe42d2edc37)
diff --git a/argp/argp-fmtstream.h b/argp/argp-fmtstream.h
index 6dd087a..8f8192a 100644
--- a/argp/argp-fmtstream.h
+++ b/argp/argp-fmtstream.h
@@ -29,21 +29,6 @@
#include <string.h>
#include <unistd.h>
-#ifndef __attribute__
-/* This feature is available in gcc versions 2.5 and later. */
-# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5) || \
- defined __STRICT_ANSI__
-# define __attribute__(Spec) /* empty */
-# endif
-/* The __-protected variants of `format' and `printf' attributes
- are accepted by gcc versions 2.6.4 (effectively 2.7) and later. */
-# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7) || \
- defined __STRICT_ANSI__
-# define __format__ format
-# define __printf__ printf
-# endif
-#endif
-
#if defined (__GNU_LIBRARY__) && defined (HAVE_LINEWRAP_H)
/* line_wrap_stream is available, so use that. */
#define ARGP_FMTSTREAM_USE_LINEWRAP
@@ -111,6 +96,8 @@ struct argp_fmtstream
typedef struct argp_fmtstream *argp_fmtstream_t;
+__BEGIN_DECLS
+
/* Return an argp_fmtstream that outputs to STREAM, and which prefixes lines
written on it with LMARGIN spaces and limits them to RMARGIN columns
total. If WMARGIN >= 0, words that extend past RMARGIN are wrapped by
@@ -297,6 +284,8 @@ __argp_fmtstream_point (argp_fmtstream_t __fs)
#endif /* __OPTIMIZE__ */
+__END_DECLS
+
#endif /* ARGP_FMTSTREAM_USE_LINEWRAP */
#endif /* argp-fmtstream.h */
diff --git a/argp/argp.h b/argp/argp.h
index 40bf5e6..0771921 100644
--- a/argp/argp.h
+++ b/argp/argp.h
@@ -28,48 +28,12 @@
#define __need_error_t
#include <errno.h>
-#ifndef __THROW
-# define __THROW
-#endif
-#ifndef __NTH
-# define __NTH(fct) fct __THROW
-#endif
-
-#ifndef __attribute__
-/* This feature is available in gcc versions 2.5 and later. */
-# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5) || \
- defined __STRICT_ANSI__
-# define __attribute__(Spec) /* empty */
-# endif
-/* The __-protected variants of `format' and `printf' attributes
- are accepted by gcc versions 2.6.4 (effectively 2.7) and later. */
-# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7) || \
- defined __STRICT_ANSI__
-# define __format__ format
-# define __printf__ printf
-# endif
-#endif
-
-/* GCC 2.95 and later have "__restrict"; C99 compilers have
- "restrict", and "configure" may have defined "restrict". */
-#ifndef __restrict
-# if ! (2 < __GNUC__ || (2 == __GNUC__ && 95 <= __GNUC_MINOR__))
-# if defined restrict || 199901L <= __STDC_VERSION__
-# define __restrict restrict
-# else
-# define __restrict
-# endif
-# endif
-#endif
-
#ifndef __error_t_defined
typedef int error_t;
# define __error_t_defined
#endif
-#ifdef __cplusplus
-extern "C" {
-#endif
+__BEGIN_DECLS
/* A description of a particular option. A pointer to an array of
these is passed in the OPTIONS field of an argp structure. Each option
@@ -590,8 +554,6 @@ __NTH (__option_is_end (const struct argp_option *__opt))
# endif
#endif /* Use extern inlines. */
-#ifdef __cplusplus
-}
-#endif
+__END_DECLS
#endif /* argp.h */

View File

@ -1,6 +1,16 @@
diff -rup a/elf/dl-load.c b/elf/dl-load.c
--- a/elf/dl-load.c 2012-02-03 10:59:58.917870716 -0700
+++ b/elf/dl-load.c 2012-02-03 11:01:01.796580644 -0700
@@ -880,7 +880,8 @@ _dl_map_object_from_fd (const char *name, int fd, struct filebuf *fbp,
/* Get file information. */
struct r_file_id id;
- if (__glibc_unlikely (!_dl_get_file_id (fd, &id)))
+ struct stat64 st;
+ if (__glibc_unlikely (!_dl_get_file_id (fd, &id, &st)))
{
errstring = N_("cannot stat shared object");
call_lose_errno:
@@ -1130,6 +1130,16 @@ _dl_map_object_from_fd (const char *name
= N_("ELF load command address/offset not properly aligned");
goto call_lose;
@ -18,3 +28,45 @@ diff -rup a/elf/dl-load.c b/elf/dl-load.c
struct loadcmd *c = &loadcmds[nloadcmds++];
c->mapstart = ph->p_vaddr & ~(GLRO(dl_pagesize) - 1);
diff --git a/sysdeps/generic/dl-fileid.h b/sysdeps/generic/dl-fileid.h
index 2cbd21d..9b7f410 100644
--- a/sysdeps/generic/dl-fileid.h
+++ b/sysdeps/generic/dl-fileid.h
@@ -29,7 +29,8 @@ struct r_file_id
On error, returns false, with errno set. */
static inline bool
_dl_get_file_id (int fd __attribute__ ((unused)),
- struct r_file_id *id __attribute__ ((unused)))
+ struct r_file_id *id __attribute__ ((unused)),
+ struct stat64_t *st __attribute__((unused)))
{
return true;
}
diff --git a/sysdeps/posix/dl-fileid.h b/sysdeps/posix/dl-fileid.h
index d0d5436..7115c3b 100644
--- a/sysdeps/posix/dl-fileid.h
+++ b/sysdeps/posix/dl-fileid.h
@@ -27,18 +27,16 @@ struct r_file_id
ino64_t ino;
};
-/* Sample FD to fill in *ID. Returns true on success.
+/* Sample FD to fill in *ID and *ST. Returns true on success.
On error, returns false, with errno set. */
static inline bool
-_dl_get_file_id (int fd, struct r_file_id *id)
+_dl_get_file_id (int fd, struct r_file_id *id, struct stat64 *st)
{
- struct stat64 st;
-
- if (__glibc_unlikely (__fxstat64 (_STAT_VER, fd, &st) < 0))
+ if (__glibc_unlikely (__fxstat64 (_STAT_VER, fd, st) < 0))
return false;
- id->dev = st.st_dev;
- id->ino = st.st_ino;
+ id->dev = st->st_dev;
+ id->ino = st->st_ino;
return true;
}

View File

@ -1,167 +0,0 @@
diff -pruN a/malloc/arena.c b/malloc/arena.c
--- a/malloc/arena.c 2014-01-07 07:07:47.000000000 +0530
+++ b/malloc/arena.c 2014-01-07 14:11:40.093628218 +0530
@@ -702,7 +702,7 @@ heap_trim (heap_info *heap, size_t pad)
if (!prev_inuse (p)) /* consolidate backward */
{
p = prev_chunk (p);
- unlink (p, bck, fwd);
+ unlink (ar_ptr, p, bck, fwd);
}
assert (((unsigned long) ((char *) p + new_size) & (pagesz - 1)) == 0);
assert (((char *) p + new_size) == ((char *) heap + heap->size));
diff -pruN a/malloc/hooks.c b/malloc/hooks.c
--- a/malloc/hooks.c 2014-01-07 07:07:47.000000000 +0530
+++ b/malloc/hooks.c 2014-01-07 14:12:41.804625603 +0530
@@ -237,7 +237,9 @@ top_check (void)
(char *) t + chunksize (t) == mp_.sbrk_base + main_arena.system_mem)))
return 0;
+ mutex_unlock(&main_arena.mutex);
malloc_printerr (check_action, "malloc: top chunk is corrupt", t);
+ mutex_lock(&main_arena.mutex);
/* Try to set up a new top chunk. */
brk = MORECORE (0);
diff -pruN a/malloc/malloc.c b/malloc/malloc.c
--- a/malloc/malloc.c 2014-01-07 07:07:47.000000000 +0530
+++ b/malloc/malloc.c 2014-01-07 14:29:53.370581893 +0530
@@ -1404,11 +1404,15 @@ typedef struct malloc_chunk *mbinptr;
#define last(b) ((b)->bk)
/* Take a chunk off a bin list */
-#define unlink(P, BK, FD) { \
+#define unlink(AV, P, BK, FD) { \
FD = P->fd; \
BK = P->bk; \
if (__builtin_expect (FD->bk != P || BK->fd != P, 0)) \
- malloc_printerr (check_action, "corrupted double-linked list", P); \
+ { \
+ mutex_unlock(&(AV)->mutex); \
+ malloc_printerr (check_action, "corrupted double-linked list", P); \
+ mutex_lock(&(AV)->mutex); \
+ } \
else { \
FD->bk = BK; \
BK->fd = FD; \
@@ -2524,7 +2528,9 @@ sysmalloc (INTERNAL_SIZE_T nb, mstate av
else if (contiguous (av) && old_size && brk < old_end)
{
/* Oops! Someone else killed our space.. Can't touch anything. */
+ mutex_unlock(&av->mutex);
malloc_printerr (3, "break adjusted to free malloc space", brk);
+ mutex_lock(&av->mutex);
}
/*
@@ -3353,7 +3359,9 @@ _int_malloc (mstate av, size_t bytes)
{
errstr = "malloc(): memory corruption (fast)";
errout:
+ mutex_unlock(&av->mutex);
malloc_printerr (check_action, errstr, chunk2mem (victim));
+ mutex_lock(&av->mutex);
return NULL;
}
check_remalloced_chunk (av, victim, nb);
@@ -3441,8 +3449,12 @@ _int_malloc (mstate av, size_t bytes)
bck = victim->bk;
if (__builtin_expect (victim->size <= 2 * SIZE_SZ, 0)
|| __builtin_expect (victim->size > av->system_mem, 0))
- malloc_printerr (check_action, "malloc(): memory corruption",
- chunk2mem (victim));
+ {
+ void *p = chunk2mem(victim);
+ mutex_unlock(&av->mutex);
+ malloc_printerr (check_action, "malloc(): memory corruption", p);
+ mutex_lock(&av->mutex);
+ }
size = chunksize (victim);
/*
@@ -3589,7 +3601,7 @@ _int_malloc (mstate av, size_t bytes)
victim = victim->fd;
remainder_size = size - nb;
- unlink (victim, bck, fwd);
+ unlink (av, victim, bck, fwd);
/* Exhaust */
if (remainder_size < MINSIZE)
@@ -3694,7 +3706,7 @@ _int_malloc (mstate av, size_t bytes)
remainder_size = size - nb;
/* unlink */
- unlink (victim, bck, fwd);
+ unlink (av, victim, bck, fwd);
/* Exhaust */
if (remainder_size < MINSIZE)
@@ -3832,9 +3844,11 @@ _int_free (mstate av, mchunkptr p, int h
{
errstr = "free(): invalid pointer";
errout:
- if (!have_lock && locked)
+ if (have_lock || locked)
(void) mutex_unlock (&av->mutex);
malloc_printerr (check_action, errstr, chunk2mem (p));
+ if (have_lock)
+ mutex_lock(&av->mutex);
return;
}
/* We know that each chunk is at least MINSIZE bytes in size or a
@@ -3981,7 +3995,7 @@ _int_free (mstate av, mchunkptr p, int h
prevsize = p->prev_size;
size += prevsize;
p = chunk_at_offset(p, -((long) prevsize));
- unlink(p, bck, fwd);
+ unlink(av, p, bck, fwd);
}
if (nextchunk != av->top) {
@@ -3990,7 +4004,7 @@ _int_free (mstate av, mchunkptr p, int h
/* consolidate forward */
if (!nextinuse) {
- unlink(nextchunk, bck, fwd);
+ unlink(av, nextchunk, bck, fwd);
size += nextsize;
} else
clear_inuse_bit_at_offset(nextchunk, 0);
@@ -4151,7 +4165,7 @@ static void malloc_consolidate(mstate av
prevsize = p->prev_size;
size += prevsize;
p = chunk_at_offset(p, -((long) prevsize));
- unlink(p, bck, fwd);
+ unlink(av, p, bck, fwd);
}
if (nextchunk != av->top) {
@@ -4159,7 +4173,7 @@ static void malloc_consolidate(mstate av
if (!nextinuse) {
size += nextsize;
- unlink(nextchunk, bck, fwd);
+ unlink(av, nextchunk, bck, fwd);
} else
clear_inuse_bit_at_offset(nextchunk, 0);
@@ -4228,7 +4242,9 @@ _int_realloc(mstate av, mchunkptr oldp,
{
errstr = "realloc(): invalid old size";
errout:
+ mutex_unlock(&av->mutex);
malloc_printerr (check_action, errstr, chunk2mem (oldp));
+ mutex_lock(&av->mutex);
return NULL;
}
@@ -4274,7 +4290,7 @@ _int_realloc(mstate av, mchunkptr oldp,
(unsigned long) (nb))
{
newp = oldp;
- unlink (next, bck, fwd);
+ unlink (av, next, bck, fwd);
}
/* allocate, copy, free */

View File

@ -1,33 +0,0 @@
diff -rup a/resolv/res_init.c b/resolv/res_init.c
--- a/resolv/res_init.c 2012-07-26 15:10:45.655638776 -0600
+++ b/resolv/res_init.c 2012-07-26 15:11:27.731423002 -0600
@@ -314,9 +314,9 @@ __res_vinit(res_state statp, int preinit
cp++;
if ((*cp != '\0') && (*cp != '\n')
&& __inet_aton(cp, &a)) {
- statp->nsaddr_list[nservall].sin_addr = a;
- statp->nsaddr_list[nservall].sin_family = AF_INET;
- statp->nsaddr_list[nservall].sin_port =
+ statp->nsaddr_list[nserv].sin_addr = a;
+ statp->nsaddr_list[nserv].sin_family = AF_INET;
+ statp->nsaddr_list[nserv].sin_port =
htons(NAMESERVER_PORT);
nserv++;
#ifdef _LIBC
diff -rup a/resolv/res_send.c b/resolv/res_send.c
--- a/resolv/res_send.c 2010-05-04 05:27:23.000000000 -0600
+++ b/resolv/res_send.c 2012-07-26 15:34:58.398261659 -0600
@@ -421,10 +421,10 @@ __libc_res_nsend(res_state statp, const
EXT(statp).nsmap[n] = MAXNS;
}
}
- n = statp->nscount;
- if (statp->nscount > EXT(statp).nscount)
+ n = statp->nscount - EXT(statp).nscount6;
+ if (n > EXT(statp).nscount)
for (n = EXT(statp).nscount, ns = 0;
- n < statp->nscount; n++) {
+ n < statp->nscount - EXT(statp).nscount6; n++) {
while (ns < MAXNS
&& EXT(statp).nsmap[ns] != MAXNS)
ns++;

26
glibc-rtkaio-libof.patch Normal file
View File

@ -0,0 +1,26 @@
diff -pruN glibc-2.21-649-gae5eae7/rtkaio/Makefile glibc-2.21-649-gae5eae7.new/rtkaio/Makefile
--- glibc-2.21-649-gae5eae7/rtkaio/Makefile 2015-07-27 22:57:05.742601066 +0530
+++ glibc-2.21-649-gae5eae7.new/rtkaio/Makefile 2015-07-27 23:33:09.892874337 +0530
@@ -66,7 +66,9 @@ CFLAGS-kaio_librt-cancellation.c = -fasy
LDFLAGS-rtkaio.so = -Wl,-soname=lib$(libprefix)rt.so$(librt.so-version) \
-Wl,--enable-new-dtags,-z,nodelete
-CPPFLAGS-librtkaio += -DIS_IN_librt=1 -I$(..)rt
+# Resort to this ugliness of undefining and defining MODULE_NAME because
+# setting libof-<> to librt has many more side-effects that we want to avoid.
+CPPFLAGS-librtkaio += -I$(..)rt -UMODULE_NAME -DMODULE_NAME=librt
rpath-dirs := $(patsubst rt,rtkaio,$(rpath-dirs))
diff -pruN glibc-2.21-649-gae5eae7/rtkaio/sysdeps/unix/sysv/linux/syscalls.list glibc-2.21-649-gae5eae7.new/rtkaio/sysdeps/unix/sysv/linux/syscalls.list
--- glibc-2.21-649-gae5eae7/rtkaio/sysdeps/unix/sysv/linux/syscalls.list 2015-07-27 22:47:23.073776396 +0530
+++ glibc-2.21-649-gae5eae7.new/rtkaio/sysdeps/unix/sysv/linux/syscalls.list 2015-07-27 23:33:09.892874337 +0530
@@ -1,5 +1,5 @@
# File name Caller Syscall name Args Strong name Weak names
-kaio_mq_timedsend - mq_timedsend Ci:ipiip __GI_mq_timedsend mq_timedsend
-kaio_mq_timedreceive - mq_timedreceive Ci:ipipp __GI_mq_timedreceive mq_timedreceive
-kaio_mq_setattr - mq_getsetattr i:ipp __GI_mq_setattr mq_setattr
+kaio_mq_timedsend - mq_timedsend Ci:ipiip __mq_timedsend mq_timedsend
+kaio_mq_timedreceive - mq_timedreceive Ci:ipipp __mq_timedreceive mq_timedreceive
+kaio_mq_setattr - mq_getsetattr i:ipp mq_setattr

126
glibc-swbz20222.patch Normal file
View File

@ -0,0 +1,126 @@
commit 0d6895748bf4531b5e516c47409d35d104f51642
Author: Florian Weimer <fweimer@redhat.com>
Date: Sat Jun 11 12:07:14 2016 +0200
fopencookie: Mangle function pointers stored on the heap [BZ #20222]
(cherry picked from commit 983fd5c41ab7e5a5c33922259ca1ac99b3b413f8)
diff --git a/libio/iofopncook.c b/libio/iofopncook.c
index b845d29..3aad3d3 100644
--- a/libio/iofopncook.c
+++ b/libio/iofopncook.c
@@ -46,11 +46,13 @@ _IO_cookie_read (fp, buf, size)
_IO_ssize_t size;
{
struct _IO_cookie_file *cfile = (struct _IO_cookie_file *) fp;
+ cookie_read_function_t *read_cb = cfile->__io_functions.read;
+ PTR_DEMANGLE (read_cb);
- if (cfile->__io_functions.read == NULL)
+ if (read_cb == NULL)
return -1;
- return cfile->__io_functions.read (cfile->__cookie, buf, size);
+ return read_cb (cfile->__cookie, buf, size);
}
static _IO_ssize_t
@@ -60,14 +62,16 @@ _IO_cookie_write (fp, buf, size)
_IO_ssize_t size;
{
struct _IO_cookie_file *cfile = (struct _IO_cookie_file *) fp;
+ cookie_write_function_t *write_cb = cfile->__io_functions.write;
+ PTR_DEMANGLE (write_cb);
- if (cfile->__io_functions.write == NULL)
+ if (write_cb == NULL)
{
fp->_flags |= _IO_ERR_SEEN;
return 0;
}
- _IO_ssize_t n = cfile->__io_functions.write (cfile->__cookie, buf, size);
+ _IO_ssize_t n = write_cb (cfile->__cookie, buf, size);
if (n < size)
fp->_flags |= _IO_ERR_SEEN;
@@ -81,9 +85,11 @@ _IO_cookie_seek (fp, offset, dir)
int dir;
{
struct _IO_cookie_file *cfile = (struct _IO_cookie_file *) fp;
+ cookie_seek_function_t *seek_cb = cfile->__io_functions.seek;
+ PTR_DEMANGLE (seek_cb);
- return ((cfile->__io_functions.seek == NULL
- || (cfile->__io_functions.seek (cfile->__cookie, &offset, dir)
+ return ((seek_cb == NULL
+ || (seek_cb (cfile->__cookie, &offset, dir)
== -1)
|| offset == (_IO_off64_t) -1)
? _IO_pos_BAD : offset);
@@ -94,11 +100,13 @@ _IO_cookie_close (fp)
_IO_FILE *fp;
{
struct _IO_cookie_file *cfile = (struct _IO_cookie_file *) fp;
+ cookie_close_function_t *close_cb = cfile->__io_functions.close;
+ PTR_DEMANGLE (close_cb);
- if (cfile->__io_functions.close == NULL)
+ if (close_cb == NULL)
return 0;
- return cfile->__io_functions.close (cfile->__cookie);
+ return close_cb (cfile->__cookie);
}
@@ -140,6 +148,19 @@ static const struct _IO_jump_t _IO_cookie_jumps = {
};
+/* Copy the callbacks from SOURCE to *TARGET, with pointer
+ mangling. */
+static void
+set_callbacks (_IO_cookie_io_functions_t *target,
+ _IO_cookie_io_functions_t source)
+{
+ PTR_MANGLE (source.read);
+ PTR_MANGLE (source.write);
+ PTR_MANGLE (source.seek);
+ PTR_MANGLE (source.close);
+ *target = source;
+}
+
void
_IO_cookie_init (struct _IO_cookie_file *cfile, int read_write,
void *cookie, _IO_cookie_io_functions_t io_functions)
@@ -148,7 +169,7 @@ _IO_cookie_init (struct _IO_cookie_file *cfile, int read_write,
_IO_JUMPS (&cfile->__fp) = &_IO_cookie_jumps;
cfile->__cookie = cookie;
- cfile->__io_functions = io_functions;
+ set_callbacks (&cfile->__io_functions, io_functions);
_IO_file_init (&cfile->__fp);
@@ -223,14 +244,14 @@ _IO_old_cookie_seek (fp, offset, dir)
int dir;
{
struct _IO_cookie_file *cfile = (struct _IO_cookie_file *) fp;
- int (*seek) (_IO_FILE *, _IO_off_t, int);
- int ret;
+ int (*seek_cb) (_IO_FILE *, _IO_off_t, int)
+ = (int (*) (_IO_FILE *, _IO_off_t, int)) cfile->__io_functions.seek;;
+ PTR_DEMANGLE (seek_cb);
- seek = (int (*)(_IO_FILE *, _IO_off_t, int)) cfile->__io_functions.seek;
- if (seek == NULL)
+ if (seek_cb == NULL)
return _IO_pos_BAD;
- ret = seek (cfile->__cookie, offset, dir);
+ int ret = seek_cb (cfile->__cookie, offset, dir);
return (ret == -1) ? _IO_pos_BAD : ret;
}

39
glibc-swbz20435.patch Normal file
View File

@ -0,0 +1,39 @@
commit a85abfa92220239cad0a8a6b0f2a223f5e6472a9
Author: Andreas Schwab <schwab@suse.de>
Date: Thu Aug 18 11:38:28 2016 +0200
arm: mark __startcontext as .cantunwind (bug 20435)
__startcontext marks the bottom of the call stack of the contexts created
by makecontext.
(cherry picked from commit 9e2ff6c9cc54c0b4402b8d49e4abe7000fde7617)
Also includes the NEWS update, cherry-picked from commits
056dd72af83f5459ce6d545a49dea6dba7d635dc and
4d047efdbc55b0d68947cde682e5363d16a66294.
diff --git a/sysdeps/unix/sysv/linux/arm/setcontext.S b/sysdeps/unix/sysv/linux/arm/setcontext.S
index 24c7294..926b65a 100644
--- a/sysdeps/unix/sysv/linux/arm/setcontext.S
+++ b/sysdeps/unix/sysv/linux/arm/setcontext.S
@@ -86,12 +86,19 @@ weak_alias(__setcontext, setcontext)
/* Called when a makecontext() context returns. Start the
context in R4 or fall through to exit(). */
+ /* Unwind descriptors are looked up based on PC - 2, so we have to
+ make sure to mark the instruction preceding the __startcontext
+ label as .cantunwind. */
+ .fnstart
+ .cantunwind
+ nop
ENTRY(__startcontext)
movs r0, r4
bne PLTJMP(__setcontext)
@ New context was 0 - exit
b PLTJMP(HIDDEN_JUMPTARGET(exit))
+ .fnend
END(__startcontext)
#ifdef PIC

View File

@ -1,6 +1,6 @@
%define glibcsrcdir glibc-2.21-357-gb40a4e1
%define glibcversion 2.21.90
%define glibcrelease 19%{?dist}
%define glibcsrcdir glibc-2.22
%define glibcversion 2.22
%define glibcrelease 18%{?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.
@ -208,8 +208,10 @@ Patch0053: glibc-cs-path.patch
# Remove the clock_* functions and use the ones in libc like librt does.
Patch0054: glibc-rtkaio-clock.patch
# Temporarily revert a fix to work around bz #1209451.
Patch0055: glibc-revert-arena-threshold-fix.patch
Patch0055: glibc-rtkaio-libof.patch
# Add C.UTF-8 locale into /usr/lib/locale/
Patch0059: glibc-c-utf8-locale.patch
##############################################################################
#
@ -217,6 +219,66 @@ Patch0055: glibc-revert-arena-threshold-fix.patch
#
##############################################################################
Patch1000: glibc-rh1276711.patch
Patch1001: glibc-rh1288662.patch
Patch1002: glibc-rh1276761-1.patch
Patch1003: glibc-rh1276761-2.patch
Patch1004: glibc-rh1276761-3.patch
Patch1005: glibc-rh1332912.patch
Patch1006: glibc-rh1321954.patch
Patch1007: glibc-rh1332914-1.patch
Patch1008: glibc-rh1332914-2.patch
Patch1009: glibc-rh1332914-3.patch
Patch1010: glibc-rh1332914-4.patch
Patch1011: glibc-rh1332914-5.patch
Patch1012: glibc-rh1313404-1.patch
Patch1013: glibc-rh1313404-2.patch
Patch1014: glibc-rh1313404-3.patch
Patch1015: glibc-rh1321861.patch
Patch1016: glibc-rh1316972.patch
Patch1017: glibc-rh1316972-2.patch
Patch1018: glibc-rh1333940.patch
Patch1019: glibc-rh1333901-1.patch
Patch1020: glibc-rh1333901-2.patch
Patch1021: glibc-rh1333901-3.patch
Patch1022: glibc-rh1333901-4.patch
Patch1023: glibc-rh1333901-5.patch
Patch1024: glibc-rh1315648-1.patch
Patch1025: glibc-rh1315648-2.patch
Patch1028: glibc-rh1332917-1.patch
Patch1029: glibc-rh1332917-2.patch
Patch1030: glibc-rh1332917-3.patch
Patch1031: glibc-rh1332917-4.patch
Patch1032: glibc-rh1332917-5.patch
Patch1033: glibc-rh1321372.patch
Patch1034: glibc-rh1300314.patch
Patch1035: glibc-rh1300311-1.patch
Patch1036: glibc-rh1300311-2.patch
Patch1037: glibc-rh1300311-3.patch
Patch1038: glibc-rh1300311-4.patch
Patch1039: glibc-rh1293139.patch
Patch1040: glibc-rh1300300.patch
Patch1041: glibc-rh1300304-1.patch
Patch1042: glibc-rh1300304-2.patch
Patch1043: glibc-rh1300304-3.patch
Patch1044: glibc-rh1307234-1.patch
Patch1045: glibc-rh1307234-2.patch
Patch1046: glibc-rh1288740.patch
Patch1047: glibc-rh1330888.patch
Patch1048: glibc-rh1204521.patch
Patch1049: glibc-rh1282011.patch
Patch1050: glibc-rh1337140.patch
Patch1051: glibc-rh1326903.patch
Patch1052: glibc-rh1337291.patch
Patch1053: glibc-build-time.patch
Patch1054: glibc-rh1352625.patch
Patch1055: glibc-rh1348620.patch
Patch1056: glibc-swbz20435.patch
Patch1057: glibc-rh1294574.patch
Patch1058: glibc-rh1344480.patch
Patch1059: glibc-swbz20222.patch
Patch1060: glibc-rh1366830.patch
##############################################################################
#
# Patches submitted, but not yet approved upstream.
@ -230,16 +292,11 @@ Patch0055: glibc-revert-arena-threshold-fix.patch
# http://sourceware.org/ml/libc-alpha/2012-12/msg00103.html
Patch2007: glibc-rh697421.patch
Patch2011: glibc-rh757881.patch
Patch2013: glibc-rh741105.patch
# Upstream BZ 14247
Patch2023: glibc-rh827510.patch
# Upstream BZ 13028
Patch2026: glibc-rh841787.patch
# Upstream BZ 14185
Patch2027: glibc-rh819430.patch
@ -247,7 +304,6 @@ Patch2031: glibc-rh1070416.patch
Patch2033: glibc-aarch64-tls-fixes.patch
Patch2034: glibc-aarch64-workaround-nzcv-clobber-in-tlsdesc.patch
Patch2035: glibc-new-condvar.patch
# Upstream BZ 18568
Patch2101: glibc-rh1238412-remove-duplicate-transliterations.patch
@ -256,14 +312,28 @@ Patch2103: glibc-rh1238412-update-the-translit-files-to-unicode-7.0.0.patch
Patch2104: glibc-rh1238412-add-translit-rules-for-da-nb-nn-sv-locales.patch
Patch2105: glibc-rh1238412-unicode-8.0.0-update.patch
# Upstream BZ 19573, patch reverts problematic commit
Patch2106: glibc-rh1252570.patch
# Upstream BZ 18665
Patch2107: glibc-CVE-2015-7547.patch
# Upstream BZ 19682
Patch2108: glibc-rh1310168.patch
# Upstream BZ 19581
Patch2109: glibc-rh1114591.patch
##############################################################################
#
# Benchmark comparison patches.
#
##############################################################################
Patch3001: glibc-bench-compare.patch
Patch3002: glibc-bench-build.patch
# Upstream BZ 19048
Patch2035: glibc-rh1276112.patch
##############################################################################
# End of glibc patches.
##############################################################################
@ -584,7 +654,6 @@ microbenchmark tests on the system.
%patch0006 -p1
%patch2007 -p1
%patch0009 -p1
%patch2011 -p1
%patch0012 -p1
%patch2013 -p1
%patch0014 -p1
@ -595,7 +664,6 @@ microbenchmark tests on the system.
%patch2023 -p1
%patch0024 -p1
%patch0025 -p1
%patch2026 -p1
%patch2027 -p1
%patch0028 -p1
%patch0030 -p1
@ -612,19 +680,82 @@ microbenchmark tests on the system.
%patch0047 -p1
%patch2033 -p1
%patch2034 -p1
%patch2035 -p1
%patch0052 -p1
%patch0053 -p1
%patch0054 -p1
%patch0055 -p1 -R
%patch3001 -p1
%patch3002 -p1
%patch2035 -p1
%patch2101 -p1
%patch2102 -p1
%patch2103 -p1
%patch2104 -p1
%patch2105 -p1
%patch2106 -p1
%patch2107 -p1
%patch2108 -p1
%patch2109 -p1
%patch0055 -p1
%patch1000 -p1
%patch1001 -p1
%patch1002 -p1
%patch1003 -p1
%patch1004 -p1
%patch1005 -p1
%patch1006 -p1
%patch1007 -p1
%patch1008 -p1
%patch1009 -p1
%patch1010 -p1
%patch1011 -p1
%patch1012 -p1
%patch1013 -p1
%patch1014 -p1
%patch1015 -p1
%patch1016 -p1
%patch1017 -p1
%patch1018 -p1
%patch1019 -p1
%patch1020 -p1
%patch1021 -p1
%patch1022 -p1
%patch1023 -p1
%patch1024 -p1
%patch1025 -p1
%patch1028 -p1
%patch1029 -p1
%patch1030 -p1
%patch1031 -p1
%patch1032 -p1
%patch1033 -p1
%patch1034 -p1
%patch1035 -p1
%patch1036 -p1
%patch1037 -p1
%patch1038 -p1
%patch1039 -p1
%patch1040 -p1
%patch1041 -p1
%patch1042 -p1
%patch1043 -p1
%patch1044 -p1
%patch1045 -p1
%patch1046 -p1
%patch1047 -p1
%patch1048 -p1
%patch1049 -p1
%patch1050 -p1
%patch1051 -p1
%patch1052 -p1
%patch1053 -p1
%patch1054 -p1
%patch1055 -p1
%patch1056 -p1
%patch1057 -p1
%patch1058 -p1
%patch1059 -p1
%patch1060 -p1
%patch0059 -p1
##############################################################################
# %%prep - Additional prep required...
@ -1035,7 +1166,9 @@ $olddir/build-%{target}/elf/ld.so \
--library-path $olddir/build-%{target}/ \
$olddir/build-%{target}/locale/localedef \
--prefix ${RPM_BUILD_ROOT} --add-to-archive \
*_*
C.utf8 *_*
# Removes all locales except C.utf8 which remains as fallback in
# the event the user cleans the locale-archive using localedef.
rm -rf *_*
mv locale-archive{,.tmpl}
popd
@ -1784,6 +1917,8 @@ rm -f *.filelist*
%files -f common.filelist common
%defattr(-,root,root)
%dir %{_prefix}/lib/locale
%dir %{_prefix}/lib/locale/C.utf8
%{_prefix}/lib/locale/C.utf8/*
%attr(0644,root,root) %verify(not md5 size mtime) %{_prefix}/lib/locale/locale-archive.tmpl
%attr(0644,root,root) %verify(not md5 size mtime mode) %ghost %config(missingok,noreplace) %{_prefix}/lib/locale/locale-archive
%dir %attr(755,root,root) /etc/default
@ -1840,6 +1975,94 @@ rm -f *.filelist*
%endif
%changelog
* Thu Aug 18 2016 Florian Weimer <fweimer@redhat.com> - 2.22-18
- Build time improvements
- Avoid duplicating object files already in libc.a (#1352625)
- malloc: Avoid premature fallback to mmap (#1348620)
- CVE-2016-6323: Backtraces can hang on ARM EABI (32-bit) (swbz#20435)
- Return proper status from _nss_nis_initgroups_dyn (#1294574)
- nss_db: Fix initialization of iteration position (#1344480)
- fopencookie: Mangle function pointers stored on the heap (swbz#20222)
- argp: Do not override GCC keywords with macros (#1366830)
* Thu Jun 2 2016 Florian Weimer <fweimer@redhat.com> - 2.22-17
- CVE-2016-4429: stack overflow in Sun RPC clntudp_call (#1337140)
- Fix fork redirection in libpthread (#1326903)
- struct sockaddr_storage GCC 6 enablement (#1337291)
* Wed May 11 2016 Florian Weimer <fweimer@redhat.com> - 2.22-16
- Back out dlsym (RTLD_NEXT)/dlerror change (#1333945)
because it reveals an ASAN bug (#1335011)
- CVE-2016-3706: stack overflow in getaddrinfo hostent conversion (#1330888)
- Fix first day of week of the fr_CH, it_CH locales (#1204521)
- Fix first day of week of the hr_HR locale (#1282011)
* Sat May 7 2016 Florian Weimer <fweimer@redhat.com> - 2.22-15
- Change first day of the week for es_CL to Monday (#1321372)
- CVE-2015-8779: unbounded stack allocation in catopen (#1300314)
- CVE-2014-9761: unbounded stack allocation in nan* functions (#1300311)
- Fix invalid memory access in getmntent_r (#1293139)
- CVE-2015-8776: crash with invalid data in strftime (#1300300)
- CVE-2015-8778: integer overflow in hcreate and hcreate_r (#1300304)
- Fix strfmon_l to use the locale object for grouping (#1307234)
- Fix tst-makecontext on armhfp (#1288740)
* Fri May 6 2016 Florian Weimer <fweimer@redhat.com> - 2.22-14
- Fix getnameinfo memory leak and incorrect truncation (#1333901)
- CVE-2016-1234: buffer overflow in glob with GLOB_ALTDIRFUNC (#1315648)
- Set dlerror after dlsym (RTLD_NEXT) failure (#1333945)
- Fix deadlock between between fflush, getdelim, and fork (#1332917)
* Fri May 6 2016 Florian Weimer <fweimer@redhat.com> - 2.22-13
- Avoid build failure in TZ tests (#1333940)
* Fri May 6 2016 Florian Weimer <fweimer@redhat.com> - 2.22-12
- Fix heap-based buffer overflow in get_txt_records (#1332912)
- CVE-2016-3075: Stack overflow in _nss_dns_getnetbyname_r (#1321954)
- April 2016 nss_dns hardening (#1332914)
- Fix elf/tst-audit10 and elf/tst-audit4 failures (#1313404)
- nss_db: Fix handling of long entries (#1321861)
- resolv: Fix NULL pointer dereference with unconnectable address (#1316972)
* Wed Mar 02 2016 Mike FABIAN <mfabian@redhat.com> - 2.22-11
- Add the C.UTF-8 locale
* Fri Feb 19 2016 Florian Weimer <fweimer@redhat.com> - 2.22-10
- Fix socket system call selection on s390x (#1310168).
- Remove stray newline from Serbian locales (#1114591).
* Tue Feb 16 2016 Florian Weimer <fweimer@redhat.com> - 2.22-9
- CVE-2015-7547: Stack-based buffer overflow in getaddrinfo (#1308943).
* Mon Feb 15 2016 Florian Weimer <fweimer@redhat.com> - 2.22-8
- Revert upstream commit 2212c1420c92a33b0e0bd9a34938c9814a56c0f7 (#1252570).
* Mon Jan 4 2016 Florian Weimer <fweimer@redhat.com> - 2.22-7
- Update glibc-rh1276112.patch to include backports to fix
upstream bugs 19243 and 19182. (#1295189)
* Sat Dec 5 2015 Florian Weimer <fweimer@redhat.com> - 2.22-6
- Re-enable large file support in openat. (#1288662)
- Apply additional pointer guard hardening. (#1276761)
* Mon Nov 9 2015 Carlos O'Donell <carlos@redhat.com> - 2.22-5
- Remove invalid strcoll optimization (#1276711).
* Fri Oct 30 2015 Florian Weimer <fweimer@redhat.com> - 2.22-4
- Prevent malloc arena free list from becoming cyclic. (#1276112)
* Wed Sep 16 2015 Mike FABIAN <mfabian@redhat.com> - 2.22-3
- build-locale-archive sometimes created empty archives (fixed by David Shea) (#1262040)
* Fri Aug 14 2015 Siddhesh Poyarekar <siddhesh@redhat.com> - 2.22-2
- Remove initgroups from default nsswitch.conf (#751450).
* Tue Jul 28 2015 Siddhesh Poyarekar <siddhesh@redhat.com> - 2.21.90-21
- Auto-sync with upstream master.
* Mon Jul 27 2015 Siddhesh Poyarekar <siddhesh@redhat.com> - 2.12.90-20
- Back out new condvar implementation.
* Thu Jul 23 2015 Mike FABIAN <mfabian@redhat.com> - 2.21.90-19
- some more additions to the translit_neutral file by Marko Myllynen

View File

@ -33,7 +33,6 @@
passwd: files sss
shadow: files sss
group: files sss
initgroups: files
#hosts: db files nisplus nis dns
hosts: files dns

View File

@ -4,8 +4,17 @@ export QUILT_PATCHES=$PWD
# Extract source file name from sources file,
# and assume it's the same name as the directory.
source=`cat sources | sed -e 's,^.* ,,g'`
tar zxvf $source
srcdir=${source%.tar.gz}
if [ "$1" == "-f" ] && [ -d "$srcdir" ]; then
echo Cleaning up $srcdir
rm -rf $srcdir
fi
if [ -d "$srcdir" ]; then
# Don't overwrite existing source directory.
echo "ERROR: Source directory $srcdir already exists. Use -f to force cleanup step."
exit 1
fi
tar zxvf $source
echo "Entering $srcdir"
pushd $srcdir
# Apply all patches.

44
series
View File

@ -1,44 +0,0 @@
glibc-rtkaio.patch -p1
glibc-c_stubs.patch -p1
glibc-fedora-nscd.patch -p1
glibc-fedora-ldd.patch -p1
glibc-fedora-ppc-unwind.patch -p1
glibc-rh825061.patch -p1
glibc-arm-hardfloat-3.patch -p1
glibc-rh697421.patch -p1
glibc-fedora-include-bits-ldbl.patch -p1
glibc-rh757881.patch -p1
glibc-fedora-linux-tcsetattr.patch -p1
glibc-rh741105.patch -p1
glibc-fedora-nptl-linklibc.patch -p1
glibc-fedora-localedef.patch -p1
glibc-fedora-i386-tls-direct-seg-refs.patch -p1
glibc-fedora-nis-rh188246.patch -p1
glibc-fedora-manual-dircategory.patch -p1
glibc-rh827510.patch -p1
glibc-fedora-locarchive.patch -p1
glibc-fedora-streams-rh436349.patch -p1
glibc-rh841787.patch -p1
glibc-rh819430.patch -p1
glibc-fedora-localedata-rh61908.patch -p1
glibc-fedora-uname-getrlimit.patch -p1
glibc-fedora-__libc_multiple_libcs.patch -p1
glibc-fedora-elf-ORIGIN.patch -p1
glibc-fedora-elf-init-hidden_undef.patch -p1
glibc-rh952799.patch -p1
glibc-rh731833-rtkaio.patch -p1
glibc-rh731833-rtkaio-2.patch -p1
glibc-rh970865.patch -p1
glibc-rh1009145.patch -p1
glibc-rh1013801.patch -p1
glibc-rh1070416.patch -p1
glibc-nscd-sysconfig.patch -p1
glibc-aarch64-tls-fixes.patch -p1
glibc-aarch64-workaround-nzcv-clobber-in-tlsdesc.patch -p1
glibc-disable-rwlock-elision.patch -p1
glibc-cs-path.patch -p1
glibc-rtkaio-clock.patch -p1
glibc-revert-arena-threshold-fix.patch -p1 -R
glibc-bench-compare.patch -p1
glibc-bench-build.patch -p1
glibc-new-condvar.patch -p1

View File

@ -1 +1 @@
ab8cde6d7c2bb3cfc9da616fb5cf2323 glibc-2.21-357-gb40a4e1.tar.gz
91dcaa30870c1ce5c9974c49c3af03eb glibc-2.22.tar.gz