Compare commits
55 Commits
Author | SHA1 | Date |
---|---|---|
Florian Weimer | 60b8a73579 | |
Florian Weimer | 80acfa27b0 | |
Florian Weimer | fe01d7c362 | |
Florian Weimer | 18df09c331 | |
Florian Weimer | 371b5ecb70 | |
Florian Weimer | b256ca9b8a | |
Florian Weimer | 37bc92a77f | |
Florian Weimer | b9da92483d | |
Florian Weimer | 9b47092236 | |
Florian Weimer | 7a43147883 | |
Florian Weimer | 2d5168f40a | |
Florian Weimer | 0b01e9c2eb | |
Florian Weimer | 6edf83c63d | |
Florian Weimer | 76672943a2 | |
Florian Weimer | d7fc7c363e | |
Florian Weimer | 10fdc4382b | |
Florian Weimer | 55dbe293ce | |
Florian Weimer | 0ad6e19e8d | |
Florian Weimer | a5d8db31b4 | |
Florian Weimer | 9f4a81eb45 | |
Florian Weimer | 15f7423992 | |
Florian Weimer | 421842aad7 | |
Florian Weimer | 327133fe22 | |
Florian Weimer | e97f134cc1 | |
Florian Weimer | c3f1918b6c | |
Florian Weimer | 53d6baa069 | |
Florian Weimer | 6ca2fbefbe | |
Florian Weimer | 4c57cf5cfa | |
Florian Weimer | 8ef83de907 | |
Florian Weimer | d277a9bbcd | |
Florian Weimer | 84517e1bc0 | |
Florian Weimer | 79cd021451 | |
Florian Weimer | 217d136f41 | |
Florian Weimer | 116e17a138 | |
Florian Weimer | 6702e0c88e | |
Florian Weimer | bea7fc560d | |
Florian Weimer | 62f2d369c8 | |
Mike FABIAN | dd028df7c1 | |
Florian Weimer | 431c99df4c | |
Florian Weimer | 6136c09c1e | |
Florian Weimer | e8497bf411 | |
Florian Weimer | 9f1734eb6c | |
Florian Weimer | 73fbe412ea | |
Florian Weimer | 74847c75cc | |
Florian Weimer | 67d13737ec | |
Florian Weimer | e8f4ba5ab2 | |
Jaromir Capik | 6f2d4738ab | |
Carlos O'Donell | 7a808bcd62 | |
Jaromir Capik | 37137eb3e4 | |
Florian Weimer | 6fbf955dad | |
Mike FABIAN | 26f4d28240 | |
Siddhesh Poyarekar | a0be169239 | |
Siddhesh Poyarekar | 07e6287dc2 | |
Siddhesh Poyarekar | 9af85e62a6 | |
Siddhesh Poyarekar | c2535df93e |
17
STAGE1-glibc
17
STAGE1-glibc
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
@ -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"
|
|
@ -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
|
@ -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. */
|
|
@ -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
|
||||
|
|
|
@ -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;
|
|
@ -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))
|
|
@ -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;
|
|
@ -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
|
|
@ -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
|
|
@ -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 */
|
|
@ -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"
|
|
@ -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
|
|
@ -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)
|
|
@ -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"
|
|
@ -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
|
|
@ -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
|
|
@ -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)
|
|
@ -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.
|
|
@ -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;
|
|
@ -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)
|
|
@ -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 ()
|
|
@ -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;
|
|
@ -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;
|
|
@ -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);
|
|
@ -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);
|
||||
|
|
@ -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"
|
|
@ -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"
|
|
@ -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
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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"
|
|
@ -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)
|
|
@ -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
|
|
@ -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"
|
|
@ -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);
|
||||
|
|
@ -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
|
|
@ -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;
|
|
@ -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
|
||||
|
|
@ -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)) {
|
||||
/*
|
|
@ -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 ();
|
|
@ -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
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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)
|
||||
{
|
|
@ -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
|
|
@ -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
|
|
@ -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;
|
||||
}
|
|
@ -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:
|
|
@ -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;
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
|
@ -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)
|
|
@ -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 */
|
||||
|
|
@ -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 ();
|
||||
|
|
@ -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 ------------------ */
|
||||
|
|
@ -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)
|
|
@ -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 */
|
|
@ -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)
|
|
@ -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)
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -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
|
|
@ -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 */
|
|
@ -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)
|
||||
{
|
|
@ -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);
|
|
@ -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
|
|
@ -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 */
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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 */
|
|
@ -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++;
|
|
@ -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
|
|
@ -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;
|
||||
}
|
|
@ -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
|
261
glibc.spec
261
glibc.spec
|
@ -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
|
||||
|
||||
|
|
|
@ -33,7 +33,6 @@
|
|||
passwd: files sss
|
||||
shadow: files sss
|
||||
group: files sss
|
||||
initgroups: files
|
||||
|
||||
#hosts: db files nisplus nis dns
|
||||
hosts: files dns
|
||||
|
|
|
@ -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
44
series
|
@ -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
|
Loading…
Reference in New Issue