mirror of
git://sourceware.org/git/glibc.git
synced 2026-09-09 11:58:23 +08:00
Compare commits
129
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
70ae2309a8 | ||
|
|
49a0c33ead | ||
|
|
d8b6b33f1d | ||
|
|
42a2c81226 | ||
|
|
3790ec0ca5 | ||
|
|
15a05fafa4 | ||
|
|
017d97cd2e | ||
|
|
436359fd41 | ||
|
|
407ec87626 | ||
|
|
d2450a97c3 | ||
|
|
c64d6bc3da | ||
|
|
d9c54360ca | ||
|
|
f87adbcaa4 | ||
|
|
21c5d14bfb | ||
|
|
9d0aec2368 | ||
|
|
89dc0372bb | ||
|
|
1be1845b28 | ||
|
|
e28b4381b0 | ||
|
|
771fb81f98 | ||
|
|
a4c507f0eb | ||
|
|
264856cfcd | ||
|
|
35c185d103 | ||
|
|
f47319aa87 | ||
|
|
f502fe6847 | ||
|
|
5976a49e6a | ||
|
|
e07eca6a72 | ||
|
|
718da076cb | ||
|
|
0d6895748b | ||
|
|
240ceafed7 | ||
|
|
809cde4a64 | ||
|
|
a8c871a871 | ||
|
|
a85abfa922 | ||
|
|
60022fbfba | ||
|
|
21ed68033a | ||
|
|
b2c32b05c6 | ||
|
|
4b59550ead | ||
|
|
19e9aaec52 | ||
|
|
65ecfefc66 | ||
|
|
cf3a189a07 | ||
|
|
6c45453cd5 | ||
|
|
bfb83ebd8f | ||
|
|
ee55e3c8fb | ||
|
|
b5714a32f8 | ||
|
|
861a383598 | ||
|
|
a79b262c1e | ||
|
|
444fb8c27d | ||
|
|
a64be6fb2f | ||
|
|
ccc3d71b28 | ||
|
|
9d4fe83c8c | ||
|
|
46329bea58 | ||
|
|
d14837f6ed | ||
|
|
f95984beb2 | ||
|
|
13a601a0df | ||
|
|
eb8c932bac | ||
|
|
00cd4dad17 | ||
|
|
c252c193e2 | ||
|
|
fb336c7471 | ||
|
|
5b4aa65a48 | ||
|
|
c833c617a6 | ||
|
|
30fa323f82 | ||
|
|
f664b66311 | ||
|
|
e2c17de539 | ||
|
|
ab753f625e | ||
|
|
a07df04187 | ||
|
|
740e642e32 | ||
|
|
5fc92dc17d | ||
|
|
942c502aca | ||
|
|
d87bf6412b | ||
|
|
0f0060399a | ||
|
|
fc58942b39 | ||
|
|
883dceebc8 | ||
|
|
5a1a5f0dd2 | ||
|
|
de905d1487 | ||
|
|
e5d560e0e7 | ||
|
|
2b8ab5c3f6 | ||
|
|
c95a56e2a8 | ||
|
|
d6778fc4b0 | ||
|
|
425c48c217 | ||
|
|
21ab483c6a | ||
|
|
3237210aa6 | ||
|
|
7ef1870646 | ||
|
|
a33d347c18 | ||
|
|
3803874b4a | ||
|
|
b995d95a59 | ||
|
|
4660fb2714 | ||
|
|
287de30e17 | ||
|
|
43f189b003 | ||
|
|
a73a62562a | ||
|
|
7ad78f8698 | ||
|
|
c6d1664014 | ||
|
|
7a5d312963 | ||
|
|
795b5d3658 | ||
|
|
0c5f5b2339 | ||
|
|
3b54d91180 | ||
|
|
ec54e4f7c2 | ||
|
|
cd51b14244 | ||
|
|
13ff0739fd | ||
|
|
060f8dbd0c | ||
|
|
af822b45a6 | ||
|
|
a7e6fd7d41 | ||
|
|
f0489b8314 | ||
|
|
3cdd4ce75b | ||
|
|
387011e0b6 | ||
|
|
7d605623b1 | ||
|
|
5b319ce294 | ||
|
|
5fb7924cb6 | ||
|
|
dc22a1ec15 | ||
|
|
2b529a82af | ||
|
|
c0769d60c1 | ||
|
|
ed7f3a2e27 | ||
|
|
6c84109cfa | ||
|
|
666bb4dc55 | ||
|
|
38810947f9 | ||
|
|
1abe050526 | ||
|
|
5c8c312365 | ||
|
|
36c6e27a26 | ||
|
|
3007f797a1 | ||
|
|
a0a9f8d957 | ||
|
|
7d9fd6a5a1 | ||
|
|
c146a4a740 | ||
|
|
64c2534571 | ||
|
|
9031106ea0 | ||
|
|
a34d1c6afc | ||
|
|
561a9f11a9 | ||
|
|
19742d3d5f | ||
|
|
8415fb8d4f | ||
|
|
3fd69b2634 | ||
|
|
f903b287fe | ||
|
|
ee2ff82cba |
+12
-3
@@ -395,6 +395,9 @@ ifndef after-link
|
||||
after-link =
|
||||
endif
|
||||
|
||||
# Additional libraries to link into every test.
|
||||
link-extra-libs-tests = $(libsupport)
|
||||
|
||||
# Command for linking PIE programs with the C library.
|
||||
ifndef +link-pie
|
||||
+link-pie-before-libc = $(CC) -pie -Wl,-O1 -nostdlib -nostartfiles -o $@ \
|
||||
@@ -504,7 +507,7 @@ link-libc = $(link-libc-rpath-link) $(link-libc-before-gnulib) $(gnulib)
|
||||
link-libc-tests = $(link-libc-tests-rpath-link) \
|
||||
$(link-libc-before-gnulib) $(gnulib-tests)
|
||||
# This is how to find at build-time things that will be installed there.
|
||||
rpath-dirs = math elf dlfcn nss nis rt resolv crypt mathvec
|
||||
rpath-dirs = math elf dlfcn nss nis rt resolv crypt mathvec support
|
||||
rpath-link = \
|
||||
$(common-objdir):$(subst $(empty) ,:,$(patsubst ../$(subdir),.,$(rpath-dirs:%=$(common-objpfx)%)))
|
||||
else
|
||||
@@ -851,7 +854,7 @@ libio-include = -I$(..)libio
|
||||
# List of non-library modules that we build.
|
||||
built-modules = iconvprogs iconvdata ldconfig lddlibc4 libmemusage \
|
||||
libSegFault libpcprofile librpcsvc locale-programs \
|
||||
memusagestat nonlib nscd extramodules libnldbl
|
||||
memusagestat nonlib nscd extramodules libnldbl libsupport
|
||||
|
||||
in-module = $(subst -,_,$(firstword $(libof-$(basename $(@F))) \
|
||||
$(libof-$(<F)) \
|
||||
@@ -1089,6 +1092,12 @@ libm = $(common-objpfx)math/libm.a
|
||||
libmvec = $(common-objpfx)mathvec/libmvec.a
|
||||
endif
|
||||
|
||||
ifeq ($(build-shared),yes)
|
||||
libsupport = $(common-objpfx)support/libsupport_nonshared.a
|
||||
else
|
||||
libsupport = $(common-objpfx)support/libsupport.a
|
||||
endif
|
||||
|
||||
# These are the subdirectories containing the library source. The order
|
||||
# is more or less arbitrary. The sorting step will take care of the
|
||||
# dependencies.
|
||||
@@ -1096,7 +1105,7 @@ all-subdirs = csu assert ctype locale intl catgets math setjmp signal \
|
||||
stdlib stdio-common libio malloc string wcsmbs time dirent \
|
||||
grp pwd posix io termios resource misc socket sysvipc gmon \
|
||||
gnulib iconv iconvdata wctype manual shadow gshadow po argp \
|
||||
crypt localedata timezone rt conform debug mathvec \
|
||||
crypt localedata timezone rt conform debug mathvec support \
|
||||
$(add-on-subdirs) dlfcn elf
|
||||
|
||||
ifndef avoid-generated
|
||||
|
||||
@@ -4,6 +4,106 @@ See the end for copying conditions.
|
||||
|
||||
Please send GNU C library bug reports via <http://sourceware.org/bugzilla/>
|
||||
using `glibc' in the "product" field.
|
||||
|
||||
Version 2.22.1
|
||||
|
||||
* On ARM EABI (32-bit), generating a backtrace for execution contexts which
|
||||
have been created with makecontext could fail to terminate due to a
|
||||
missing .cantunwind annotation. This has been observed to lead to a hang
|
||||
(denial of service) in some Go applications compiled with gccgo. Reported
|
||||
by Andreas Schwab. (CVE-2016-6323)
|
||||
|
||||
* A stack-based buffer overflow was found in libresolv when invoked from
|
||||
libnss_dns, allowing specially crafted DNS responses to seize control
|
||||
of execution flow in the DNS client. The buffer overflow occurs in
|
||||
the functions send_dg (send datagram) and send_vc (send TCP) for the
|
||||
NSS module libnss_dns.so.2 when calling getaddrinfo with AF_UNSPEC
|
||||
family. The use of AF_UNSPEC triggers the low-level resolver code to
|
||||
send out two parallel queries for A and AAAA. A mismanagement of the
|
||||
buffers used for those queries could result in the response of a query
|
||||
writing beyond the alloca allocated buffer created by
|
||||
_nss_dns_gethostbyname4_r. Buffer management is simplified to remove
|
||||
the overflow. Thanks to the Google Security Team and Red Hat for
|
||||
reporting the security impact of this issue, and Robert Holiday of
|
||||
Ciena for reporting the related bug 18665. (CVE-2015-7547)
|
||||
|
||||
* The following bugs are resolved with this release:
|
||||
|
||||
17905, 18420, 18421, 18480, 18589, 18743, 18778, 18781, 18787, 18796,
|
||||
18870, 18887, 18921, 18928, 18969, 18985, 19003, 19018, 19048, 19058,
|
||||
19174, 19178, 19182, 19243, 19573, 19590, 19682, 19791, 19822, 19853,
|
||||
19879, 19779, 20010, 20112, 20277.
|
||||
|
||||
* The getnetbyname implementation in nss_dns had a potentially unbounded
|
||||
alloca call (in the form of a call to strdupa), leading to a stack
|
||||
overflow (stack exhaustion) and a crash if getnetbyname is invoked
|
||||
on a very long name. (CVE-2016-3075)
|
||||
|
||||
* The LD_POINTER_GUARD environment variable can no longer be used to
|
||||
disable the pointer guard feature. It is always enabled.
|
||||
|
||||
* A defect in the malloc implementation, present since glibc 2.15 (2012) or
|
||||
glibc 2.10 via --enable-experimental-malloc (2009), could result in the
|
||||
unnecessary serialization of memory allocation requests across threads.
|
||||
The defect is now corrected. Users should see a substantial increase in
|
||||
the concurent throughput of allocation requests for applications which
|
||||
trigger this bug. Affected applications typically create create and
|
||||
destroy threads frequently. (Bug 19048 was reported and analyzed by
|
||||
Ericsson.)
|
||||
|
||||
* The glob function suffered from a stack-based buffer overflow when it was
|
||||
called with the GLOB_ALTDIRFUNC flag and encountered a long file name.
|
||||
Reported by Alexander Cherepanov. (CVE-2016-1234)
|
||||
|
||||
* Previously, getaddrinfo copied large amounts of address data to the stack,
|
||||
even after the fix for CVE-2013-4458 has been applied, potentially
|
||||
resulting in a stack overflow. getaddrinfo now uses a heap allocation
|
||||
instead. Reported by Michael Petlan. (CVE-2016-3706)
|
||||
|
||||
* The Sun RPC UDP client could exhaust all available stack space when
|
||||
flooded with crafted ICMP and UDP messages. Reported by Aldy Hernandez'
|
||||
alloca plugin for GCC. (CVE-2016-4429)
|
||||
|
||||
* A use-after-free vulnerability in clntudp_call in the Sun RPC system has been
|
||||
fixed (CVE-2017-12133).
|
||||
|
||||
* CVE-2017-16997: Incorrect handling of RPATH or RUNPATH containing $ORIGIN
|
||||
for AT_SECURE or SUID binaries could be used to load libraries from the
|
||||
current directory.
|
||||
|
||||
* CVE-2017-1000409: Buffer overflow in _dl_init_paths due to miscomputation
|
||||
of the number of search path components. (This is not a security
|
||||
vulnerability per se because no trust boundary is crossed if the fix for
|
||||
CVE-2017-1000366 has been applied, but it is mentioned here only because
|
||||
of the CVE assignment.) Reported by Qualys.
|
||||
|
||||
* CVE-2017-1000408: Incorrect array size computation in _dl_init_paths leads
|
||||
to the allocation of too much memory. (This is not a security bug per se,
|
||||
it is mentioned here only because of the CVE assignment.) Reported by
|
||||
Qualys.
|
||||
|
||||
* CVE-2009-5064: The ldd script would sometimes run the program under
|
||||
examination directly, without preventing code execution through the
|
||||
dynamic linker. (The glibc project disputes that this is a security
|
||||
vulnerability; only trusted binaries must be examined using the ldd
|
||||
script.)
|
||||
|
||||
* CVE-2018-6485: The posix_memalign and memalign functions, when called with
|
||||
an object size near the value of SIZE_MAX, would return a pointer to a
|
||||
buffer which is too small, instead of NULL. Reported by Jakub Wilk.
|
||||
|
||||
* CVE-2018-6551: The malloc function, when called with an object size near
|
||||
the value of SIZE_MAX, would return a pointer to a buffer which is too
|
||||
small, instead of NULL.
|
||||
|
||||
* CVE-2017-15670: The glob function, when invoked with GLOB_TILDE, suffered
|
||||
from a one-byte overflow during ~ operator processing (either on the stack
|
||||
or the heap, depending on the length of the user name).
|
||||
|
||||
* CVE-2017-15804: The glob function, when invoked with GLOB_TILDE and without
|
||||
GLOB_NOESCAPE, could write past the end of a buffer while
|
||||
unescaping user names. Reported by Tim Rühsen.
|
||||
|
||||
|
||||
Version 2.22
|
||||
|
||||
@@ -84,7 +184,7 @@ Version 2.22
|
||||
release. Use of this header will trigger a deprecation warning.
|
||||
Application developers should update their code to use <regex.h> instead.
|
||||
|
||||
This header was formerly part of SUSv2, but was deprecated in 1997 and
|
||||
This header was formerly part of SUS, but was deprecated in 1994 and
|
||||
removed from the standard in 2001. Also, the glibc implementation
|
||||
leaks memory. See BZ#18681 for more details.
|
||||
|
||||
|
||||
@@ -149,6 +149,7 @@ endif
|
||||
|
||||
ifneq "$(strip $(binaries-shared-tests))" ""
|
||||
$(addprefix $(objpfx),$(binaries-shared-tests)): %: %.o \
|
||||
$(link-extra-libs-tests) \
|
||||
$(sort $(filter $(common-objpfx)lib%,$(link-libc))) \
|
||||
$(addprefix $(csu-objpfx),start.o) $(+preinit) $(+postinit)
|
||||
$(+link-tests)
|
||||
@@ -156,6 +157,7 @@ endif
|
||||
|
||||
ifneq "$(strip $(binaries-pie-tests))" ""
|
||||
$(addprefix $(objpfx),$(binaries-pie-tests)): %: %.o \
|
||||
$(link-extra-libs-tests) \
|
||||
$(sort $(filter $(common-objpfx)lib%,$(link-libc))) \
|
||||
$(addprefix $(csu-objpfx),start.o) $(+preinit) $(+postinit)
|
||||
$(+link-pie-tests)
|
||||
@@ -177,6 +179,7 @@ endif
|
||||
|
||||
ifneq "$(strip $(binaries-static-tests))" ""
|
||||
$(addprefix $(objpfx),$(binaries-static-tests)): %: %.o \
|
||||
$(link-extra-libs-tests) \
|
||||
$(sort $(filter $(common-objpfx)lib%,$(link-libc-static-tests))) \
|
||||
$(addprefix $(csu-objpfx),start.o) $(+preinit) $(+postinit)
|
||||
$(+link-static-tests)
|
||||
|
||||
+4
-15
@@ -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 */
|
||||
|
||||
+2
-40
@@ -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 */
|
||||
|
||||
+8
-1
@@ -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
|
||||
|
||||
+12
-7
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
+14
-9
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -91,6 +91,9 @@
|
||||
/* Define if assembler supports AVX512. */
|
||||
#undef HAVE_AVX512_ASM_SUPPORT
|
||||
|
||||
/* Define if assembler supports vector instructions on S390. */
|
||||
#undef HAVE_S390_VX_ASM_SUPPORT
|
||||
|
||||
/* Define if assembler supports Intel MPX. */
|
||||
#undef HAVE_MPX_SUPPORT
|
||||
|
||||
|
||||
@@ -51,6 +51,7 @@ have-z-combreloc = @libc_cv_z_combreloc@
|
||||
have-z-execstack = @libc_cv_z_execstack@
|
||||
have-Bgroup = @libc_cv_Bgroup@
|
||||
have-protected-data = @libc_cv_protected_data@
|
||||
have-glob-dat-reloc = @libc_cv_has_glob_dat@
|
||||
with-fp = @with_fp@
|
||||
old-glibc-headers = @old_glibc_headers@
|
||||
unwind-find-fde = @libc_cv_gcc_unwind_find_fde@
|
||||
|
||||
@@ -628,6 +628,7 @@ gnu89_inline
|
||||
libc_cv_ssp
|
||||
fno_unit_at_a_time
|
||||
libc_cv_output_format
|
||||
libc_cv_has_glob_dat
|
||||
libc_cv_hashstyle
|
||||
libc_cv_fpie
|
||||
libc_cv_z_execstack
|
||||
@@ -6335,6 +6336,39 @@ $as_echo "$libc_cv_use_default_link" >&6; }
|
||||
use_default_link=$libc_cv_use_default_link
|
||||
fi
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GLOB_DAT reloc" >&5
|
||||
$as_echo_n "checking for GLOB_DAT reloc... " >&6; }
|
||||
if ${libc_cv_has_glob_dat+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
cat > conftest.c <<EOF
|
||||
extern int mumble;
|
||||
int foo (void) { return mumble; }
|
||||
EOF
|
||||
if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS
|
||||
-fPIC -shared -o conftest.so conftest.c
|
||||
-nostdlib -nostartfiles
|
||||
1>&5'
|
||||
{ { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
|
||||
(eval $ac_try) 2>&5
|
||||
ac_status=$?
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
|
||||
test $ac_status = 0; }; }
|
||||
then
|
||||
if $READELF -rW conftest.so | grep '_GLOB_DAT' > /dev/null; then
|
||||
libc_cv_has_glob_dat=yes
|
||||
else
|
||||
libc_cv_has_glob_dat=no
|
||||
fi
|
||||
else
|
||||
libc_cv_has_glob_dat=no
|
||||
fi
|
||||
rm -f conftest*
|
||||
fi
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_has_glob_dat" >&5
|
||||
$as_echo "$libc_cv_has_glob_dat" >&6; }
|
||||
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking linker output format" >&5
|
||||
$as_echo_n "checking linker output format... " >&6; }
|
||||
if ${libc_cv_output_format+:} false; then :
|
||||
|
||||
@@ -1535,6 +1535,29 @@ $ac_try"
|
||||
use_default_link=$libc_cv_use_default_link
|
||||
fi
|
||||
|
||||
AC_CACHE_CHECK(for GLOB_DAT reloc,
|
||||
libc_cv_has_glob_dat, [dnl
|
||||
cat > conftest.c <<EOF
|
||||
extern int mumble;
|
||||
int foo (void) { return mumble; }
|
||||
EOF
|
||||
if AC_TRY_COMMAND([${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS
|
||||
-fPIC -shared -o conftest.so conftest.c
|
||||
-nostdlib -nostartfiles
|
||||
1>&AS_MESSAGE_LOG_FD])
|
||||
then
|
||||
dnl look for GLOB_DAT relocation.
|
||||
if $READELF -rW conftest.so | grep '_GLOB_DAT' > /dev/null; then
|
||||
libc_cv_has_glob_dat=yes
|
||||
else
|
||||
libc_cv_has_glob_dat=no
|
||||
fi
|
||||
else
|
||||
libc_cv_has_glob_dat=no
|
||||
fi
|
||||
rm -f conftest*])
|
||||
AC_SUBST(libc_cv_has_glob_dat)
|
||||
|
||||
AC_CACHE_CHECK(linker output format, libc_cv_output_format, [dnl
|
||||
if libc_cv_output_format=`
|
||||
${CC-cc} -nostartfiles -nostdlib -Wl,--print-output-format 2>&AS_MESSAGE_LOG_FD`
|
||||
|
||||
+26
-2
@@ -148,7 +148,8 @@ tests += loadtest restest1 preloadtest loadfail multiload origtest resolvfail \
|
||||
tst-unique1 tst-unique2 $(if $(CXX),tst-unique3 tst-unique4 \
|
||||
tst-nodelete) \
|
||||
tst-initorder tst-initorder2 tst-relsort1 tst-null-argv \
|
||||
tst-ptrguard1 tst-tlsalign tst-tlsalign-extern tst-nodelete-opened
|
||||
tst-ptrguard1 tst-tlsalign tst-tlsalign-extern tst-nodelete-opened \
|
||||
tst-nodelete2
|
||||
# reldep9
|
||||
ifeq ($(build-hardcoded-path-in-tests),yes)
|
||||
tests += tst-dlopen-aout
|
||||
@@ -218,7 +219,7 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \
|
||||
tst-initorder2d \
|
||||
tst-relsort1mod1 tst-relsort1mod2 tst-array2dep \
|
||||
tst-array5dep tst-null-argv-lib \
|
||||
tst-tlsalign-lib tst-nodelete-opened-lib
|
||||
tst-tlsalign-lib tst-nodelete-opened-lib tst-nodelete2mod
|
||||
ifeq (yes,$(have-protected-data))
|
||||
modules-names += tst-protected1moda tst-protected1modb
|
||||
tests += tst-protected1a tst-protected1b
|
||||
@@ -292,6 +293,13 @@ check-abi: $(objpfx)check-abi-ld.out
|
||||
tests-special += $(objpfx)check-abi-ld.out
|
||||
update-abi: update-abi-ld
|
||||
|
||||
ifeq ($(have-glob-dat-reloc),yes)
|
||||
tests += tst-prelink
|
||||
ifeq ($(run-built-tests),yes)
|
||||
tests-special += $(objpfx)tst-prelink-cmp.out
|
||||
endif
|
||||
endif
|
||||
|
||||
include ../Rules
|
||||
|
||||
ifeq (yes,$(build-shared))
|
||||
@@ -594,6 +602,7 @@ tst-auditmod9b.so-no-z-defs = yes
|
||||
tst-nodelete-uniquemod.so-no-z-defs = yes
|
||||
tst-nodelete-rtldmod.so-no-z-defs = yes
|
||||
tst-nodelete-zmod.so-no-z-defs = yes
|
||||
tst-nodelete2mod.so-no-z-defs = yes
|
||||
|
||||
ifeq ($(build-shared),yes)
|
||||
# Build all the modules even when not actually running test programs.
|
||||
@@ -1164,6 +1173,11 @@ $(objpfx)tst-nodelete.out: $(objpfx)tst-nodelete-uniquemod.so \
|
||||
LDFLAGS-tst-nodelete = -rdynamic
|
||||
LDFLAGS-tst-nodelete-zmod.so = -Wl,--enable-new-dtags,-z,nodelete
|
||||
|
||||
$(objpfx)tst-nodelete2: $(libdl)
|
||||
$(objpfx)tst-nodelete2.out: $(objpfx)tst-nodelete2mod.so
|
||||
|
||||
LDFLAGS-tst-nodelete2 = -rdynamic
|
||||
|
||||
$(objpfx)tst-initorder-cmp.out: tst-initorder.exp $(objpfx)tst-initorder.out
|
||||
cmp $^ > $@; \
|
||||
$(evaluate-test)
|
||||
@@ -1205,3 +1219,13 @@ $(objpfx)tst-unused-dep.out: $(objpfx)testobj1.so
|
||||
$(objpfx)tst-unused-dep-cmp.out: $(objpfx)tst-unused-dep.out
|
||||
cmp $< /dev/null > $@; \
|
||||
$(evaluate-test)
|
||||
|
||||
tst-prelink-ENV = LD_TRACE_PRELINKING=1
|
||||
|
||||
$(objpfx)tst-prelink-conflict.out: $(objpfx)tst-prelink.out
|
||||
grep stdout $< | grep conflict | $(AWK) '{ print $$10, $$11 }' > $@
|
||||
|
||||
$(objpfx)tst-prelink-cmp.out: tst-prelink.exp \
|
||||
$(objpfx)tst-prelink-conflict.out
|
||||
cmp $^ > $@; \
|
||||
$(evaluate-test)
|
||||
|
||||
+8
-7
@@ -144,6 +144,14 @@ _dl_close_worker (struct link_map *map, bool force)
|
||||
char done[nloaded];
|
||||
struct link_map *maps[nloaded];
|
||||
|
||||
/* Clear DF_1_NODELETE to force object deletion. We don't need to touch
|
||||
l_tls_dtor_count because forced object deletion only happens when an
|
||||
error occurs during object load. Destructor registration for TLS
|
||||
non-POD objects should not have happened till then for this
|
||||
object. */
|
||||
if (force)
|
||||
map->l_flags_1 &= ~DF_1_NODELETE;
|
||||
|
||||
/* Run over the list and assign indexes to the link maps and enter
|
||||
them into the MAPS array. */
|
||||
int idx = 0;
|
||||
@@ -153,13 +161,6 @@ _dl_close_worker (struct link_map *map, bool force)
|
||||
maps[idx] = l;
|
||||
++idx;
|
||||
|
||||
/* Clear DF_1_NODELETE to force object deletion. We don't need to touch
|
||||
l_tls_dtor_count because forced object deletion only happens when an
|
||||
error occurs during object load. Destructor registration for TLS
|
||||
non-POD objects should not have happened till then for this
|
||||
object. */
|
||||
if (force)
|
||||
l->l_flags_1 &= ~DF_1_NODELETE;
|
||||
}
|
||||
assert (idx == nloaded);
|
||||
|
||||
|
||||
+83
-41
@@ -36,12 +36,14 @@
|
||||
#include <caller.h>
|
||||
#include <sysdep.h>
|
||||
#include <stap-probe.h>
|
||||
#include <array_length.h>
|
||||
|
||||
#include <dl-dst.h>
|
||||
#include <dl-load.h>
|
||||
#include <dl-map-segments.h>
|
||||
#include <dl-unmap-segments.h>
|
||||
#include <dl-machine-reject-phdr.h>
|
||||
#include <dl-sysdep-open.h>
|
||||
|
||||
|
||||
#include <endian.h>
|
||||
@@ -101,7 +103,9 @@ static size_t ncapstr attribute_relro;
|
||||
static size_t max_capstrlen attribute_relro;
|
||||
|
||||
|
||||
/* Get the generated information about the trusted directories. */
|
||||
/* Get the generated information about the trusted directories. Use
|
||||
an array of concatenated strings to avoid relocations. See
|
||||
gen-trusted-dirs.awk. */
|
||||
#include "trusted-dirs.h"
|
||||
|
||||
static const char system_dirs[] = SYSTEM_DIRS;
|
||||
@@ -109,9 +113,7 @@ static const size_t system_dirs_len[] =
|
||||
{
|
||||
SYSTEM_DIRS_LEN
|
||||
};
|
||||
#define nsystem_dirs_len \
|
||||
(sizeof (system_dirs_len) / sizeof (system_dirs_len[0]))
|
||||
|
||||
#define nsystem_dirs_len array_length (system_dirs_len)
|
||||
|
||||
static bool
|
||||
is_trusted_path (const char *path, size_t len)
|
||||
@@ -431,32 +433,41 @@ fillin_rpath (char *rpath, struct r_search_path_elem **result, const char *sep,
|
||||
{
|
||||
char *cp;
|
||||
size_t nelems = 0;
|
||||
char *to_free;
|
||||
|
||||
while ((cp = __strsep (&rpath, sep)) != NULL)
|
||||
{
|
||||
struct r_search_path_elem *dirp;
|
||||
char *to_free = NULL;
|
||||
size_t len = 0;
|
||||
|
||||
to_free = cp = expand_dynamic_string_token (l, cp, 1);
|
||||
|
||||
size_t len = strlen (cp);
|
||||
|
||||
/* `strsep' can pass an empty string. This has to be
|
||||
interpreted as `use the current directory'. */
|
||||
if (len == 0)
|
||||
/* `strsep' can pass an empty string. */
|
||||
if (*cp != '\0')
|
||||
{
|
||||
static const char curwd[] = "./";
|
||||
cp = (char *) curwd;
|
||||
to_free = cp = expand_dynamic_string_token (l, cp, 1);
|
||||
|
||||
/* expand_dynamic_string_token can return NULL in case of empty
|
||||
path or memory allocation failure. */
|
||||
if (cp == NULL)
|
||||
continue;
|
||||
|
||||
/* Compute the length after dynamic string token expansion and
|
||||
ignore empty paths. */
|
||||
len = strlen (cp);
|
||||
if (len == 0)
|
||||
{
|
||||
free (to_free);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Remove trailing slashes (except for "/"). */
|
||||
while (len > 1 && cp[len - 1] == '/')
|
||||
--len;
|
||||
|
||||
/* Now add one if there is none so far. */
|
||||
if (len > 0 && cp[len - 1] != '/')
|
||||
cp[len++] = '/';
|
||||
}
|
||||
|
||||
/* Remove trailing slashes (except for "/"). */
|
||||
while (len > 1 && cp[len - 1] == '/')
|
||||
--len;
|
||||
|
||||
/* Now add one if there is none so far. */
|
||||
if (len > 0 && cp[len - 1] != '/')
|
||||
cp[len++] = '/';
|
||||
|
||||
/* Make sure we don't use untrusted directories if we run SUID. */
|
||||
if (__glibc_unlikely (check_trusted) && !is_trusted_path (cp, len))
|
||||
{
|
||||
@@ -619,6 +630,14 @@ decompose_rpath (struct r_search_path_struct *sps,
|
||||
necessary. */
|
||||
free (copy);
|
||||
|
||||
/* There is no path after expansion. */
|
||||
if (result[0] == NULL)
|
||||
{
|
||||
free (result);
|
||||
sps->dirs = (struct r_search_path_elem **) -1;
|
||||
return false;
|
||||
}
|
||||
|
||||
sps->dirs = result;
|
||||
/* The caller will change this value if we haven't used a real malloc. */
|
||||
sps->malloced = 1;
|
||||
@@ -686,9 +705,8 @@ _dl_init_paths (const char *llp)
|
||||
+ ncapstr * sizeof (enum r_dir_status))
|
||||
/ sizeof (struct r_search_path_elem));
|
||||
|
||||
rtld_search_dirs.dirs[0] = (struct r_search_path_elem *)
|
||||
malloc ((sizeof (system_dirs) / sizeof (system_dirs[0]))
|
||||
* round_size * sizeof (struct r_search_path_elem));
|
||||
rtld_search_dirs.dirs[0] = malloc (nsystem_dirs_len * round_size
|
||||
* sizeof (*rtld_search_dirs.dirs[0]));
|
||||
if (rtld_search_dirs.dirs[0] == NULL)
|
||||
{
|
||||
errstring = N_("cannot create cache for search path");
|
||||
@@ -774,8 +792,6 @@ _dl_init_paths (const char *llp)
|
||||
|
||||
if (llp != NULL && *llp != '\0')
|
||||
{
|
||||
size_t nllp;
|
||||
const char *cp = llp;
|
||||
char *llp_tmp;
|
||||
|
||||
#ifdef SHARED
|
||||
@@ -798,13 +814,10 @@ _dl_init_paths (const char *llp)
|
||||
|
||||
/* Decompose the LD_LIBRARY_PATH contents. First determine how many
|
||||
elements it has. */
|
||||
nllp = 1;
|
||||
while (*cp)
|
||||
{
|
||||
if (*cp == ':' || *cp == ';')
|
||||
++nllp;
|
||||
++cp;
|
||||
}
|
||||
size_t nllp = 1;
|
||||
for (const char *cp = llp_tmp; *cp != '\0'; ++cp)
|
||||
if (*cp == ':' || *cp == ';')
|
||||
++nllp;
|
||||
|
||||
env_path_list.dirs = (struct r_search_path_elem **)
|
||||
malloc ((nllp + 1) * sizeof (struct r_search_path_elem *));
|
||||
@@ -1471,9 +1484,13 @@ print_search_path (struct r_search_path_elem **list,
|
||||
ignore only ELF files for other architectures. Non-ELF files and
|
||||
ELF files with different header information cause fatal errors since
|
||||
this could mean there is something wrong in the installation and the
|
||||
user might want to know about this. */
|
||||
user might want to know about this.
|
||||
|
||||
If FD is not -1, then the file is already open and FD refers to it.
|
||||
In that case, FD is consumed for both successful and error returns. */
|
||||
static int
|
||||
open_verify (const char *name, struct filebuf *fbp, struct link_map *loader,
|
||||
open_verify (const char *name, int fd,
|
||||
struct filebuf *fbp, struct link_map *loader,
|
||||
int whatcode, int mode, bool *found_other_class, bool free_name)
|
||||
{
|
||||
/* This is the expected ELF header. */
|
||||
@@ -1514,6 +1531,7 @@ open_verify (const char *name, struct filebuf *fbp, struct link_map *loader,
|
||||
if (__glibc_unlikely (GLRO(dl_naudit) > 0) && whatcode != 0
|
||||
&& loader->l_auditing == 0)
|
||||
{
|
||||
const char *original_name = name;
|
||||
struct audit_ifaces *afct = GLRO(dl_audit);
|
||||
for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
|
||||
{
|
||||
@@ -1528,11 +1546,21 @@ open_verify (const char *name, struct filebuf *fbp, struct link_map *loader,
|
||||
|
||||
afct = afct->next;
|
||||
}
|
||||
|
||||
if (fd != -1 && name != original_name && strcmp (name, original_name))
|
||||
{
|
||||
/* An audit library changed what we're supposed to open,
|
||||
so FD no longer matches it. */
|
||||
__close (fd);
|
||||
fd = -1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Open the file. We always open files read-only. */
|
||||
int fd = __open (name, O_RDONLY | O_CLOEXEC);
|
||||
if (fd == -1)
|
||||
/* Open the file. We always open files read-only. */
|
||||
fd = __open (name, O_RDONLY | O_CLOEXEC);
|
||||
|
||||
if (fd != -1)
|
||||
{
|
||||
ElfW(Ehdr) *ehdr;
|
||||
@@ -1801,7 +1829,7 @@ open_path (const char *name, size_t namelen, int mode,
|
||||
if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_LIBS))
|
||||
_dl_debug_printf (" trying file=%s\n", buf);
|
||||
|
||||
fd = open_verify (buf, fbp, loader, whatcode, mode,
|
||||
fd = open_verify (buf, -1, fbp, loader, whatcode, mode,
|
||||
found_other_class, false);
|
||||
if (this_dir->status[cnt] == unknown)
|
||||
{
|
||||
@@ -2041,6 +2069,20 @@ _dl_map_object (struct link_map *loader, const char *name,
|
||||
&loader->l_runpath_dirs, &realname, &fb, loader,
|
||||
LA_SER_RUNPATH, &found_other_class);
|
||||
|
||||
if (fd == -1)
|
||||
{
|
||||
realname = _dl_sysdep_open_object (name, namelen, &fd);
|
||||
if (realname != NULL)
|
||||
{
|
||||
fd = open_verify (realname, fd,
|
||||
&fb, loader ?: GL(dl_ns)[nsid]._ns_loaded,
|
||||
LA_SER_CONFIG, mode, &found_other_class,
|
||||
false);
|
||||
if (fd == -1)
|
||||
free (realname);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef USE_LDCONFIG
|
||||
if (fd == -1
|
||||
&& (__glibc_likely ((mode & __RTLD_SECURE) == 0)
|
||||
@@ -2086,7 +2128,7 @@ _dl_map_object (struct link_map *loader, const char *name,
|
||||
|
||||
if (cached != NULL)
|
||||
{
|
||||
fd = open_verify (cached,
|
||||
fd = open_verify (cached, -1,
|
||||
&fb, loader ?: GL(dl_ns)[nsid]._ns_loaded,
|
||||
LA_SER_CONFIG, mode, &found_other_class,
|
||||
false);
|
||||
@@ -2121,7 +2163,7 @@ _dl_map_object (struct link_map *loader, const char *name,
|
||||
fd = -1;
|
||||
else
|
||||
{
|
||||
fd = open_verify (realname, &fb,
|
||||
fd = open_verify (realname, -1, &fb,
|
||||
loader ?: GL(dl_ns)[nsid]._ns_loaded, 0, mode,
|
||||
&found_other_class, true);
|
||||
if (__glibc_unlikely (fd == -1))
|
||||
|
||||
+19
-2
@@ -1016,6 +1016,18 @@ _dl_debug_bindings (const char *undef_name, struct link_map *undef_map,
|
||||
#ifdef SHARED
|
||||
if (GLRO(dl_debug_mask) & DL_DEBUG_PRELINK)
|
||||
{
|
||||
/* ELF_RTYPE_CLASS_XXX must match RTYPE_CLASS_XXX used by prelink with
|
||||
LD_TRACE_PRELINKING. */
|
||||
#define RTYPE_CLASS_VALID 8
|
||||
#define RTYPE_CLASS_PLT (8|1)
|
||||
#define RTYPE_CLASS_COPY (8|2)
|
||||
#define RTYPE_CLASS_TLS (8|4)
|
||||
#if ELF_RTYPE_CLASS_PLT != 0 && ELF_RTYPE_CLASS_PLT != 1
|
||||
# error ELF_RTYPE_CLASS_PLT must be 0 or 1!
|
||||
#endif
|
||||
#if ELF_RTYPE_CLASS_COPY != 0 && ELF_RTYPE_CLASS_COPY != 2
|
||||
# error ELF_RTYPE_CLASS_COPY must be 0 or 2!
|
||||
#endif
|
||||
int conflict = 0;
|
||||
struct sym_val val = { NULL, NULL };
|
||||
|
||||
@@ -1071,12 +1083,17 @@ _dl_debug_bindings (const char *undef_name, struct link_map *undef_map,
|
||||
|
||||
if (value->s)
|
||||
{
|
||||
/* Keep only ELF_RTYPE_CLASS_PLT and ELF_RTYPE_CLASS_COPY
|
||||
bits since since prelink only uses them. */
|
||||
type_class &= ELF_RTYPE_CLASS_PLT | ELF_RTYPE_CLASS_COPY;
|
||||
if (__glibc_unlikely (ELFW(ST_TYPE) (value->s->st_info)
|
||||
== STT_TLS))
|
||||
type_class = 4;
|
||||
/* Clear the RTYPE_CLASS_VALID bit in RTYPE_CLASS_TLS. */
|
||||
type_class = RTYPE_CLASS_TLS & ~RTYPE_CLASS_VALID;
|
||||
else if (__glibc_unlikely (ELFW(ST_TYPE) (value->s->st_info)
|
||||
== STT_GNU_IFUNC))
|
||||
type_class |= 8;
|
||||
/* Set the RTYPE_CLASS_VALID bit. */
|
||||
type_class |= RTYPE_CLASS_VALID;
|
||||
}
|
||||
|
||||
if (conflict
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
/* System-specific call to open a shared object by name. Stub 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/>. */
|
||||
|
||||
#ifndef _DL_SYSDEP_OPEN_H
|
||||
#define _DL_SYSDEP_OPEN_H 1
|
||||
|
||||
#include <assert.h>
|
||||
#include <stddef.h>
|
||||
|
||||
/* NAME is a name without slashes, as it appears in a DT_NEEDED entry
|
||||
or a dlopen call's argument or suchlike. NAMELEN is (strlen (NAME) + 1).
|
||||
|
||||
Find NAME in an OS-dependent fashion, and return its "real" name.
|
||||
Optionally fill in *FD with a file descriptor open on that file (or
|
||||
else leave its initial value of -1). The return value is a new
|
||||
malloc'd string, which will be free'd by the caller. If NAME is
|
||||
resolved to an actual file that can be opened, then the return
|
||||
value should name that file (and if *FD was not set, then a normal
|
||||
__open call on that string will be made). If *FD was set by some
|
||||
other means than a normal open and there is no "real" name to use,
|
||||
then __strdup (NAME) is fine (modulo error checking). */
|
||||
|
||||
static inline char *
|
||||
_dl_sysdep_open_object (const char *name, size_t namelen, int *fd)
|
||||
{
|
||||
assert (*fd == -1);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif /* dl-sysdep-open.h */
|
||||
@@ -138,9 +138,6 @@ elf_get_dynamic_info (struct link_map *l, ElfW(Dyn) *temp)
|
||||
|| (info[VERSYMIDX (DT_FLAGS_1)]->d_un.d_val & ~DF_1_NOW) == 0);
|
||||
assert (info[DT_FLAGS] == NULL
|
||||
|| (info[DT_FLAGS]->d_un.d_val & ~DF_BIND_NOW) == 0);
|
||||
/* Flags must not be set for ld.so. */
|
||||
assert (info[DT_RUNPATH] == NULL);
|
||||
assert (info[DT_RPATH] == NULL);
|
||||
#else
|
||||
if (info[DT_FLAGS] != NULL)
|
||||
{
|
||||
|
||||
+1
-13
@@ -164,18 +164,6 @@ warning: you do not have execution permission for" "\`$file'" >&2
|
||||
fi
|
||||
done
|
||||
case $ret in
|
||||
0)
|
||||
# If the program exits with exit code 5, it means the process has been
|
||||
# invoked with __libc_enable_secure. Fall back to running it through
|
||||
# the dynamic linker.
|
||||
try_trace "$file"
|
||||
rc=$?
|
||||
if [ $rc = 5 ]; then
|
||||
try_trace "$RTLD" "$file"
|
||||
rc=$?
|
||||
fi
|
||||
[ $rc = 0 ] || result=1
|
||||
;;
|
||||
1)
|
||||
# This can be a non-ELF binary or no binary at all.
|
||||
nonelf "$file" || {
|
||||
@@ -183,7 +171,7 @@ warning: you do not have execution permission for" "\`$file'" >&2
|
||||
result=1
|
||||
}
|
||||
;;
|
||||
2)
|
||||
0|2)
|
||||
try_trace "$RTLD" "$file" || result=1
|
||||
;;
|
||||
*)
|
||||
|
||||
+4
-11
@@ -162,7 +162,6 @@ struct rtld_global_ro _rtld_global_ro attribute_relro =
|
||||
._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,
|
||||
|
||||
@@ -709,15 +708,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
|
||||
@@ -2471,9 +2467,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:
|
||||
|
||||
@@ -167,11 +167,11 @@ makesymlink (src, dest)
|
||||
const char *src;
|
||||
const char *dest;
|
||||
{
|
||||
struct stat stats;
|
||||
struct stat64 stats;
|
||||
const char *error;
|
||||
|
||||
/* Destination must not be a directory. */
|
||||
if (lstat (dest, &stats) == 0)
|
||||
if (lstat64 (dest, &stats) == 0)
|
||||
{
|
||||
if (S_ISDIR (stats.st_mode))
|
||||
{
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
#include "../dlfcn/dlfcn.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <gnu/lib-names.h>
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
printf ("\nOpening pthread library.\n");
|
||||
void *pthread = dlopen (LIBPTHREAD_SO, RTLD_LAZY);
|
||||
|
||||
/* This is a test for correct DF_1_NODELETE clearing when dlopen failure
|
||||
happens. We should clear DF_1_NODELETE for failed library only, because
|
||||
doing this for others (e.g. libpthread) might cause them to be unloaded,
|
||||
that may lead to some global references (e.g. __rtld_lock_unlock) to be
|
||||
broken. The dlopen should fail because of undefined symbols in shared
|
||||
library, that cause DF_1_NODELETE to be cleared. For libpthread, this
|
||||
flag should be set, because if not, SIGSEGV will happen in dlclose. */
|
||||
if (dlopen ("tst-nodelete2mod.so", RTLD_NOW) != NULL)
|
||||
{
|
||||
printf ("Unique symbols test failed\n");
|
||||
result = 1;
|
||||
}
|
||||
|
||||
if (pthread)
|
||||
dlclose (pthread);
|
||||
|
||||
if (result == 0)
|
||||
printf ("SUCCESS\n");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#define TEST_FUNCTION do_test ()
|
||||
#include "../test-skeleton.c"
|
||||
@@ -1,6 +1,7 @@
|
||||
/* Undefined symbol. */
|
||||
extern int not_exist (void);
|
||||
|
||||
int foo (void)
|
||||
{
|
||||
return not_exist ();
|
||||
return not_exist ();
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/* Test the output from the environment variable, LD_TRACE_PRELINKING,
|
||||
for prelink.
|
||||
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>
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
fprintf (stdout, "hello\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define TEST_FUNCTION do_test ()
|
||||
#include "../test-skeleton.c"
|
||||
@@ -0,0 +1 @@
|
||||
/0 stdout
|
||||
@@ -5,6 +5,9 @@
|
||||
# The variable $($(lib)-routines) defines the list of modules
|
||||
# to be included in that library. A sysdep Makefile can add to
|
||||
# $(lib)-sysdep_routines to include additional modules.
|
||||
#
|
||||
# Libraries listed in $(extra-libs-noinstall) are built, but not
|
||||
# installed.
|
||||
|
||||
lib := $(firstword $(extra-libs-left))
|
||||
extra-libs-left := $(filter-out $(lib),$(extra-libs-left))
|
||||
@@ -28,7 +31,9 @@ extra-objs := $(extra-objs)
|
||||
all-$(lib)-routines := $($(lib)-routines) $($(lib)-sysdep_routines)
|
||||
|
||||
# Add each flavor of library to the lists of things to build and install.
|
||||
ifeq (,$(filter $(lib), $(extra-libs-noinstall)))
|
||||
install-lib += $(foreach o,$(object-suffixes-$(lib)),$(lib:lib%=$(libtype$o)))
|
||||
endif
|
||||
extra-objs += $(foreach o,$(filter-out .os .oS,$(object-suffixes-$(lib))),\
|
||||
$(patsubst %,%$o,$(filter-out \
|
||||
$($(lib)-shared-only-routines),\
|
||||
|
||||
+1
-1
@@ -28,7 +28,7 @@ extra-libs-others = $(extra-libs)
|
||||
subdir-dirs = nss_hesiod
|
||||
vpath %.c nss_hesiod
|
||||
|
||||
libnss_hesiod-routines := hesiod hesiod-grp hesiod-init hesiod-proto \
|
||||
libnss_hesiod-routines := hesiod hesiod-grp hesiod-proto \
|
||||
hesiod-pwd hesiod-service
|
||||
# Build only shared library
|
||||
libnss_hesiod-inhibit-o = $(filter-out .os,$(object-suffixes))
|
||||
|
||||
+18
-69
@@ -1,6 +1,19 @@
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static const char rcsid[] = "$BINDId: hesiod.c,v 1.21 2000/02/28 14:51:08 vixie Exp $";
|
||||
#endif
|
||||
/* 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/>. */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1996,1999 by Internet Software Consortium.
|
||||
@@ -52,18 +65,9 @@ static const char rcsid[] = "$BINDId: hesiod.c,v 1.21 2000/02/28 14:51:08 vixie
|
||||
|
||||
/* Forward */
|
||||
|
||||
int hesiod_init(void **context);
|
||||
void hesiod_end(void *context);
|
||||
char * hesiod_to_bind(void *context, const char *name,
|
||||
const char *type);
|
||||
char ** hesiod_resolve(void *context, const char *name,
|
||||
const char *type);
|
||||
void hesiod_free_list(void *context, char **list);
|
||||
|
||||
static int parse_config_file(struct hesiod_p *ctx, const char *filename);
|
||||
static char ** get_txt_records(struct hesiod_p *ctx, int class,
|
||||
const char *name);
|
||||
static int init(struct hesiod_p *ctx);
|
||||
|
||||
/* Public */
|
||||
|
||||
@@ -82,7 +86,6 @@ hesiod_init(void **context) {
|
||||
|
||||
ctx->LHS = NULL;
|
||||
ctx->RHS = NULL;
|
||||
ctx->res = NULL;
|
||||
/* Set default query classes. */
|
||||
ctx->classes[0] = C_IN;
|
||||
ctx->classes[1] = C_HS;
|
||||
@@ -131,11 +134,6 @@ hesiod_init(void **context) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (res_ninit(ctx->res) < 0)
|
||||
goto cleanup;
|
||||
#endif
|
||||
|
||||
*context = ctx;
|
||||
return (0);
|
||||
|
||||
@@ -152,12 +150,8 @@ hesiod_end(void *context) {
|
||||
struct hesiod_p *ctx = (struct hesiod_p *) context;
|
||||
int save_errno = errno;
|
||||
|
||||
if (ctx->res)
|
||||
res_nclose(ctx->res);
|
||||
free(ctx->RHS);
|
||||
free(ctx->LHS);
|
||||
if (ctx->res && ctx->free_res)
|
||||
(*ctx->free_res)(ctx->res);
|
||||
free(ctx);
|
||||
__set_errno(save_errno);
|
||||
}
|
||||
@@ -232,10 +226,6 @@ hesiod_resolve(void *context, const char *name, const char *type) {
|
||||
|
||||
if (bindname == NULL)
|
||||
return (NULL);
|
||||
if (init(ctx) == -1) {
|
||||
free(bindname);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
retvec = get_txt_records(ctx, ctx->classes[0], bindname);
|
||||
|
||||
@@ -365,13 +355,13 @@ get_txt_records(struct hesiod_p *ctx, int class, const char *name) {
|
||||
/*
|
||||
* Construct the query and send it.
|
||||
*/
|
||||
n = res_nmkquery(ctx->res, QUERY, name, class, T_TXT, NULL, 0,
|
||||
n = res_mkquery(QUERY, name, class, T_TXT, NULL, 0,
|
||||
NULL, qbuf, MAX_HESRESP);
|
||||
if (n < 0) {
|
||||
__set_errno(EMSGSIZE);
|
||||
return (NULL);
|
||||
}
|
||||
n = res_nsend(ctx->res, qbuf, n, abuf, MAX_HESRESP);
|
||||
n = res_send(qbuf, n, abuf, MAX_HESRESP);
|
||||
if (n < 0) {
|
||||
__set_errno(ECONNREFUSED);
|
||||
return (NULL);
|
||||
@@ -464,44 +454,3 @@ get_txt_records(struct hesiod_p *ctx, int class, const char *name) {
|
||||
free(list);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
struct __res_state *
|
||||
__hesiod_res_get(void *context) {
|
||||
struct hesiod_p *ctx = context;
|
||||
|
||||
if (!ctx->res) {
|
||||
struct __res_state *res;
|
||||
res = (struct __res_state *)calloc(1, sizeof *res);
|
||||
if (res == NULL)
|
||||
return (NULL);
|
||||
__hesiod_res_set(ctx, res, free);
|
||||
}
|
||||
|
||||
return (ctx->res);
|
||||
}
|
||||
|
||||
void
|
||||
__hesiod_res_set(void *context, struct __res_state *res,
|
||||
void (*free_res)(void *)) {
|
||||
struct hesiod_p *ctx = context;
|
||||
|
||||
if (ctx->res && ctx->free_res) {
|
||||
res_nclose(ctx->res);
|
||||
(*ctx->free_res)(ctx->res);
|
||||
}
|
||||
|
||||
ctx->res = res;
|
||||
ctx->free_res = free_res;
|
||||
}
|
||||
|
||||
static int
|
||||
init(struct hesiod_p *ctx) {
|
||||
|
||||
if (!ctx->res && !__hesiod_res_get(ctx))
|
||||
return (-1);
|
||||
|
||||
if (__res_maybe_init (ctx->res, 0) == -1)
|
||||
return (-1);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
+22
-12
@@ -1,3 +1,20 @@
|
||||
/* 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/>. */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1996,1999 by Internet Software Consortium.
|
||||
*
|
||||
@@ -19,22 +36,15 @@
|
||||
* This file is primarily maintained by <tytso@mit.edu> and <ghudson@mit.edu>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* $BINDId: hesiod.h,v 1.7 1999/01/08 19:22:45 vixie Exp $
|
||||
*/
|
||||
|
||||
#ifndef _HESIOD_H_INCLUDED
|
||||
#define _HESIOD_H_INCLUDED
|
||||
|
||||
int hesiod_init (void **context);
|
||||
void hesiod_end (void *context);
|
||||
int hesiod_init (void **context) attribute_hidden;
|
||||
void hesiod_end (void *context) attribute_hidden;
|
||||
char * hesiod_to_bind (void *context, const char *name,
|
||||
const char *type);
|
||||
const char *type) attribute_hidden;
|
||||
char ** hesiod_resolve (void *context, const char *name,
|
||||
const char *type);
|
||||
void hesiod_free_list (void *context, char **list);
|
||||
struct __res_state * __hesiod_res_get (void *context);
|
||||
void __hesiod_res_set (void *context, struct __res_state *,
|
||||
void (*)(void *));
|
||||
const char *type) attribute_hidden;
|
||||
void hesiod_free_list (void *context, char **list) attribute_hidden;
|
||||
|
||||
#endif /*_HESIOD_H_INCLUDED*/
|
||||
|
||||
+17
-9
@@ -1,3 +1,20 @@
|
||||
/* 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/>. */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1996,1999 by Internet Software Consortium.
|
||||
*
|
||||
@@ -19,10 +36,6 @@
|
||||
* This file is primarily maintained by <tytso@mit.edu> and <ghudson@mit.edu>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* $BINDId: hesiod_p.h,v 1.9 1999/01/08 19:24:39 vixie Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
* hesiod_p.h -- private definitions for the hesiod library
|
||||
*/
|
||||
@@ -36,11 +49,6 @@
|
||||
struct hesiod_p {
|
||||
char * LHS; /* normally ".ns" */
|
||||
char * RHS; /* AKA the default hesiod domain */
|
||||
struct __res_state * res; /* resolver context */
|
||||
void (*free_res)(void *);
|
||||
void (*res_set)(struct hesiod_p *, struct __res_state *,
|
||||
void (*)(void *));
|
||||
struct __res_state * (*res_get)(struct hesiod_p *);
|
||||
int classes[2]; /* The class search order. */
|
||||
};
|
||||
|
||||
|
||||
@@ -26,8 +26,6 @@
|
||||
#include <string.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
#include "nss_hesiod.h"
|
||||
|
||||
/* Get the declaration of the parser function. */
|
||||
#define ENTNAME grent
|
||||
#define STRUCTURE group
|
||||
@@ -58,8 +56,7 @@ lookup (const char *name, const char *type, struct group *grp,
|
||||
size_t len;
|
||||
int olderr = errno;
|
||||
|
||||
context = _nss_hesiod_init ();
|
||||
if (context == NULL)
|
||||
if (hesiod_init (&context) < 0)
|
||||
return NSS_STATUS_UNAVAIL;
|
||||
|
||||
list = hesiod_resolve (context, name, type);
|
||||
@@ -179,8 +176,7 @@ _nss_hesiod_initgroups_dyn (const char *user, gid_t group, long int *start,
|
||||
gid_t *groups = *groupsp;
|
||||
int save_errno;
|
||||
|
||||
context = _nss_hesiod_init ();
|
||||
if (context == NULL)
|
||||
if (hesiod_init (&context) < 0)
|
||||
return NSS_STATUS_UNAVAIL;
|
||||
|
||||
list = hesiod_resolve (context, user, "grplist");
|
||||
|
||||
@@ -25,8 +25,6 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "nss_hesiod.h"
|
||||
|
||||
/* Declare a parser for Hesiod protocol entries. Although the format
|
||||
of the entries is identical to those in /etc/protocols, here is no
|
||||
predefined parser for us to use. */
|
||||
@@ -68,8 +66,7 @@ lookup (const char *name, const char *type, struct protoent *proto,
|
||||
int found;
|
||||
int olderr = errno;
|
||||
|
||||
context = _nss_hesiod_init ();
|
||||
if (context == NULL)
|
||||
if (hesiod_init (&context) < 0)
|
||||
return NSS_STATUS_UNAVAIL;
|
||||
|
||||
list = hesiod_resolve (context, name, type);
|
||||
|
||||
@@ -24,8 +24,6 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "nss_hesiod.h"
|
||||
|
||||
/* Get the declaration of the parser function. */
|
||||
#define ENTNAME pwent
|
||||
#define STRUCTURE passwd
|
||||
@@ -56,8 +54,7 @@ lookup (const char *name, const char *type, struct passwd *pwd,
|
||||
size_t len;
|
||||
int olderr = errno;
|
||||
|
||||
context = _nss_hesiod_init ();
|
||||
if (context == NULL)
|
||||
if (hesiod_init (&context) < 0)
|
||||
return NSS_STATUS_UNAVAIL;
|
||||
|
||||
list = hesiod_resolve (context, name, type);
|
||||
|
||||
@@ -25,8 +25,6 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "nss_hesiod.h"
|
||||
|
||||
/* Hesiod uses a format for service entries that differs from the
|
||||
traditional format. We therefore declare our own parser. */
|
||||
|
||||
@@ -69,8 +67,7 @@ lookup (const char *name, const char *type, const char *protocol,
|
||||
int found;
|
||||
int olderr = errno;
|
||||
|
||||
context = _nss_hesiod_init ();
|
||||
if (context == NULL)
|
||||
if (hesiod_init (&context) < 0)
|
||||
return NSS_STATUS_UNAVAIL;
|
||||
|
||||
list = hesiod_resolve (context, name, type);
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
/* The array_length and array_end macros.
|
||||
Copyright (C) 2017 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/>. */
|
||||
|
||||
#ifndef _ARRAY_LENGTH_H
|
||||
#define _ARRAY_LENGTH_H
|
||||
|
||||
/* array_length (VAR) is the number of elements in the array VAR. VAR
|
||||
must evaluate to an array, not a pointer. */
|
||||
#define array_length(var) \
|
||||
__extension__ ({ \
|
||||
_Static_assert (!__builtin_types_compatible_p \
|
||||
(__typeof (var), __typeof (&(var)[0])), \
|
||||
"argument must be an array"); \
|
||||
sizeof (var) / sizeof ((var)[0]); \
|
||||
})
|
||||
|
||||
/* array_end (VAR) is a pointer one past the end of the array VAR.
|
||||
VAR must evaluate to an array, not a pointer. */
|
||||
#define array_end(var) (&(var)[array_length (var)])
|
||||
|
||||
#endif /* _ARRAY_LENGTH_H */
|
||||
+20
-1
@@ -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;
|
||||
|
||||
+35
-14
@@ -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;
|
||||
}
|
||||
|
||||
+1
-3
@@ -144,8 +144,6 @@ const struct __locale_data _nl_C_LC_COLLATE attribute_hidden =
|
||||
/* _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 }
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
+4
-3
@@ -121,9 +121,10 @@ _nl_intern_locale_data (int category, const void *data, size_t datasize)
|
||||
switch (category)
|
||||
{
|
||||
#define CATTEST(cat) \
|
||||
case LC_##cat: \
|
||||
assert (cnt < (sizeof (_nl_value_type_LC_##cat) \
|
||||
/ sizeof (_nl_value_type_LC_##cat[0]))); \
|
||||
case LC_##cat: \
|
||||
if (cnt >= (sizeof (_nl_value_type_LC_##cat) \
|
||||
/ sizeof (_nl_value_type_LC_##cat[0]))) \
|
||||
goto puntdata; \
|
||||
break
|
||||
CATTEST (NUMERIC);
|
||||
CATTEST (TIME);
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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 *locale, const struct charmap_t *charmap,
|
||||
/* 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 *locale, const struct charmap_t *charmap,
|
||||
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);
|
||||
|
||||
+4
-1
@@ -28,7 +28,8 @@ tests := mallocbug tst-malloc tst-valloc tst-calloc tst-obstack \
|
||||
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 tst-malloc-too-large \
|
||||
|
||||
test-srcs = tst-mtrace
|
||||
|
||||
routines = malloc morecore mcheck mtrace obstack \
|
||||
@@ -47,6 +48,8 @@ libmemusage-inhibit-o = $(filter-out .os,$(object-suffixes))
|
||||
|
||||
$(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
|
||||
|
||||
+154
-16
@@ -67,10 +67,30 @@ extern int sanity_check_heap_info_alignment[(sizeof (heap_info)
|
||||
/* 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,66 @@ _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;
|
||||
tsd_getspecific (arena_key, replaced_arena);
|
||||
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. */
|
||||
static mstate
|
||||
get_free_list (void)
|
||||
{
|
||||
mstate replaced_arena;
|
||||
mstate result = free_list;
|
||||
|
||||
tsd_getspecific (arena, replaced_arena);
|
||||
|
||||
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. */
|
||||
assert (result->attached_threads == 0);
|
||||
result->attached_threads = 1;
|
||||
|
||||
detach_arena (replaced_arena);
|
||||
}
|
||||
(void) mutex_unlock (&free_list_lock);
|
||||
|
||||
if (result != NULL)
|
||||
{
|
||||
@@ -795,6 +882,26 @@ get_free_list (void)
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Remove the arena from the free list (if it is present).
|
||||
free_list_lock must have been acquired by the caller. */
|
||||
static void
|
||||
remove_from_free_list (mstate arena)
|
||||
{
|
||||
mstate *previous = &free_list;
|
||||
for (mstate p = free_list; p != NULL; p = p->next_free)
|
||||
{
|
||||
assert (p->attached_threads == 0);
|
||||
if (p == arena)
|
||||
{
|
||||
/* Remove the requested arena from the list. */
|
||||
*previous = p->next_free;
|
||||
break;
|
||||
}
|
||||
else
|
||||
previous = &p->next_free;
|
||||
}
|
||||
}
|
||||
|
||||
/* Lock and return an arena that can be reused for memory allocation.
|
||||
Avoid AVOID_ARENA as we have already failed to allocate memory in
|
||||
it and it is currently locked. */
|
||||
@@ -802,16 +909,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);
|
||||
@@ -827,19 +938,40 @@ 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);
|
||||
|
||||
out:
|
||||
/* Attach the arena to the current thread. */
|
||||
{
|
||||
mstate replaced_arena;
|
||||
|
||||
tsd_getspecific (arena, replaced_arena);
|
||||
(void) mutex_lock (&free_list_lock);
|
||||
detach_arena (replaced_arena);
|
||||
|
||||
/* We may have picked up an arena on the free list. We need to
|
||||
preserve the invariant that no arena on the free list has a
|
||||
positive attached_threads counter (otherwise,
|
||||
arena_thread_freeres cannot use the counter to determine if the
|
||||
arena needs to be put on the free list). We unconditionally
|
||||
remove the selected arena from the free list. The caller of
|
||||
reused_arena checked the free list and observed it to be empty,
|
||||
so the list is very short. */
|
||||
remove_from_free_list (result);
|
||||
|
||||
++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 +1064,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);
|
||||
|
||||
+31
-10
@@ -1252,14 +1252,21 @@ nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
MINSIZE : \
|
||||
((req) + SIZE_SZ + MALLOC_ALIGN_MASK) & ~MALLOC_ALIGN_MASK)
|
||||
|
||||
/* Same, except also perform argument check */
|
||||
|
||||
#define checked_request2size(req, sz) \
|
||||
if (REQUEST_OUT_OF_RANGE (req)) { \
|
||||
__set_errno (ENOMEM); \
|
||||
return 0; \
|
||||
} \
|
||||
(sz) = request2size (req);
|
||||
/* Same, except also perform an argument and result check. First, we check
|
||||
that the padding done by request2size didn't result in an integer
|
||||
overflow. Then we check (using REQUEST_OUT_OF_RANGE) that the resulting
|
||||
size isn't so large that a later alignment would lead to another integer
|
||||
overflow. */
|
||||
#define checked_request2size(req, sz) \
|
||||
({ \
|
||||
(sz) = request2size (req); \
|
||||
if (((sz) < (req)) \
|
||||
|| REQUEST_OUT_OF_RANGE (sz)) \
|
||||
{ \
|
||||
__set_errno (ENOMEM); \
|
||||
return 0; \
|
||||
} \
|
||||
})
|
||||
|
||||
/*
|
||||
--------------- Physical chunk operations ---------------
|
||||
@@ -1709,9 +1716,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 +1768,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. */
|
||||
@@ -4410,6 +4424,13 @@ _int_memalign (mstate av, size_t alignment, size_t bytes)
|
||||
*/
|
||||
|
||||
|
||||
/* Check for overflow. */
|
||||
if (nb > SIZE_MAX - alignment - MINSIZE)
|
||||
{
|
||||
__set_errno (ENOMEM);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Call malloc with worst case padding to hit alignment. */
|
||||
|
||||
m = (char *) (_int_malloc (av, nb + alignment + MINSIZE));
|
||||
|
||||
@@ -0,0 +1,218 @@
|
||||
/* 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 <malloc.h>
|
||||
#include <pthread.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static int do_test (void);
|
||||
|
||||
#define TEST_FUNCTION do_test ()
|
||||
#include "../test-skeleton.c"
|
||||
|
||||
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 threads should be smaller than the number of
|
||||
arenas, so that there will be some free arenas to add to the
|
||||
arena free list. */
|
||||
enum { outer_thread_count = 2 };
|
||||
if (mallopt (M_ARENA_MAX, 8) == 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;
|
||||
|
||||
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;
|
||||
}
|
||||
@@ -0,0 +1,237 @@
|
||||
/* Test and verify that too-large memory allocations fail with ENOMEM.
|
||||
Copyright (C) 2018 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/>. */
|
||||
|
||||
/* Bug 22375 reported a regression in malloc where if after malloc'ing then
|
||||
free'ing a small block of memory, malloc is then called with a really
|
||||
large size argument (close to SIZE_MAX): instead of returning NULL and
|
||||
setting errno to ENOMEM, malloc incorrectly returns the previously
|
||||
allocated block instead. Bug 22343 reported a similar case where
|
||||
posix_memalign incorrectly returns successfully when called with an with
|
||||
a really large size argument.
|
||||
|
||||
Both of these were caused by integer overflows in the allocator when it
|
||||
was trying to pad the requested size to allow for book-keeping or
|
||||
alignment. This test guards against such bugs by repeatedly allocating
|
||||
and freeing small blocks of memory then trying to allocate various block
|
||||
sizes larger than the memory bus width of 64-bit targets, or almost
|
||||
as large as SIZE_MAX on 32-bit targets supported by glibc. In each case,
|
||||
it verifies that such impossibly large allocations correctly fail. */
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <malloc.h>
|
||||
#include <errno.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/resource.h>
|
||||
#include <libc-internal.h>
|
||||
#include <support/check.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
|
||||
/* This function prepares for each 'too-large memory allocation' test by
|
||||
performing a small successful malloc/free and resetting errno prior to
|
||||
the actual test. */
|
||||
static void
|
||||
test_setup (void)
|
||||
{
|
||||
void *volatile ptr = malloc (16);
|
||||
TEST_VERIFY_EXIT (ptr != NULL);
|
||||
free (ptr);
|
||||
errno = 0;
|
||||
}
|
||||
|
||||
|
||||
/* This function tests each of:
|
||||
- malloc (SIZE)
|
||||
- realloc (PTR_FOR_REALLOC, SIZE)
|
||||
- for various values of NMEMB:
|
||||
- calloc (NMEMB, SIZE/NMEMB)
|
||||
- calloc (SIZE/NMEMB, NMEMB)
|
||||
and precedes each of these tests with a small malloc/free before it. */
|
||||
static void
|
||||
test_large_allocations (size_t size)
|
||||
{
|
||||
void * ptr_to_realloc;
|
||||
|
||||
test_setup ();
|
||||
TEST_VERIFY (malloc (size) == NULL);
|
||||
TEST_VERIFY (errno == ENOMEM);
|
||||
|
||||
ptr_to_realloc = malloc (16);
|
||||
TEST_VERIFY_EXIT (ptr_to_realloc != NULL);
|
||||
test_setup ();
|
||||
TEST_VERIFY (realloc (ptr_to_realloc, size) == NULL);
|
||||
TEST_VERIFY (errno == ENOMEM);
|
||||
free (ptr_to_realloc);
|
||||
|
||||
for (size_t nmemb = 1; nmemb <= 8; nmemb *= 2)
|
||||
if ((size % nmemb) == 0)
|
||||
{
|
||||
test_setup ();
|
||||
TEST_VERIFY (calloc (nmemb, size / nmemb) == NULL);
|
||||
TEST_VERIFY (errno == ENOMEM);
|
||||
|
||||
test_setup ();
|
||||
TEST_VERIFY (calloc (size / nmemb, nmemb) == NULL);
|
||||
TEST_VERIFY (errno == ENOMEM);
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
static long pagesize;
|
||||
|
||||
/* This function tests the following aligned memory allocation functions
|
||||
using several valid alignments and precedes each allocation test with a
|
||||
small malloc/free before it:
|
||||
memalign, posix_memalign, aligned_alloc, valloc, pvalloc. */
|
||||
static void
|
||||
test_large_aligned_allocations (size_t size)
|
||||
{
|
||||
/* ptr stores the result of posix_memalign but since all those calls
|
||||
should fail, posix_memalign should never change ptr. We set it to
|
||||
NULL here and later on we check that it remains NULL after each
|
||||
posix_memalign call. */
|
||||
void * ptr = NULL;
|
||||
|
||||
size_t align;
|
||||
|
||||
/* All aligned memory allocation functions expect an alignment that is a
|
||||
power of 2. Given this, we test each of them with every valid
|
||||
alignment from 1 thru PAGESIZE. */
|
||||
for (align = 1; align <= pagesize; align *= 2)
|
||||
{
|
||||
test_setup ();
|
||||
TEST_VERIFY (memalign (align, size) == NULL);
|
||||
TEST_VERIFY (errno == ENOMEM);
|
||||
|
||||
/* posix_memalign expects an alignment that is a power of 2 *and* a
|
||||
multiple of sizeof (void *). */
|
||||
if ((align % sizeof (void *)) == 0)
|
||||
{
|
||||
test_setup ();
|
||||
TEST_VERIFY (posix_memalign (&ptr, align, size) == ENOMEM);
|
||||
TEST_VERIFY (ptr == NULL);
|
||||
}
|
||||
|
||||
/* aligned_alloc expects a size that is a multiple of alignment. */
|
||||
if ((size % align) == 0)
|
||||
{
|
||||
test_setup ();
|
||||
TEST_VERIFY (aligned_alloc (align, size) == NULL);
|
||||
TEST_VERIFY (errno == ENOMEM);
|
||||
}
|
||||
}
|
||||
|
||||
/* Both valloc and pvalloc return page-aligned memory. */
|
||||
|
||||
test_setup ();
|
||||
TEST_VERIFY (valloc (size) == NULL);
|
||||
TEST_VERIFY (errno == ENOMEM);
|
||||
|
||||
test_setup ();
|
||||
TEST_VERIFY (pvalloc (size) == NULL);
|
||||
TEST_VERIFY (errno == ENOMEM);
|
||||
}
|
||||
|
||||
|
||||
#define FOURTEEN_ON_BITS ((1UL << 14) - 1)
|
||||
#define FIFTY_ON_BITS ((1UL << 50) - 1)
|
||||
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
|
||||
#if __WORDSIZE >= 64
|
||||
|
||||
/* This test assumes that none of the supported targets have an address
|
||||
bus wider than 50 bits, and that therefore allocations for sizes wider
|
||||
than 50 bits will fail. Here, we ensure that the assumption continues
|
||||
to be true in the future when we might have address buses wider than 50
|
||||
bits. */
|
||||
|
||||
struct rlimit alloc_size_limit
|
||||
= {
|
||||
.rlim_cur = FIFTY_ON_BITS,
|
||||
.rlim_max = FIFTY_ON_BITS
|
||||
};
|
||||
|
||||
setrlimit (RLIMIT_AS, &alloc_size_limit);
|
||||
|
||||
#endif /* __WORDSIZE >= 64 */
|
||||
|
||||
DIAG_PUSH_NEEDS_COMMENT;
|
||||
#if __GNUC_PREREQ (7, 0)
|
||||
/* GCC 7 warns about too-large allocations; here we want to test
|
||||
that they fail. */
|
||||
DIAG_IGNORE_NEEDS_COMMENT (7, "-Walloc-size-larger-than=");
|
||||
#endif
|
||||
|
||||
/* Aligned memory allocation functions need to be tested up to alignment
|
||||
size equivalent to page size, which should be a power of 2. */
|
||||
pagesize = sysconf (_SC_PAGESIZE);
|
||||
TEST_VERIFY_EXIT (powerof2 (pagesize));
|
||||
|
||||
/* Loop 1: Ensure that all allocations with SIZE close to SIZE_MAX, i.e.
|
||||
in the range (SIZE_MAX - 2^14, SIZE_MAX], fail.
|
||||
|
||||
We can expect that this range of allocation sizes will always lead to
|
||||
an allocation failure on both 64 and 32 bit targets, because:
|
||||
|
||||
1. no currently supported 64-bit target has an address bus wider than
|
||||
50 bits -- and (2^64 - 2^14) is much wider than that;
|
||||
|
||||
2. on 32-bit targets, even though 2^32 is only 4 GB and potentially
|
||||
addressable, glibc itself is more than 2^14 bytes in size, and
|
||||
therefore once glibc is loaded, less than (2^32 - 2^14) bytes remain
|
||||
available. */
|
||||
|
||||
for (size_t i = 0; i <= FOURTEEN_ON_BITS; i++)
|
||||
{
|
||||
test_large_allocations (SIZE_MAX - i);
|
||||
test_large_aligned_allocations (SIZE_MAX - i);
|
||||
}
|
||||
|
||||
#if __WORDSIZE >= 64
|
||||
/* On 64-bit targets, we need to test a much wider range of too-large
|
||||
sizes, so we test at intervals of (1 << 50) that allocation sizes
|
||||
ranging from SIZE_MAX down to (1 << 50) fail:
|
||||
The 14 MSBs are decremented starting from "all ON" going down to 1,
|
||||
the 50 LSBs are "all ON" and then "all OFF" during every iteration. */
|
||||
for (size_t msbs = FOURTEEN_ON_BITS; msbs >= 1; msbs--)
|
||||
{
|
||||
size_t size = (msbs << 50) | FIFTY_ON_BITS;
|
||||
test_large_allocations (size);
|
||||
test_large_aligned_allocations (size);
|
||||
|
||||
size = msbs << 50;
|
||||
test_large_allocations (size);
|
||||
test_large_aligned_allocations (size);
|
||||
}
|
||||
#endif /* __WORDSIZE >= 64 */
|
||||
|
||||
DIAG_POP_NEEDS_COMMENT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#include <support/test-driver.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;
|
||||
}
|
||||
+38
-1
@@ -237,7 +237,44 @@ function used to read the contents of a directory. It is used if the
|
||||
@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}
|
||||
|
||||
+3
-2
@@ -98,8 +98,9 @@ $(inst_libdir)/libm.so: $(common-objpfx)format.lds \
|
||||
(echo '/* GNU ld script'; echo '*/';\
|
||||
cat $<; \
|
||||
echo 'GROUP ( $(slibdir)/libm.so$(libm.so-version) ' \
|
||||
'AS_NEEDED ( $(slibdir)/libmvec.so$(libmvec.so-version) ) )' \
|
||||
) > $@
|
||||
'AS_NEEDED ( $(libdir)/libmvec_nonshared.a $(slibdir)/libmvec.so$(libmvec.so-version) ) )' \
|
||||
) > $@.new
|
||||
mv -f $@.new $@
|
||||
endif
|
||||
|
||||
# Rules for the test suite.
|
||||
|
||||
@@ -53,11 +53,6 @@ static const mp1 mp_exp1 = {
|
||||
a784d904, 5190cfef, 324e7738, 926cfbe5, f4bf8d8d, 8c31d763)
|
||||
};
|
||||
|
||||
static const mp1 mp_exp_m1 = {
|
||||
CONSTSZ (0, 5e2d58d8, b3bcdf1a, badec782, 9054f90d, da9805aa, b56c7733,
|
||||
3024b9d0, a507daed, b16400bf, 472b4215, b8245b66, 9d90d27a)
|
||||
};
|
||||
|
||||
static const mp1 mp_log2 = {
|
||||
CONSTSZ (0, b17217f7, d1cf79ab, c9e3b398, 03f2f6af, 40f34326, 7298b62d,
|
||||
8a0d175b, 8baafa2b, e7b87620, 6debac98, 559552fb, 4afa1b10)
|
||||
|
||||
+2
-1
@@ -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 bug18240
|
||||
ifeq ($(run-built-tests),yes)
|
||||
tests-special += $(objpfx)tst-error1-mem.out
|
||||
endif
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
/* 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>
|
||||
#include <sys/resource.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)
|
||||
{
|
||||
/* 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);
|
||||
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"
|
||||
+18
-12
@@ -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
|
||||
@@ -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
|
||||
@@ -81,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;
|
||||
|
||||
+3
-1
@@ -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';
|
||||
}
|
||||
|
||||
+5
-4
@@ -19,10 +19,11 @@
|
||||
#ifndef _REGEXP_H
|
||||
#define _REGEXP_H 1
|
||||
|
||||
/* The contents of this header file were standardized in the
|
||||
Single Unix Specification, Version 2 (1997) but marked as
|
||||
LEGACY; new applications were already being encouraged to
|
||||
use <regex.h> instead. POSIX.1-2001 removed this header.
|
||||
/* The contents of this header file were originally standardized in
|
||||
the Single Unix Specification, Issue 3 (1992). In Issue 4 (1994)
|
||||
the header was marked as TO BE WITHDRAWN, and new applications
|
||||
were encouraged to use <regex.h> instead. It was officially
|
||||
withdrawn from the standard in Issue 6 (aka POSIX.1-2001).
|
||||
|
||||
This header is provided only for backward compatibility.
|
||||
It will be removed in the next release of the GNU C Library.
|
||||
|
||||
@@ -50,6 +50,9 @@
|
||||
#if !defined NOFILE && defined OPEN_MAX
|
||||
# define NOFILE OPEN_MAX
|
||||
#endif
|
||||
#if !defined MAXHOSTNAMELEN && defined HOST_NAME_MAX
|
||||
# define MAXHOSTNAMELEN HOST_NAME_MAX
|
||||
#endif
|
||||
#ifndef NCARGS
|
||||
# ifdef ARG_MAX
|
||||
# define NCARGS ARG_MAX
|
||||
|
||||
@@ -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"
|
||||
@@ -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"
|
||||
@@ -73,26 +73,6 @@ main (int argc, char *argv[])
|
||||
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;
|
||||
|
||||
+11
-9
@@ -680,16 +680,18 @@ nis_server_cache_add (const_nis_name name, int search_parent,
|
||||
/* Choose which entry should be evicted from the cache. */
|
||||
loc = &nis_server_cache[0];
|
||||
if (*loc != NULL)
|
||||
for (i = 1; i < 16; ++i)
|
||||
if (nis_server_cache[i] == NULL)
|
||||
{
|
||||
{
|
||||
for (i = 1; i < 16; ++i)
|
||||
if (nis_server_cache[i] == NULL)
|
||||
{
|
||||
loc = &nis_server_cache[i];
|
||||
break;
|
||||
}
|
||||
else if ((*loc)->uses > nis_server_cache[i]->uses
|
||||
|| ((*loc)->uses == nis_server_cache[i]->uses
|
||||
&& (*loc)->expires > nis_server_cache[i]->expires))
|
||||
loc = &nis_server_cache[i];
|
||||
break;
|
||||
}
|
||||
else if ((*loc)->uses > nis_server_cache[i]->uses
|
||||
|| ((*loc)->uses == nis_server_cache[i]->uses
|
||||
&& (*loc)->expires > nis_server_cache[i]->expires))
|
||||
loc = &nis_server_cache[i];
|
||||
}
|
||||
old = *loc;
|
||||
*loc = new;
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
+10
-33
@@ -25,48 +25,25 @@
|
||||
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.
|
||||
|
||||
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. */
|
||||
|
||||
#if SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_22)
|
||||
|
||||
# if HAVE_IFUNC
|
||||
|
||||
static __typeof (fork) *
|
||||
__attribute__ ((used))
|
||||
fork_resolve (void)
|
||||
{
|
||||
return &__libc_fork;
|
||||
}
|
||||
|
||||
# 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 */
|
||||
|
||||
static pid_t __attribute__ ((used))
|
||||
fork_compat (void)
|
||||
{
|
||||
return __libc_fork ();
|
||||
}
|
||||
|
||||
# define DEFINE_FORK(name) strong_alias (fork_compat, name)
|
||||
strong_alias (fork_compat, fork_alias)
|
||||
compat_symbol (libpthread, fork_alias, fork, GLIBC_2_0);
|
||||
|
||||
# endif /* HAVE_IFUNC */
|
||||
|
||||
DEFINE_FORK (fork_ifunc)
|
||||
compat_symbol (libpthread, fork_ifunc, 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
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
#include <stap-probe.h>
|
||||
|
||||
#ifndef lll_unlock_elision
|
||||
#define lll_unlock_elision(a,b) ({ lll_unlock (a,b); 0; })
|
||||
#define lll_unlock_elision(a,b,c) ({ lll_unlock (a,c); 0; })
|
||||
#endif
|
||||
|
||||
static int
|
||||
@@ -63,7 +63,7 @@ __pthread_mutex_unlock_usercnt (mutex, decr)
|
||||
else if (__glibc_likely (type == PTHREAD_MUTEX_TIMED_ELISION_NP))
|
||||
{
|
||||
/* Don't reset the owner/users fields for elision. */
|
||||
return lll_unlock_elision (mutex->__data.__lock,
|
||||
return lll_unlock_elision (mutex->__data.__lock, mutex->__data.__elision,
|
||||
PTHREAD_MUTEX_PSHARED (mutex));
|
||||
}
|
||||
else if (__builtin_expect (PTHREAD_MUTEX_TYPE (mutex)
|
||||
|
||||
@@ -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"
|
||||
|
||||
+9
-3
@@ -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)
|
||||
{
|
||||
@@ -288,8 +294,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;
|
||||
}
|
||||
|
||||
|
||||
+11
-3
@@ -43,7 +43,7 @@ routines := \
|
||||
getpgid setpgid getpgrp bsd-getpgrp setpgrp getsid setsid \
|
||||
getresuid getresgid setresuid setresgid \
|
||||
pathconf sysconf fpathconf \
|
||||
glob glob64 fnmatch regex \
|
||||
glob glob64 globfree globfree64 glob_pattern_p fnmatch regex \
|
||||
confstr \
|
||||
getopt getopt1 getopt_init \
|
||||
sched_setp sched_getp sched_sets sched_gets sched_yield sched_primax \
|
||||
@@ -87,7 +87,8 @@ tests := tstgetopt testfnm runtests runptests \
|
||||
bug-getopt1 bug-getopt2 bug-getopt3 bug-getopt4 \
|
||||
bug-getopt5 tst-getopt_long1 bug-regex34 bug-regex35 \
|
||||
tst-pathconf tst-getaddrinfo4 tst-rxspencer-no-utf8 \
|
||||
tst-fnmatch3 bug-regex36 tst-getaddrinfo5
|
||||
tst-fnmatch3 bug-regex36 tst-getaddrinfo5 \
|
||||
tst-glob-tilde
|
||||
xtests := bug-ga2
|
||||
ifeq (yes,$(build-shared))
|
||||
test-srcs := globtest
|
||||
@@ -130,7 +131,8 @@ tests-special += $(objpfx)bug-regex2-mem.out $(objpfx)bug-regex14-mem.out \
|
||||
$(objpfx)tst-rxspencer-no-utf8-mem.out $(objpfx)tst-pcre-mem.out \
|
||||
$(objpfx)tst-boost-mem.out $(objpfx)tst-getconf.out \
|
||||
$(objpfx)bug-glob2-mem.out $(objpfx)tst-vfork3-mem.out \
|
||||
$(objpfx)tst-fnmatch-mem.out $(objpfx)bug-regex36-mem.out
|
||||
$(objpfx)tst-fnmatch-mem.out $(objpfx)bug-regex36-mem.out \
|
||||
$(objpfx)tst-glob-tilde-mem.out
|
||||
xtests-special += $(objpfx)bug-ga2-mem.out
|
||||
endif
|
||||
|
||||
@@ -307,6 +309,12 @@ $(objpfx)bug-glob2-mem.out: $(objpfx)bug-glob2.out
|
||||
$(common-objpfx)malloc/mtrace $(objpfx)bug-glob2.mtrace > $@; \
|
||||
$(evaluate-test)
|
||||
|
||||
tst-glob-tilde-ENV = MALLOC_TRACE=$(objpfx)tst-glob-tilde.mtrace
|
||||
|
||||
$(objpfx)tst-glob-tilde-mem.out: $(objpfx)tst-glob-tilde.out
|
||||
$(common-objpfx)malloc/mtrace $(objpfx)tst-glob-tilde.mtrace > $@; \
|
||||
$(evaluate-test)
|
||||
|
||||
$(inst_libexecdir)/getconf: $(inst_bindir)/getconf \
|
||||
$(objpfx)getconf.speclist FORCE
|
||||
$(addprefix $(..)./scripts/mkinstalldirs ,\
|
||||
|
||||
+14
-2
@@ -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;
|
||||
|
||||
|
||||
@@ -193,7 +205,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,45 @@
|
||||
/* Sizes of structs with flexible array members.
|
||||
|
||||
Copyright 2016-2017 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/>.
|
||||
|
||||
Written by Paul Eggert. */
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
/* Nonzero multiple of alignment of TYPE, suitable for FLEXSIZEOF below.
|
||||
On older platforms without _Alignof, use a pessimistic bound that is
|
||||
safe in practice even if FLEXIBLE_ARRAY_MEMBER is 1.
|
||||
On newer platforms, use _Alignof to get a tighter bound. */
|
||||
|
||||
#if !defined __STDC_VERSION__ || __STDC_VERSION__ < 201112
|
||||
# define FLEXALIGNOF(type) (sizeof (type) & ~ (sizeof (type) - 1))
|
||||
#else
|
||||
# define FLEXALIGNOF(type) _Alignof (type)
|
||||
#endif
|
||||
|
||||
/* Upper bound on the size of a struct of type TYPE with a flexible
|
||||
array member named MEMBER that is followed by N bytes of other data.
|
||||
This is not simply sizeof (TYPE) + N, since it may require
|
||||
alignment on unusually picky C11 platforms, and
|
||||
FLEXIBLE_ARRAY_MEMBER may be 1 on pre-C11 platforms.
|
||||
Yield a value less than N if and only if arithmetic overflow occurs. */
|
||||
|
||||
#define FLEXSIZEOF(type, member, n) \
|
||||
((offsetof (type, member) + FLEXALIGNOF (type) - 1 + (n)) \
|
||||
& ~ (FLEXALIGNOF (type) - 1))
|
||||
+454
-486
File diff suppressed because it is too large
Load Diff
@@ -43,10 +43,4 @@ glob64 (const char *pattern, int flags,
|
||||
}
|
||||
libc_hidden_def (glob64)
|
||||
|
||||
void
|
||||
globfree64 (glob64_t *pglob)
|
||||
{
|
||||
}
|
||||
libc_hidden_def (globfree64)
|
||||
|
||||
stub_warning (glob64)
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
/* Shared definition for glob and glob_pattern_p.
|
||||
Copyright (C) 2017 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/>. */
|
||||
|
||||
#ifndef GLOB_INTERNAL_H
|
||||
# define GLOB_INTERNAL_H
|
||||
|
||||
static inline int
|
||||
__glob_pattern_type (const char *pattern, int quote)
|
||||
{
|
||||
const char *p;
|
||||
int ret = 0;
|
||||
|
||||
for (p = pattern; *p != '\0'; ++p)
|
||||
switch (*p)
|
||||
{
|
||||
case '?':
|
||||
case '*':
|
||||
return 1;
|
||||
|
||||
case '\\':
|
||||
if (quote)
|
||||
{
|
||||
if (p[1] != '\0')
|
||||
++p;
|
||||
ret |= 2;
|
||||
}
|
||||
break;
|
||||
|
||||
case '[':
|
||||
ret |= 4;
|
||||
break;
|
||||
|
||||
case ']':
|
||||
if (ret & 4)
|
||||
return 1;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* GLOB_INTERNAL_H */
|
||||
@@ -0,0 +1,33 @@
|
||||
/* Return nonzero if PATTERN contains any metacharacters.
|
||||
Copyright (C) 2017 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/>. */
|
||||
|
||||
#ifndef _LIBC
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <glob.h>
|
||||
#include "glob_internal.h"
|
||||
|
||||
/* Return nonzero if PATTERN contains any metacharacters.
|
||||
Metacharacters can be quoted with backslashes if QUOTE is nonzero. */
|
||||
int
|
||||
__glob_pattern_p (const char *pattern, int quote)
|
||||
{
|
||||
return __glob_pattern_type (pattern, quote) == 1;
|
||||
}
|
||||
weak_alias (__glob_pattern_p, glob_pattern_p)
|
||||
@@ -0,0 +1,41 @@
|
||||
/* Frees the dynamically allocated storage from an earlier call to glob.
|
||||
Copyright (C) 2017 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/>. */
|
||||
|
||||
#ifndef _LIBC
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <glob.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Free storage allocated in PGLOB by a previous `glob' call. */
|
||||
void
|
||||
globfree (glob_t *pglob)
|
||||
{
|
||||
if (pglob->gl_pathv != NULL)
|
||||
{
|
||||
size_t i;
|
||||
for (i = 0; i < pglob->gl_pathc; ++i)
|
||||
free (pglob->gl_pathv[pglob->gl_offs + i]);
|
||||
free (pglob->gl_pathv);
|
||||
pglob->gl_pathv = NULL;
|
||||
}
|
||||
}
|
||||
#ifndef globfree
|
||||
libc_hidden_def (globfree)
|
||||
#endif
|
||||
@@ -0,0 +1,31 @@
|
||||
/* Frees the dynamically allocated storage from an earlier call to glob.
|
||||
Copyright (C) 2017 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/>. */
|
||||
|
||||
#ifndef _LIBC
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <glob.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Free storage allocated in PGLOB by a previous `glob' call. */
|
||||
void
|
||||
globfree64 (glob64_t *pglob)
|
||||
{
|
||||
}
|
||||
libc_hidden_def (globfree64)
|
||||
@@ -0,0 +1,136 @@
|
||||
/* Check for GLOB_TIDLE heap allocation issues (bug 22320, bug 22325).
|
||||
Copyright (C) 2017 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 <glob.h>
|
||||
#include <mcheck.h>
|
||||
#include <nss.h>
|
||||
#include <pwd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <support/check.h>
|
||||
#include <support/support.h>
|
||||
|
||||
/* Flag which indicates whether to pass the GLOB_ONLYDIR flag. */
|
||||
static int do_onlydir;
|
||||
|
||||
/* Flag which indicates whether to pass the GLOB_NOCHECK flag. */
|
||||
static int do_nocheck;
|
||||
|
||||
/* Flag which indicates whether to pass the GLOB_MARK flag. */
|
||||
static int do_mark;
|
||||
|
||||
static void
|
||||
one_test (const char *prefix, const char *middle, const char *suffix)
|
||||
{
|
||||
char *pattern = xasprintf ("%s%s%s", prefix, middle, suffix);
|
||||
int flags = GLOB_TILDE;
|
||||
if (do_onlydir)
|
||||
flags |= GLOB_ONLYDIR;
|
||||
if (do_nocheck)
|
||||
flags |= GLOB_NOCHECK;
|
||||
if (do_mark)
|
||||
flags |= GLOB_MARK;
|
||||
glob_t gl;
|
||||
/* This glob call might result in crashes or memory leaks. */
|
||||
if (glob (pattern, flags, NULL, &gl) == 0)
|
||||
globfree (&gl);
|
||||
free (pattern);
|
||||
}
|
||||
|
||||
enum
|
||||
{
|
||||
/* The largest base being tested. */
|
||||
largest_base_size = 500000,
|
||||
|
||||
/* The actual size is the base size plus a variable whose absolute
|
||||
value is not greater than this. This helps malloc to trigger
|
||||
overflows. */
|
||||
max_size_skew = 16,
|
||||
|
||||
/* The maximum string length supported by repeating_string
|
||||
below. */
|
||||
repeat_size = largest_base_size + max_size_skew,
|
||||
};
|
||||
|
||||
/* Used to construct strings which repeat a single character 'x'. */
|
||||
static char *repeat;
|
||||
|
||||
/* Return a string of SIZE characters. */
|
||||
const char *
|
||||
repeating_string (int size)
|
||||
{
|
||||
TEST_VERIFY (size >= 0);
|
||||
TEST_VERIFY (size <= repeat_size);
|
||||
const char *repeated_shifted = repeat + repeat_size - size;
|
||||
TEST_VERIFY (strlen (repeated_shifted) == size);
|
||||
return repeated_shifted;
|
||||
}
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
/* Avoid network-based NSS modules and initialize nss_files with a
|
||||
dummy lookup. This has to come before mtrace because NSS does
|
||||
not free all memory. */
|
||||
__nss_configure_lookup ("passwd", "files");
|
||||
(void) getpwnam ("root");
|
||||
|
||||
mtrace ();
|
||||
|
||||
repeat = xmalloc (repeat_size + 1);
|
||||
memset (repeat, 'x', repeat_size);
|
||||
repeat[repeat_size] = '\0';
|
||||
|
||||
/* These numbers control the size of the user name. The values
|
||||
cover the minimum (0), a typical size (8), a large
|
||||
stack-allocated size (100000), and a somewhat large
|
||||
heap-allocated size (largest_base_size). */
|
||||
static const int base_sizes[] = { 0, 8, 100, 100000, largest_base_size, -1 };
|
||||
|
||||
for (do_onlydir = 0; do_onlydir < 2; ++do_onlydir)
|
||||
for (do_nocheck = 0; do_nocheck < 2; ++do_nocheck)
|
||||
for (do_mark = 0; do_mark < 2; ++do_mark)
|
||||
for (int base_idx = 0; base_sizes[base_idx] >= 0; ++base_idx)
|
||||
{
|
||||
for (int size_skew = -max_size_skew; size_skew <= max_size_skew;
|
||||
++size_skew)
|
||||
{
|
||||
int size = base_sizes[base_idx] + size_skew;
|
||||
if (size < 0)
|
||||
continue;
|
||||
|
||||
const char *user_name = repeating_string (size);
|
||||
one_test ("~", user_name, "/a/b");
|
||||
}
|
||||
|
||||
const char *user_name = repeating_string (base_sizes[base_idx]);
|
||||
one_test ("~", user_name, "");
|
||||
one_test ("~", user_name, "/");
|
||||
one_test ("~", user_name, "/a");
|
||||
one_test ("~", user_name, "/*/*");
|
||||
one_test ("~", user_name, "\\/");
|
||||
one_test ("/~", user_name, "");
|
||||
one_test ("*/~", user_name, "/a/b");
|
||||
}
|
||||
|
||||
free (repeat);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include <support/test-driver.c>
|
||||
+1
-1
@@ -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;
|
||||
|
||||
@@ -40,10 +40,6 @@
|
||||
* IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
||||
*/
|
||||
|
||||
#if !defined(LINT) && !defined(CODECENTER)
|
||||
static const char rcsid[] = "$BINDId: base64.c,v 8.7 1999/10/13 16:39:33 vixie Exp $";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
+109
-2
@@ -1031,7 +1031,10 @@ gaih_getanswer_slice (const querybuf *answer, int anslen, const char *qname,
|
||||
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 *answer, int anslen, const char *qname,
|
||||
/* 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, int anslen1, const querybuf *answer2,
|
||||
|
||||
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 implementation of send_dg
|
||||
and send_vc to see response can arrive in any order, particularly
|
||||
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, int anslen1, const querybuf *answer2,
|
||||
&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;
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
+1
-1
@@ -593,7 +593,7 @@ __res_iclose(res_state statp, bool free_addr) {
|
||||
statp->_vcsock = -1;
|
||||
statp->_flags &= ~(RES_F_VC | RES_F_CONN);
|
||||
}
|
||||
for (ns = 0; ns < statp->_u._ext.nscount; ns++)
|
||||
for (ns = 0; ns < statp->nscount; ns++)
|
||||
if (statp->_u._ext.nsaddrs[ns]) {
|
||||
if (statp->_u._ext.nssocks[ns] != -1) {
|
||||
close_not_cancel_no_status(statp->_u._ext.nssocks[ns]);
|
||||
|
||||
@@ -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)
|
||||
|
||||
+237
-90
@@ -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.
|
||||
@@ -363,6 +380,8 @@ __libc_res_nsend(res_state statp, const u_char *buf, int buflen,
|
||||
#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);
|
||||
@@ -638,6 +657,89 @@ get_nsaddr (res_state statp, int n)
|
||||
return (struct sockaddr *) (void *) &statp->nsaddr_list[n];
|
||||
}
|
||||
|
||||
/* 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
|
||||
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 field 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,
|
||||
@@ -647,11 +749,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 *nsap = get_nsaddr (statp, ns);
|
||||
int truncating, connreset, n;
|
||||
/* On some architectures compiler might emit a warning indicating
|
||||
@@ -743,6 +841,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:
|
||||
@@ -779,40 +879,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;
|
||||
@@ -820,10 +894,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 not the 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;
|
||||
@@ -835,6 +913,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,
|
||||
@@ -997,6 +1078,66 @@ reopen (res_state statp, int *terrno, int ns)
|
||||
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 field 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,
|
||||
@@ -1006,8 +1147,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;
|
||||
@@ -1032,7 +1171,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);
|
||||
@@ -1040,11 +1183,11 @@ 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;
|
||||
if (resplen2 != NULL)
|
||||
*resplen2 = 0;
|
||||
wait:
|
||||
if (need_recompute) {
|
||||
recompute_resend:
|
||||
@@ -1052,9 +1195,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;
|
||||
@@ -1101,7 +1242,9 @@ send_dg(res_state statp,
|
||||
}
|
||||
|
||||
*gotsomewhere = 1;
|
||||
return (0);
|
||||
if (resplen2 != NULL)
|
||||
*resplen2 = 0;
|
||||
return 0;
|
||||
}
|
||||
if (n < 0) {
|
||||
if (errno == EINTR)
|
||||
@@ -1169,7 +1312,7 @@ send_dg(res_state statp,
|
||||
|
||||
fail_sendmmsg:
|
||||
Perror(statp, stderr, "sendmmsg", errno);
|
||||
goto err_out;
|
||||
return close_and_return_error (statp, resplen2);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -1187,7 +1330,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)
|
||||
@@ -1203,55 +1346,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 not the 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);
|
||||
@@ -1264,7 +1408,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)) {
|
||||
@@ -1275,7 +1419,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)) {
|
||||
@@ -1324,7 +1468,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)
|
||||
@@ -1376,10 +1520,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) {
|
||||
@@ -1401,6 +1545,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. */
|
||||
@@ -1416,21 +1562,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,110 @@
|
||||
#!/bin/bash
|
||||
# Create a patch which backports the support/ subdirectory.
|
||||
# Copyright (C) 2017 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 script does not backport the Makefile tweaks outside the
|
||||
# support/ directory (which need to be backported separately), or the
|
||||
# changes to test-skeleton.c (which should not be backported).
|
||||
|
||||
set -e
|
||||
|
||||
export LC_ALL=C
|
||||
export GIT_CONFIG=/dev/null
|
||||
export GTT_CONFIG_NOSYSTEM=0
|
||||
export GIT_PAGER=
|
||||
|
||||
usage () {
|
||||
cat >&2 <<EOF
|
||||
usage: $0 {patch|commit}
|
||||
EOF
|
||||
exit 1
|
||||
}
|
||||
|
||||
if test $# -ne 1 ; then
|
||||
usage
|
||||
fi
|
||||
|
||||
command="$1"
|
||||
|
||||
case "$command" in
|
||||
patch|commit)
|
||||
;;
|
||||
*)
|
||||
usage
|
||||
;;
|
||||
esac
|
||||
|
||||
# The upstream branch to work on.
|
||||
branch=origin/master
|
||||
|
||||
# The commit which added the support/ directory.
|
||||
initial_commit=c23de0aacbeaa7a091609b35764bed931475a16d
|
||||
|
||||
# We backport the support directory and this script. Directories need
|
||||
# to end in a /.
|
||||
patch_targets="support/ scripts/backport-support.sh"
|
||||
|
||||
latest_commit="$(git log --max-count=1 --pretty=format:%H "$branch" -- \
|
||||
$patch_targets)"
|
||||
|
||||
# Simplify the branch name somewhat for reporting.
|
||||
branch_name="$(echo "$branch" | sed s,^origin/,,)"
|
||||
|
||||
command_patch () {
|
||||
cat <<EOF
|
||||
This patch creates the contents of the support/ directory up to this
|
||||
upstream commit on the $branch_name branch:
|
||||
|
||||
EOF
|
||||
git log --max-count=1 "$latest_commit"
|
||||
echo
|
||||
git diff "$initial_commit"^.."$latest_commit" $patch_targets
|
||||
echo "# Before applying the patch, run this command:" >&2
|
||||
echo "# rm -rf $patch_targets" >&2
|
||||
}
|
||||
|
||||
command_commit () {
|
||||
git status --porcelain | while read line ; do
|
||||
echo "error: working copy is not clean, cannot commit" >&2
|
||||
exit 1
|
||||
done
|
||||
for path in $patch_targets; do
|
||||
echo "# Processing $path" >&2
|
||||
case "$path" in
|
||||
[a-zA-Z0-9]*/)
|
||||
# Directory.
|
||||
git rm --cached --ignore-unmatch -r "$path"
|
||||
rm -rf "$path"
|
||||
git read-tree --prefix="$path" "$latest_commit":"$path"
|
||||
git checkout "$path"
|
||||
;;
|
||||
*)
|
||||
# File.
|
||||
git show "$latest_commit":"$path" > "$path"
|
||||
git add "$path"
|
||||
esac
|
||||
done
|
||||
git commit -m "Synchronize support/ infrastructure with $branch_name
|
||||
|
||||
This commit updates the support/ subdirectory to
|
||||
commit $latest_commit
|
||||
on the $branch_name branch.
|
||||
"
|
||||
}
|
||||
|
||||
command_$command
|
||||
@@ -80,16 +80,25 @@ arglist: while (@ARGV) {
|
||||
# We expect none or one argument.
|
||||
if ($#ARGV == -1) {
|
||||
$soversions="soversions.mk";
|
||||
$config="config.make";
|
||||
} elsif ($#ARGV == 0) {
|
||||
if (-d $ARGV[0]) {
|
||||
$soversions = "$ARGV[0]/soversions.mk";
|
||||
$config = "$ARGV[0]/config.make";
|
||||
} else {
|
||||
$soversions = $ARGV[0];
|
||||
$soversions = $dir = $ARGV[0];
|
||||
$dir =~ s!/?[^/]*/*$!!;
|
||||
$config = $dir . "/config.make";
|
||||
}
|
||||
} else {
|
||||
die "Wrong number of arguments.";
|
||||
}
|
||||
|
||||
if (system ("grep -q \"build-mathvec = yes\" $config") == 0) {
|
||||
$build_mathvec = 1;
|
||||
} else {
|
||||
$build_mathvec = 0;
|
||||
}
|
||||
|
||||
# Read names and versions of all shared libraries that are part of
|
||||
# glibc
|
||||
@@ -111,6 +120,8 @@ while (<SOVERSIONS>) {
|
||||
# - libthread_db since it contains unresolved references
|
||||
# - it's just a test NSS module
|
||||
# - We don't provide the libgcc so we don't test it
|
||||
# - libmvec if it wasn't built
|
||||
next if ($build_mathvec == 0 && $name eq "mvec");
|
||||
if ($name ne "nss_ldap" && $name ne "db1"
|
||||
&& !($name =~/^nss1_/) && $name ne "thread_db"
|
||||
&& $name ne "nss_test1" && $name ne "libgcc_s") {
|
||||
|
||||
@@ -38,11 +38,11 @@ do_test (void)
|
||||
# define COMPARE_LDBL(u, v) ((u).l == (v).l)
|
||||
#endif
|
||||
|
||||
#define TEST(val) \
|
||||
#define TEST_N(val, n) \
|
||||
do \
|
||||
{ \
|
||||
u.l = (val); \
|
||||
snprintf (buf, sizeof buf, "%.30LgL", u.l); \
|
||||
snprintf (buf, sizeof buf, "%." #n "LgL", u.l); \
|
||||
if (strcmp (buf, #val) != 0) \
|
||||
{ \
|
||||
printf ("Error on line %d: %s != %s\n", __LINE__, buf, #val); \
|
||||
@@ -50,19 +50,25 @@ do_test (void)
|
||||
} \
|
||||
if (sscanf (#val, "%Lg", &v.l) != 1 || !COMPARE_LDBL (u, v)) \
|
||||
{ \
|
||||
printf ("Error sscanf on line %d: %.30Lg != %.30Lg\n", __LINE__, \
|
||||
u.l, v.l); \
|
||||
printf ("Error sscanf on line %d: %." #n "Lg != %." #n "Lg\n", \
|
||||
__LINE__, u.l, v.l); \
|
||||
result = 1; \
|
||||
} \
|
||||
/* printf ("%s %Lg %016Lx %016Lx\n", #val, u.l, u.x[0], u.x[1]); */ \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
#define TEST(val) TEST_N (val,30)
|
||||
|
||||
#if LDBL_MANT_DIG >= 106
|
||||
# if LDBL_MANT_DIG == 106
|
||||
TEST (2.22507385850719347803989925739e-308L);
|
||||
TEST (2.22507385850719397210554509863e-308L);
|
||||
TEST (2.22507385850720088902458687609e-308L);
|
||||
|
||||
/* Verify precision is not lost for long doubles
|
||||
of the form +1.pN,-1.pM. */
|
||||
TEST_N (3.32306998946228968225951765070082e+35L, 34);
|
||||
# endif
|
||||
TEST (2.22507385850720138309023271733e-308L);
|
||||
TEST (2.22507385850720187715587855858e-308L);
|
||||
|
||||
@@ -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
|
||||
|
||||
+13
-11
@@ -289,18 +289,20 @@ unsetenv (name)
|
||||
ep = __environ;
|
||||
if (ep != NULL)
|
||||
while (*ep != NULL)
|
||||
if (!strncmp (*ep, name, len) && (*ep)[len] == '=')
|
||||
{
|
||||
/* Found it. Remove this pointer by moving later ones back. */
|
||||
char **dp = ep;
|
||||
{
|
||||
if (!strncmp (*ep, name, len) && (*ep)[len] == '=')
|
||||
{
|
||||
/* Found it. Remove this pointer by moving later ones back. */
|
||||
char **dp = ep;
|
||||
|
||||
do
|
||||
dp[0] = dp[1];
|
||||
while (*dp++);
|
||||
/* Continue the loop in case NAME appears again. */
|
||||
}
|
||||
else
|
||||
++ep;
|
||||
do
|
||||
dp[0] = dp[1];
|
||||
while (*dp++);
|
||||
/* Continue the loop in case NAME appears again. */
|
||||
}
|
||||
else
|
||||
++ep;
|
||||
}
|
||||
|
||||
UNLOCK;
|
||||
|
||||
|
||||
+14
-1
@@ -54,7 +54,7 @@ tests := tester inl-tester noinl-tester testcopy test-ffs \
|
||||
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,17 @@ 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
|
||||
|
||||
@@ -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"
|
||||
+1
-37
@@ -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 STRING_TYPE *s2, __locale_t l)
|
||||
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 STRING_TYPE *s2, __locale_t l)
|
||||
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;
|
||||
|
||||
@@ -3,6 +3,20 @@
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <libc-internal.h>
|
||||
|
||||
#if __GNUC_PREREQ (6, 0)
|
||||
/* GCC 6.0 warns on big endian systems about:
|
||||
htobeXX (beXXtoh (i)) != i
|
||||
warning: self-comparison always evaluates to false [-Wtautological-compare]
|
||||
because htobeXX(x) and beXXtoh(x) is defined to (x)
|
||||
in string/endian.h on big endian systems.
|
||||
The same applies to htoleXX/leXXtoh on little endian systems. */
|
||||
# define DIAG_IGNORE_NEEDS_COMMENT_TAUTOLOGICAL_COMPARE() \
|
||||
DIAG_IGNORE_NEEDS_COMMENT (6, "-Wtautological-compare")
|
||||
#else
|
||||
# define DIAG_IGNORE_NEEDS_COMMENT_TAUTOLOGICAL_COMPARE()
|
||||
#endif
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
@@ -13,6 +27,8 @@ do_test (void)
|
||||
{
|
||||
if (i < UINT64_C (65536))
|
||||
{
|
||||
DIAG_PUSH_NEEDS_COMMENT;
|
||||
DIAG_IGNORE_NEEDS_COMMENT_TAUTOLOGICAL_COMPARE ();
|
||||
if (htobe16 (be16toh (i)) != i)
|
||||
{
|
||||
printf ("htobe16 (be16toh (%" PRIx64 ")) == %" PRIx16 "\n",
|
||||
@@ -25,6 +41,7 @@ do_test (void)
|
||||
i, (uint16_t) htole16 (le16toh (i)));
|
||||
result = 1;
|
||||
}
|
||||
DIAG_POP_NEEDS_COMMENT;
|
||||
|
||||
uint16_t n[2];
|
||||
n[__BYTE_ORDER == __LITTLE_ENDIAN] = bswap_16 (i);
|
||||
@@ -45,6 +62,8 @@ do_test (void)
|
||||
|
||||
if (i < UINT64_C (4294967296))
|
||||
{
|
||||
DIAG_PUSH_NEEDS_COMMENT;
|
||||
DIAG_IGNORE_NEEDS_COMMENT_TAUTOLOGICAL_COMPARE ();
|
||||
if (htobe32 (be32toh (i)) != i)
|
||||
{
|
||||
printf ("htobe32 (be32toh (%" PRIx64 ")) == %" PRIx32 "\n",
|
||||
@@ -57,6 +76,7 @@ do_test (void)
|
||||
i, (uint32_t) htole32 (le32toh (i)));
|
||||
result = 1;
|
||||
}
|
||||
DIAG_POP_NEEDS_COMMENT;
|
||||
|
||||
uint32_t n[2];
|
||||
n[__BYTE_ORDER == __LITTLE_ENDIAN] = bswap_32 (i);
|
||||
@@ -75,6 +95,8 @@ do_test (void)
|
||||
}
|
||||
}
|
||||
|
||||
DIAG_PUSH_NEEDS_COMMENT;
|
||||
DIAG_IGNORE_NEEDS_COMMENT_TAUTOLOGICAL_COMPARE ();
|
||||
if (htobe64 (be64toh (i)) != i)
|
||||
{
|
||||
printf ("htobe64 (be64toh (%" PRIx64 ")) == %" PRIx64 "\n",
|
||||
@@ -87,6 +109,7 @@ do_test (void)
|
||||
i, htole64 (le64toh (i)));
|
||||
result = 1;
|
||||
}
|
||||
DIAG_POP_NEEDS_COMMENT;
|
||||
|
||||
uint64_t n[2];
|
||||
n[__BYTE_ORDER == __LITTLE_ENDIAN] = bswap_64 (i);
|
||||
|
||||
@@ -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
|
||||
|
||||
+2
-1
@@ -96,7 +96,7 @@ rpcgen-objs = rpc_main.o rpc_hout.o rpc_cout.o rpc_parse.o \
|
||||
extra-objs = $(rpcgen-objs) $(addprefix cross-,$(rpcgen-objs))
|
||||
others += rpcgen
|
||||
|
||||
tests = tst-xdrmem tst-xdrmem2 test-rpcent
|
||||
tests = tst-xdrmem tst-xdrmem2 test-rpcent tst-udp-error
|
||||
xtests := tst-getmyaddr
|
||||
|
||||
ifeq ($(have-thread-library),yes)
|
||||
@@ -153,6 +153,7 @@ BUILD_CPPFLAGS += $(sunrpc-CPPFLAGS)
|
||||
$(objpfx)tst-getmyaddr: $(common-objpfx)linkobj/libc.so
|
||||
$(objpfx)tst-xdrmem: $(common-objpfx)linkobj/libc.so
|
||||
$(objpfx)tst-xdrmem2: $(common-objpfx)linkobj/libc.so
|
||||
$(objpfx)tst-udp-error: $(common-objpfx)linkobj/libc.so
|
||||
|
||||
$(objpfx)rpcgen: $(addprefix $(objpfx),$(rpcgen-objs))
|
||||
|
||||
|
||||
+9
-1
@@ -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;
|
||||
@@ -449,8 +455,10 @@ send_again:
|
||||
{
|
||||
e = (struct sock_extended_err *) CMSG_DATA(cmsg);
|
||||
cu->cu_error.re_errno = e->ee_errno;
|
||||
free (cbuf);
|
||||
return (cu->cu_error.re_status = RPC_CANTRECV);
|
||||
}
|
||||
free (cbuf);
|
||||
}
|
||||
#endif
|
||||
do
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
/* Check for use-after-free in clntudp_call (bug 21115).
|
||||
Copyright (C) 2017 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 <netinet/in.h>
|
||||
#include <rpc/clnt.h>
|
||||
#include <rpc/svc.h>
|
||||
#include <support/check.h>
|
||||
#include <support/namespace.h>
|
||||
#include <support/xsocket.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
support_become_root ();
|
||||
support_enter_network_namespace ();
|
||||
|
||||
/* Obtain a likely-unused port number. */
|
||||
struct sockaddr_in sin =
|
||||
{
|
||||
.sin_family = AF_INET,
|
||||
.sin_addr.s_addr = htonl (INADDR_LOOPBACK),
|
||||
};
|
||||
{
|
||||
int fd = xsocket (AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
|
||||
xbind (fd, (struct sockaddr *) &sin, sizeof (sin));
|
||||
socklen_t sinlen = sizeof (sin);
|
||||
xgetsockname (fd, (struct sockaddr *) &sin, &sinlen);
|
||||
/* Close the socket, so that we will receive an error below. */
|
||||
close (fd);
|
||||
}
|
||||
|
||||
int sock = RPC_ANYSOCK;
|
||||
CLIENT *clnt = clntudp_create
|
||||
(&sin, 1, 2, (struct timeval) { 1, 0 }, &sock);
|
||||
TEST_VERIFY_EXIT (clnt != NULL);
|
||||
TEST_VERIFY (clnt_call (clnt, 3,
|
||||
(xdrproc_t) xdr_void, NULL,
|
||||
(xdrproc_t) xdr_void, NULL,
|
||||
((struct timeval) { 3, 0 }))
|
||||
== RPC_CANTRECV);
|
||||
clnt_destroy (clnt);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include <support/test-driver.c>
|
||||
@@ -0,0 +1,146 @@
|
||||
# Makefile for support library, used only at build and test time
|
||||
# Copyright (C) 2016-2017 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/>.
|
||||
|
||||
subdir := support
|
||||
|
||||
include ../Makeconfig
|
||||
|
||||
extra-libs := libsupport
|
||||
extra-libs-others = $(extra-libs)
|
||||
extra-libs-noinstall := $(extra-libs)
|
||||
|
||||
libsupport-routines = \
|
||||
check \
|
||||
check_addrinfo \
|
||||
check_dns_packet \
|
||||
check_hostent \
|
||||
check_netent \
|
||||
delayed_exit \
|
||||
ignore_stderr \
|
||||
oom_error \
|
||||
resolv_test \
|
||||
set_fortify_handler \
|
||||
support-xstat \
|
||||
support_become_root \
|
||||
support_can_chroot \
|
||||
support_capture_subprocess \
|
||||
support_capture_subprocess_check \
|
||||
support_enter_network_namespace \
|
||||
support_format_address_family \
|
||||
support_format_addrinfo \
|
||||
support_format_dns_packet \
|
||||
support_format_herrno \
|
||||
support_format_hostent \
|
||||
support_format_netent \
|
||||
support_isolate_in_subprocess \
|
||||
support_record_failure \
|
||||
support_run_diff \
|
||||
support_shared_allocate \
|
||||
support_write_file_string \
|
||||
support_test_main \
|
||||
support_test_verify_impl \
|
||||
temp_file \
|
||||
write_message \
|
||||
xaccept \
|
||||
xaccept4 \
|
||||
xasprintf \
|
||||
xbind \
|
||||
xcalloc \
|
||||
xchroot \
|
||||
xclose \
|
||||
xconnect \
|
||||
xdup2 \
|
||||
xfclose \
|
||||
xfopen \
|
||||
xfork \
|
||||
xgetsockname \
|
||||
xlisten \
|
||||
xmalloc \
|
||||
xmemstream \
|
||||
xmkdir \
|
||||
xmmap \
|
||||
xmunmap \
|
||||
xopen \
|
||||
xpipe \
|
||||
xpoll \
|
||||
xpthread_attr_destroy \
|
||||
xpthread_attr_init \
|
||||
xpthread_attr_setdetachstate \
|
||||
xpthread_attr_setstacksize \
|
||||
xpthread_barrier_destroy \
|
||||
xpthread_barrier_init \
|
||||
xpthread_barrier_wait \
|
||||
xpthread_cancel \
|
||||
xpthread_check_return \
|
||||
xpthread_cond_wait \
|
||||
xpthread_create \
|
||||
xpthread_detach \
|
||||
xpthread_join \
|
||||
xpthread_mutex_consistent \
|
||||
xpthread_mutex_destroy \
|
||||
xpthread_mutex_init \
|
||||
xpthread_mutex_lock \
|
||||
xpthread_mutex_unlock \
|
||||
xpthread_mutexattr_destroy \
|
||||
xpthread_mutexattr_init \
|
||||
xpthread_mutexattr_setprotocol \
|
||||
xpthread_mutexattr_setpshared \
|
||||
xpthread_mutexattr_setrobust \
|
||||
xpthread_mutexattr_settype \
|
||||
xpthread_once \
|
||||
xpthread_sigmask \
|
||||
xpthread_spin_lock \
|
||||
xpthread_spin_unlock \
|
||||
xrealloc \
|
||||
xrecvfrom \
|
||||
xsendto \
|
||||
xsetsockopt \
|
||||
xsocket \
|
||||
xstrdup \
|
||||
xwaitpid \
|
||||
xwrite \
|
||||
|
||||
libsupport-static-only-routines := $(libsupport-routines)
|
||||
# Only build one variant of the library.
|
||||
libsupport-inhibit-o := .os
|
||||
ifeq ($(build-shared),yes)
|
||||
libsupport-inhibit-o += .o
|
||||
endif
|
||||
|
||||
tests = \
|
||||
README-testing \
|
||||
tst-support-namespace \
|
||||
tst-support_capture_subprocess \
|
||||
tst-support_format_dns_packet \
|
||||
tst-support_record_failure \
|
||||
|
||||
ifeq ($(run-built-tests),yes)
|
||||
tests-special = \
|
||||
$(objpfx)tst-support_record_failure-2.out
|
||||
|
||||
$(objpfx)tst-support_record_failure-2.out: tst-support_record_failure-2.sh \
|
||||
$(objpfx)tst-support_record_failure
|
||||
$(SHELL) $< $(common-objpfx) '$(test-program-prefix-before-env)' \
|
||||
'$(run-program-env)' '$(test-program-prefix-after-env)' \
|
||||
> $@; \
|
||||
$(evaluate-test)
|
||||
endif
|
||||
|
||||
$(objpfx)tst-support_format_dns_packet: $(common-objpfx)resolv/libresolv.so
|
||||
|
||||
include ../Rules
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user