mirror of
git://sourceware.org/git/glibc.git
synced 2026-09-09 11:58:23 +08:00
Compare commits
113
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0d7f1ed309 | ||
|
|
1154cb63e7 | ||
|
|
a7b9e4cb8e | ||
|
|
910576119f | ||
|
|
9146dc9d73 | ||
|
|
fc4a25e814 | ||
|
|
b17dc7dec9 | ||
|
|
2700f1d8b6 | ||
|
|
cfea023b20 | ||
|
|
6f9ce82c1e | ||
|
|
689ad96885 | ||
|
|
d057fef28c | ||
|
|
b085cb9bbf | ||
|
|
22b7478755 | ||
|
|
fcd316654a | ||
|
|
e853f05a57 | ||
|
|
d8d97c0539 | ||
|
|
9ae4fa0c5b | ||
|
|
fff112f4c4 | ||
|
|
23758d3539 | ||
|
|
659b3df5db | ||
|
|
b501c7b09e | ||
|
|
ff52a12250 | ||
|
|
3f949b0347 | ||
|
|
682f24d0f3 | ||
|
|
17d5d67f4f | ||
|
|
f24c345bf5 | ||
|
|
248475457e | ||
|
|
c5b38f2ece | ||
|
|
28aa53341a | ||
|
|
a4fc3a0ceb | ||
|
|
d81254d2ef | ||
|
|
bddc572881 | ||
|
|
94825c8924 | ||
|
|
1e53b88296 | ||
|
|
5ff2eb52b2 | ||
|
|
1f523e3c6e | ||
|
|
832e2ec567 | ||
|
|
89bf8ef2db | ||
|
|
bea3f92405 | ||
|
|
5084717ffa | ||
|
|
37f4c94e1f | ||
|
|
79c6f51428 | ||
|
|
7fca94796b | ||
|
|
b3c498b834 | ||
|
|
b70f43dcef | ||
|
|
caa97d7a46 | ||
|
|
d5a4092c36 | ||
|
|
36f173ab37 | ||
|
|
6aacb5befa | ||
|
|
fd5fade305 | ||
|
|
cc392d6339 | ||
|
|
605e6f9f4a | ||
|
|
8c04a73813 | ||
|
|
86ac4a78a9 | ||
|
|
0578ef88fd | ||
|
|
2febff860b | ||
|
|
aab04ca5d3 | ||
|
|
87bd4186da | ||
|
|
600b10a871 | ||
|
|
4e291e7c52 | ||
|
|
0505a57d43 | ||
|
|
7b60553e36 | ||
|
|
206e03248c | ||
|
|
8071849934 | ||
|
|
4c5785aa12 | ||
|
|
a29331702f | ||
|
|
5f85ab2869 | ||
|
|
b2e8c40afc | ||
|
|
3966298a45 | ||
|
|
cc5dcd8803 | ||
|
|
8cc2792743 | ||
|
|
7043946c79 | ||
|
|
658b0abcff | ||
|
|
4d393a8831 | ||
|
|
d012ea8506 | ||
|
|
b3b37f1a55 | ||
|
|
537a06fbde | ||
|
|
2762a7145b | ||
|
|
7e4405c50f | ||
|
|
e9e69e4680 | ||
|
|
e6eab16cc3 | ||
|
|
8eb9a92e05 | ||
|
|
1912cc082d | ||
|
|
3eff6f8431 | ||
|
|
4b8790c81c | ||
|
|
2d16e81bab | ||
|
|
65a2b63756 | ||
|
|
d174436712 | ||
|
|
2bdb3d2ee1 | ||
|
|
822305be76 | ||
|
|
fe783a26a5 | ||
|
|
797c7fb197 | ||
|
|
ccebcff824 | ||
|
|
4467e53ab2 | ||
|
|
066437ad32 | ||
|
|
28202d1341 | ||
|
|
66b8f3d8ec | ||
|
|
e591222f99 | ||
|
|
a7a8929491 | ||
|
|
d289049cf5 | ||
|
|
5370672480 | ||
|
|
8c716c2e2f | ||
|
|
58ef663c94 | ||
|
|
72450627ba | ||
|
|
e2e4984ad6 | ||
|
|
0ba4a7522b | ||
|
|
b3012e4d56 | ||
|
|
f038a42f54 | ||
|
|
8026e9db17 | ||
|
|
ea23815a79 | ||
|
|
96cd434f66 | ||
|
|
d39c4a5ec0 |
+12
-3
@@ -394,6 +394,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 $@ \
|
||||
@@ -503,7 +506,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
|
||||
@@ -850,7 +853,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,108 @@ 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.24.1
|
||||
|
||||
Security related changes:
|
||||
|
||||
* 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)
|
||||
|
||||
* The DNS stub resolver functions would crash due to a NULL pointer
|
||||
dereference when processing a query with a valid DNS question type which
|
||||
was used internally in the implementation. The stub resolver now uses a
|
||||
question type which is outside the range of valid question type values.
|
||||
(CVE-2015-5180)
|
||||
|
||||
* 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-15671: The glob function, when invoked with GLOB_TILDE,
|
||||
would sometimes fail to free memory allocated during ~ operator
|
||||
processing, leading to a memory leak and, potentially, to a denial
|
||||
of service.
|
||||
|
||||
* 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.
|
||||
|
||||
* 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-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-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-18269: An SSE2-based memmove implementation for the i386
|
||||
architecture could corrupt memory. Reported by Max Horn.
|
||||
|
||||
CVE-2018-11236: Very long pathname arguments to realpath function could
|
||||
result in an integer overflow and buffer overflow. Reported by Alexey
|
||||
Izbyshev.
|
||||
|
||||
CVE-2018-11237: The mempcpy implementation for the Intel Xeon Phi
|
||||
architecture could write beyond the target buffer, resulting in a buffer
|
||||
overflow. Reported by Andreas Schwab.
|
||||
|
||||
CVE-2019-6488: On x32, the size_t parameter may be passed in the lower
|
||||
32 bits of a 64-bit register with with non-zero upper 32 bit. When it
|
||||
happened, accessing the 32-bit size_t value as the full 64-bit register
|
||||
in the assembly string/memory functions would cause a buffer overflow.
|
||||
Reported by H.J. Lu.
|
||||
|
||||
CVE-2019-7309: x86-64 memcmp used signed Jcc instructions to check
|
||||
size. For x86-64, memcmp on an object size larger than SSIZE_MAX
|
||||
has undefined behavior. On x32, the size_t argument may be passed
|
||||
in the lower 32 bits of the 64-bit RDX register with non-zero upper
|
||||
32 bits. When it happened with the sign bit of RDX register set,
|
||||
memcmp gave the wrong result since it treated the size argument as
|
||||
zero. Reported by H.J. Lu.
|
||||
|
||||
CVE-2019-19126: ld.so failed to ignore the LD_PREFER_MAP_32BIT_EXEC
|
||||
environment variable during program execution after a security
|
||||
transition, allowing local attackers to restrict the possible mapping
|
||||
addresses for loaded libraries and thus bypass ASLR for a setuid
|
||||
program. Reported by Marcin Kościelnicki.
|
||||
|
||||
The following bugs are resolved with this release:
|
||||
|
||||
[20116] nptl: use after free in pthread_create
|
||||
[20790] Fix rpcgen buffer overrun
|
||||
[20978] Fix strlen on null pointer in nss_nisplus
|
||||
[21209] Ignore and remove LD_HWCAP_MASK for AT_SECURE programs
|
||||
[21265] x86-64: Use fxsave/xsave/xsavec in _dl_runtime_resolve
|
||||
[21289] Fix symbol redirect for fts_set
|
||||
[21386] Assertion in fork for distinct parent PID is incorrect
|
||||
[21609] x86-64: Align the stack in __tls_get_addr
|
||||
[21624] Unsafe alloca allows local attackers to alias stack and heap (CVE-2017-1000366)
|
||||
[21654] nss: Fix invalid cast in group merging
|
||||
[22636] PTHREAD_STACK_MIN is too small on x86-64
|
||||
[22637] nptl: Fix stack guard size accounting
|
||||
[22644] string: memmove-sse2-unaligned on 32bit x86 produces garbage when
|
||||
crossing 2GB threshold (CVE-2017-18269)
|
||||
[22715] x86-64: Properly align La_x86_64_retval to VEC_SIZE
|
||||
[22786] libc: Stack buffer overflow in realpath() if input size is close
|
||||
to SSIZE_MAX (CVE-2018-11236)
|
||||
[23196] string: __mempcpy_avx512_no_vzeroupper mishandles large copies
|
||||
(CVE-2018-11237)
|
||||
[24027] malloc: Integer overflow in realloc
|
||||
[24097] Can't use 64-bit register for size_t in assembly codes for x32 (CVE-2019-6488)
|
||||
[24155] x32 memcmp can treat positive length as 0 (if sign bit in RDX is set) (CVE-2019-7309)
|
||||
[25204] Ignore LD_PREFER_MAP_32BIT_EXEC for SUID programs
|
||||
|
||||
|
||||
Version 2.24
|
||||
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -6289,12 +6289,14 @@ echo >&5 "libc_undefs='$libc_undefs'"
|
||||
# symbols (resolved by the linker), so filter out unknown symbols.
|
||||
# This will fail to produce the correct result if the compiler
|
||||
# defaults to -fstack-protector but this produces an undefined symbol
|
||||
# other than __stack_chk_fail. However, compilers like that have not
|
||||
# been encountered in practice.
|
||||
libc_undefs=`echo "$libc_undefs" | egrep '^(foobar|__stack_chk_fail)$'`
|
||||
# other than __stack_chk_fail or __stack_chk_fail_local. However,
|
||||
# compilers like that have not been encountered in practice.
|
||||
libc_undefs=`echo "$libc_undefs" | \
|
||||
egrep '^(foobar|__stack_chk_fail|__stack_chk_fail_local)$'`
|
||||
case "$libc_undefs" in
|
||||
foobar) libc_cv_predef_stack_protector=no ;;
|
||||
'__stack_chk_fail
|
||||
foobar'|'__stack_chk_fail_local
|
||||
foobar') libc_cv_predef_stack_protector=yes ;;
|
||||
*) as_fn_error $? "unexpected symbols in test: $libc_undefs" "$LINENO" 5 ;;
|
||||
esac
|
||||
|
||||
+5
-3
@@ -1626,12 +1626,14 @@ echo >&AS_MESSAGE_LOG_FD "libc_undefs='$libc_undefs'"
|
||||
# symbols (resolved by the linker), so filter out unknown symbols.
|
||||
# This will fail to produce the correct result if the compiler
|
||||
# defaults to -fstack-protector but this produces an undefined symbol
|
||||
# other than __stack_chk_fail. However, compilers like that have not
|
||||
# been encountered in practice.
|
||||
libc_undefs=`echo "$libc_undefs" | egrep '^(foobar|__stack_chk_fail)$'`
|
||||
# other than __stack_chk_fail or __stack_chk_fail_local. However,
|
||||
# compilers like that have not been encountered in practice.
|
||||
libc_undefs=`echo "$libc_undefs" | \
|
||||
egrep '^(foobar|__stack_chk_fail|__stack_chk_fail_local)$'`
|
||||
case "$libc_undefs" in
|
||||
foobar) libc_cv_predef_stack_protector=no ;;
|
||||
'__stack_chk_fail
|
||||
foobar'|'__stack_chk_fail_local
|
||||
foobar') libc_cv_predef_stack_protector=yes ;;
|
||||
*) AC_MSG_ERROR([unexpected symbols in test: $libc_undefs]) ;;
|
||||
esac],
|
||||
|
||||
+4
-3
@@ -196,13 +196,13 @@ $(conformtest-header-tests): $(objpfx)%/conform.out: \
|
||||
conformtest.pl $(conformtest-headers-data)
|
||||
(set -e; std_hdr=$*; std=$${std_hdr%%/*}; hdr=$${std_hdr#*/}; \
|
||||
mkdir -p $(@D)/scratch; \
|
||||
$(PERL) conformtest.pl --tmpdir=$(@D)/scratch --cc='$(CC)' \
|
||||
$(PERL) -I. conformtest.pl --tmpdir=$(@D)/scratch --cc='$(CC)' \
|
||||
--flags='$(conformtest-cc-flags)' --standard=$$std \
|
||||
--headers=$$hdr > $@); \
|
||||
$(evaluate-test)
|
||||
|
||||
$(linknamespace-symlists-tests): $(objpfx)symlist-%: list-header-symbols.pl
|
||||
$(PERL) -w $< --tmpdir=$(objpfx) --cc='$(CC)' \
|
||||
$(PERL) -I. -w $< --tmpdir=$(objpfx) --cc='$(CC)' \
|
||||
--flags='$(conformtest-cc-flags)' --standard=$* \
|
||||
--headers="$(strip $(conformtest-headers-$*))" \
|
||||
> $@ 2> $@.err; \
|
||||
@@ -229,10 +229,11 @@ $(linknamespace-symlist-stdlibs-tests): $(objpfx)symlist-stdlibs-%: \
|
||||
|
||||
$(linknamespace-header-tests): $(objpfx)%/linknamespace.out: \
|
||||
linknamespace.pl \
|
||||
$(linknamespace-symlists-tests) \
|
||||
$(linknamespace-symlist-stdlibs-tests)
|
||||
(set -e; std_hdr=$*; std=$${std_hdr%%/*}; hdr=$${std_hdr#*/}; \
|
||||
mkdir -p $(@D)/scratch; \
|
||||
$(PERL) -w $< --tmpdir=$(@D)/scratch --cc='$(CC)' \
|
||||
$(PERL) -I. -w $< --tmpdir=$(@D)/scratch --cc='$(CC)' \
|
||||
--flags='$(conformtest-cc-flags)' --standard=$$std \
|
||||
--stdsyms=$(objpfx)symlist-$$std --header=$$hdr \
|
||||
--libsyms=$(objpfx)symlist-stdlibs-$$std \
|
||||
|
||||
+13
-2
@@ -149,7 +149,8 @@ tests += loadtest restest1 preloadtest loadfail multiload origtest resolvfail \
|
||||
tst-nodelete) \
|
||||
tst-initorder tst-initorder2 tst-relsort1 tst-null-argv \
|
||||
tst-ptrguard1 tst-tlsalign tst-tlsalign-extern tst-nodelete-opened \
|
||||
tst-nodelete2 tst-audit11 tst-audit12 tst-dlsym-error
|
||||
tst-nodelete2 tst-audit11 tst-audit12 tst-dlsym-error \
|
||||
tst-nodelete-dlclose
|
||||
# reldep9
|
||||
ifeq ($(build-hardcoded-path-in-tests),yes)
|
||||
tests += tst-dlopen-aout
|
||||
@@ -223,7 +224,8 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \
|
||||
tst-array5dep tst-null-argv-lib \
|
||||
tst-tlsalign-lib tst-nodelete-opened-lib tst-nodelete2mod \
|
||||
tst-audit11mod1 tst-audit11mod2 tst-auditmod11 \
|
||||
tst-audit12mod1 tst-audit12mod2 tst-audit12mod3 tst-auditmod12
|
||||
tst-audit12mod1 tst-audit12mod2 tst-audit12mod3 tst-auditmod12 \
|
||||
tst-nodelete-dlclose-dso tst-nodelete-dlclose-plugin
|
||||
ifeq (yes,$(have-mtls-dialect-gnu2))
|
||||
tests += tst-gnu2-tls1
|
||||
modules-names += tst-gnu2-tls1mod
|
||||
@@ -1267,3 +1269,12 @@ $(objpfx)tst-ldconfig-X.out : tst-ldconfig-X.sh $(objpfx)ldconfig
|
||||
$(evaluate-test)
|
||||
|
||||
$(objpfx)tst-dlsym-error: $(libdl)
|
||||
|
||||
# The application depends on the DSO, and the DSO loads the plugin.
|
||||
# The plugin also depends on the DSO. This creates the circular
|
||||
# dependency via dlopen that we're testing to make sure works.
|
||||
$(objpfx)tst-nodelete-dlclose-dso.so: $(libdl)
|
||||
$(objpfx)tst-nodelete-dlclose-plugin.so: $(objpfx)tst-nodelete-dlclose-dso.so
|
||||
$(objpfx)tst-nodelete-dlclose: $(objpfx)tst-nodelete-dlclose-dso.so
|
||||
$(objpfx)tst-nodelete-dlclose.out: $(objpfx)tst-nodelete-dlclose-dso.so \
|
||||
$(objpfx)tst-nodelete-dlclose-plugin.so
|
||||
|
||||
+24
-6
@@ -805,19 +805,37 @@ _dl_close (void *_map)
|
||||
{
|
||||
struct link_map *map = _map;
|
||||
|
||||
/* First see whether we can remove the object at all. */
|
||||
/* We must take the lock to examine the contents of map and avoid
|
||||
concurrent dlopens. */
|
||||
__rtld_lock_lock_recursive (GL(dl_load_lock));
|
||||
|
||||
/* At this point we are guaranteed nobody else is touching the list of
|
||||
loaded maps, but a concurrent dlclose might have freed our map
|
||||
before we took the lock. There is no way to detect this (see below)
|
||||
so we proceed assuming this isn't the case. First see whether we
|
||||
can remove the object at all. */
|
||||
if (__glibc_unlikely (map->l_flags_1 & DF_1_NODELETE))
|
||||
{
|
||||
assert (map->l_init_called);
|
||||
/* Nope. Do nothing. */
|
||||
__rtld_lock_unlock_recursive (GL(dl_load_lock));
|
||||
return;
|
||||
}
|
||||
|
||||
/* At present this is an unreliable check except in the case where the
|
||||
caller has recursively called dlclose and we are sure the link map
|
||||
has not been freed. In a non-recursive dlclose the map itself
|
||||
might have been freed and this access is potentially a data race
|
||||
with whatever other use this memory might have now, or worse we
|
||||
might silently corrupt memory if it looks enough like a link map.
|
||||
POSIX has language in dlclose that appears to guarantee that this
|
||||
should be a detectable case and given that dlclose should be threadsafe
|
||||
we need this to be a reliable detection.
|
||||
This is bug 20990. */
|
||||
if (__builtin_expect (map->l_direct_opencount, 1) == 0)
|
||||
GLRO(dl_signal_error) (0, map->l_name, NULL, N_("shared object not open"));
|
||||
|
||||
/* Acquire the lock. */
|
||||
__rtld_lock_lock_recursive (GL(dl_load_lock));
|
||||
{
|
||||
__rtld_lock_unlock_recursive (GL(dl_load_lock));
|
||||
_dl_signal_error (0, map->l_name, NULL, N_("shared object not open"));
|
||||
}
|
||||
|
||||
_dl_close_worker (map, false);
|
||||
|
||||
|
||||
+47
-53
@@ -37,6 +37,7 @@
|
||||
#include <sysdep.h>
|
||||
#include <stap-probe.h>
|
||||
#include <libc-internal.h>
|
||||
#include <array_length.h>
|
||||
|
||||
#include <dl-dst.h>
|
||||
#include <dl-load.h>
|
||||
@@ -103,7 +104,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;
|
||||
@@ -111,9 +114,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)
|
||||
@@ -433,32 +434,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))
|
||||
{
|
||||
@@ -621,6 +631,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;
|
||||
@@ -688,9 +706,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");
|
||||
@@ -776,37 +793,14 @@ _dl_init_paths (const char *llp)
|
||||
|
||||
if (llp != NULL && *llp != '\0')
|
||||
{
|
||||
size_t nllp;
|
||||
const char *cp = llp;
|
||||
char *llp_tmp;
|
||||
|
||||
#ifdef SHARED
|
||||
/* Expand DSTs. */
|
||||
size_t cnt = DL_DST_COUNT (llp, 1);
|
||||
if (__glibc_likely (cnt == 0))
|
||||
llp_tmp = strdupa (llp);
|
||||
else
|
||||
{
|
||||
/* Determine the length of the substituted string. */
|
||||
size_t total = DL_DST_REQUIRED (l, llp, strlen (llp), cnt);
|
||||
|
||||
/* Allocate the necessary memory. */
|
||||
llp_tmp = (char *) alloca (total + 1);
|
||||
llp_tmp = _dl_dst_substitute (l, llp, llp_tmp, 1);
|
||||
}
|
||||
#else
|
||||
llp_tmp = strdupa (llp);
|
||||
#endif
|
||||
char *llp_tmp = strdupa (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 *));
|
||||
|
||||
+165
-33
@@ -99,14 +99,121 @@ uintptr_t __pointer_chk_guard_local
|
||||
strong_alias (__pointer_chk_guard_local, __pointer_chk_guard)
|
||||
#endif
|
||||
|
||||
/* Length limits for names and paths, to protect the dynamic linker,
|
||||
particularly when __libc_enable_secure is active. */
|
||||
#ifdef NAME_MAX
|
||||
# define SECURE_NAME_LIMIT NAME_MAX
|
||||
#else
|
||||
# define SECURE_NAME_LIMIT 255
|
||||
#endif
|
||||
#ifdef PATH_MAX
|
||||
# define SECURE_PATH_LIMIT PATH_MAX
|
||||
#else
|
||||
# define SECURE_PATH_LIMIT 1024
|
||||
#endif
|
||||
|
||||
/* List of auditing DSOs. */
|
||||
/* Check that AT_SECURE=0, or that the passed name does not contain
|
||||
directories and is not overly long. Reject empty names
|
||||
unconditionally. */
|
||||
static bool
|
||||
dso_name_valid_for_suid (const char *p)
|
||||
{
|
||||
if (__glibc_unlikely (__libc_enable_secure))
|
||||
{
|
||||
/* Ignore pathnames with directories for AT_SECURE=1
|
||||
programs, and also skip overlong names. */
|
||||
size_t len = strlen (p);
|
||||
if (len >= SECURE_NAME_LIMIT || memchr (p, '/', len) != NULL)
|
||||
return false;
|
||||
}
|
||||
return *p != '\0';
|
||||
}
|
||||
|
||||
/* LD_AUDIT variable contents. Must be processed before the
|
||||
audit_list below. */
|
||||
const char *audit_list_string;
|
||||
|
||||
/* Cyclic list of auditing DSOs. audit_list->next is the first
|
||||
element. */
|
||||
static struct audit_list
|
||||
{
|
||||
const char *name;
|
||||
struct audit_list *next;
|
||||
} *audit_list;
|
||||
|
||||
/* Iterator for audit_list_string followed by audit_list. */
|
||||
struct audit_list_iter
|
||||
{
|
||||
/* Tail of audit_list_string still needing processing, or NULL. */
|
||||
const char *audit_list_tail;
|
||||
|
||||
/* The list element returned in the previous iteration. NULL before
|
||||
the first element. */
|
||||
struct audit_list *previous;
|
||||
|
||||
/* Scratch buffer for returning a name which is part of
|
||||
audit_list_string. */
|
||||
char fname[SECURE_NAME_LIMIT];
|
||||
};
|
||||
|
||||
/* Initialize an audit list iterator. */
|
||||
static void
|
||||
audit_list_iter_init (struct audit_list_iter *iter)
|
||||
{
|
||||
iter->audit_list_tail = audit_list_string;
|
||||
iter->previous = NULL;
|
||||
}
|
||||
|
||||
/* Iterate through both audit_list_string and audit_list. */
|
||||
static const char *
|
||||
audit_list_iter_next (struct audit_list_iter *iter)
|
||||
{
|
||||
if (iter->audit_list_tail != NULL)
|
||||
{
|
||||
/* First iterate over audit_list_string. */
|
||||
while (*iter->audit_list_tail != '\0')
|
||||
{
|
||||
/* Split audit list at colon. */
|
||||
size_t len = strcspn (iter->audit_list_tail, ":");
|
||||
if (len > 0 && len < sizeof (iter->fname))
|
||||
{
|
||||
memcpy (iter->fname, iter->audit_list_tail, len);
|
||||
iter->fname[len] = '\0';
|
||||
}
|
||||
else
|
||||
/* Do not return this name to the caller. */
|
||||
iter->fname[0] = '\0';
|
||||
|
||||
/* Skip over the substring and the following delimiter. */
|
||||
iter->audit_list_tail += len;
|
||||
if (*iter->audit_list_tail == ':')
|
||||
++iter->audit_list_tail;
|
||||
|
||||
/* If the name is valid, return it. */
|
||||
if (dso_name_valid_for_suid (iter->fname))
|
||||
return iter->fname;
|
||||
/* Otherwise, wrap around and try the next name. */
|
||||
}
|
||||
/* Fall through to the procesing of audit_list. */
|
||||
}
|
||||
|
||||
if (iter->previous == NULL)
|
||||
{
|
||||
if (audit_list == NULL)
|
||||
/* No pre-parsed audit list. */
|
||||
return NULL;
|
||||
/* Start of audit list. The first list element is at
|
||||
audit_list->next (cyclic list). */
|
||||
iter->previous = audit_list->next;
|
||||
return iter->previous->name;
|
||||
}
|
||||
if (iter->previous == audit_list)
|
||||
/* Cyclic list wrap-around. */
|
||||
return NULL;
|
||||
iter->previous = iter->previous->next;
|
||||
return iter->previous->name;
|
||||
}
|
||||
|
||||
#ifndef HAVE_INLINED_SYSCALLS
|
||||
/* Set nonzero during loading and initialization of executable and
|
||||
libraries, cleared before the executable's entry point runs. This
|
||||
@@ -730,6 +837,42 @@ static const char *preloadlist attribute_relro;
|
||||
/* Nonzero if information about versions has to be printed. */
|
||||
static int version_info attribute_relro;
|
||||
|
||||
/* The LD_PRELOAD environment variable gives list of libraries
|
||||
separated by white space or colons that are loaded before the
|
||||
executable's dependencies and prepended to the global scope list.
|
||||
(If the binary is running setuid all elements containing a '/' are
|
||||
ignored since it is insecure.) Return the number of preloads
|
||||
performed. */
|
||||
unsigned int
|
||||
handle_ld_preload (const char *preloadlist, struct link_map *main_map)
|
||||
{
|
||||
unsigned int npreloads = 0;
|
||||
const char *p = preloadlist;
|
||||
char fname[SECURE_PATH_LIMIT];
|
||||
|
||||
while (*p != '\0')
|
||||
{
|
||||
/* Split preload list at space/colon. */
|
||||
size_t len = strcspn (p, " :");
|
||||
if (len > 0 && len < sizeof (fname))
|
||||
{
|
||||
memcpy (fname, p, len);
|
||||
fname[len] = '\0';
|
||||
}
|
||||
else
|
||||
fname[0] = '\0';
|
||||
|
||||
/* Skip over the substring and the following delimiter. */
|
||||
p += len;
|
||||
if (*p != '\0')
|
||||
++p;
|
||||
|
||||
if (dso_name_valid_for_suid (fname))
|
||||
npreloads += do_preload (fname, main_map, "LD_PRELOAD");
|
||||
}
|
||||
return npreloads;
|
||||
}
|
||||
|
||||
static void
|
||||
dl_main (const ElfW(Phdr) *phdr,
|
||||
ElfW(Word) phnum,
|
||||
@@ -1257,11 +1400,13 @@ of this helper program; chances are you did not intend to run this program.\n\
|
||||
GL(dl_rtld_map).l_tls_modid = _dl_next_tls_modid ();
|
||||
|
||||
/* If we have auditing DSOs to load, do it now. */
|
||||
if (__glibc_unlikely (audit_list != NULL))
|
||||
bool need_security_init = true;
|
||||
if (__glibc_unlikely (audit_list != NULL)
|
||||
|| __glibc_unlikely (audit_list_string != NULL))
|
||||
{
|
||||
/* Iterate over all entries in the list. The order is important. */
|
||||
struct audit_ifaces *last_audit = NULL;
|
||||
struct audit_list *al = audit_list->next;
|
||||
struct audit_list_iter al_iter;
|
||||
audit_list_iter_init (&al_iter);
|
||||
|
||||
/* Since we start using the auditing DSOs right away we need to
|
||||
initialize the data structures now. */
|
||||
@@ -1272,9 +1417,14 @@ of this helper program; chances are you did not intend to run this program.\n\
|
||||
use different values (especially the pointer guard) and will
|
||||
fail later on. */
|
||||
security_init ();
|
||||
need_security_init = false;
|
||||
|
||||
do
|
||||
while (true)
|
||||
{
|
||||
const char *name = audit_list_iter_next (&al_iter);
|
||||
if (name == NULL)
|
||||
break;
|
||||
|
||||
int tls_idx = GL(dl_tls_max_dtv_idx);
|
||||
|
||||
/* Now it is time to determine the layout of the static TLS
|
||||
@@ -1283,7 +1433,7 @@ of this helper program; chances are you did not intend to run this program.\n\
|
||||
no DF_STATIC_TLS bit is set. The reason is that we know
|
||||
glibc will use the static model. */
|
||||
struct dlmopen_args dlmargs;
|
||||
dlmargs.fname = al->name;
|
||||
dlmargs.fname = name;
|
||||
dlmargs.map = NULL;
|
||||
|
||||
const char *objname;
|
||||
@@ -1296,7 +1446,7 @@ of this helper program; chances are you did not intend to run this program.\n\
|
||||
not_loaded:
|
||||
_dl_error_printf ("\
|
||||
ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
|
||||
al->name, err_str);
|
||||
name, err_str);
|
||||
if (malloced)
|
||||
free ((char *) err_str);
|
||||
}
|
||||
@@ -1400,10 +1550,7 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
|
||||
goto not_loaded;
|
||||
}
|
||||
}
|
||||
|
||||
al = al->next;
|
||||
}
|
||||
while (al != audit_list->next);
|
||||
|
||||
/* If we have any auditing modules, announce that we already
|
||||
have two objects loaded. */
|
||||
@@ -1481,23 +1628,8 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
|
||||
|
||||
if (__glibc_unlikely (preloadlist != NULL))
|
||||
{
|
||||
/* The LD_PRELOAD environment variable gives list of libraries
|
||||
separated by white space or colons that are loaded before the
|
||||
executable's dependencies and prepended to the global scope
|
||||
list. If the binary is running setuid all elements
|
||||
containing a '/' are ignored since it is insecure. */
|
||||
char *list = strdupa (preloadlist);
|
||||
char *p;
|
||||
|
||||
HP_TIMING_NOW (start);
|
||||
|
||||
/* Prevent optimizing strsep. Speed is not important here. */
|
||||
while ((p = (strsep) (&list, " :")) != NULL)
|
||||
if (p[0] != '\0'
|
||||
&& (__builtin_expect (! __libc_enable_secure, 1)
|
||||
|| strchr (p, '/') == NULL))
|
||||
npreloads += do_preload (p, main_map, "LD_PRELOAD");
|
||||
|
||||
npreloads += handle_ld_preload (preloadlist, main_map);
|
||||
HP_TIMING_NOW (stop);
|
||||
HP_TIMING_DIFF (diff, start, stop);
|
||||
HP_TIMING_ACCUM_NT (load_time, diff);
|
||||
@@ -1682,7 +1814,7 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
|
||||
if (tcbp == NULL)
|
||||
tcbp = init_tls ();
|
||||
|
||||
if (__glibc_likely (audit_list == NULL))
|
||||
if (__glibc_likely (need_security_init))
|
||||
/* Initialize security features. But only if we have not done it
|
||||
earlier. */
|
||||
security_init ();
|
||||
@@ -2313,9 +2445,7 @@ process_dl_audit (char *str)
|
||||
char *p;
|
||||
|
||||
while ((p = (strsep) (&str, ":")) != NULL)
|
||||
if (p[0] != '\0'
|
||||
&& (__builtin_expect (! __libc_enable_secure, 1)
|
||||
|| strchr (p, '/') == NULL))
|
||||
if (dso_name_valid_for_suid (p))
|
||||
{
|
||||
/* This is using the local malloc, not the system malloc. The
|
||||
memory can never be freed. */
|
||||
@@ -2379,7 +2509,7 @@ process_envvars (enum mode *modep)
|
||||
break;
|
||||
}
|
||||
if (memcmp (envline, "AUDIT", 5) == 0)
|
||||
process_dl_audit (&envline[6]);
|
||||
audit_list_string = &envline[6];
|
||||
break;
|
||||
|
||||
case 7:
|
||||
@@ -2423,7 +2553,8 @@ process_envvars (enum mode *modep)
|
||||
|
||||
case 10:
|
||||
/* Mask for the important hardware capabilities. */
|
||||
if (memcmp (envline, "HWCAP_MASK", 10) == 0)
|
||||
if (!__libc_enable_secure
|
||||
&& memcmp (envline, "HWCAP_MASK", 10) == 0)
|
||||
GLRO(dl_hwcap_mask) = __strtoul_internal (&envline[11], NULL,
|
||||
0, 0);
|
||||
break;
|
||||
@@ -2437,7 +2568,8 @@ process_envvars (enum mode *modep)
|
||||
|
||||
case 12:
|
||||
/* The library search path. */
|
||||
if (memcmp (envline, "LIBRARY_PATH", 12) == 0)
|
||||
if (!__libc_enable_secure
|
||||
&& memcmp (envline, "LIBRARY_PATH", 12) == 0)
|
||||
{
|
||||
library_path = &envline[13];
|
||||
break;
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
/* Bug 11941: Improper assert map->l_init_called in dlclose.
|
||||
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/>. */
|
||||
|
||||
/* This is the primary DSO that is loaded by the appliation. This DSO
|
||||
then loads a plugin with RTLD_NODELETE. This plugin depends on this
|
||||
DSO. This dependency chain means that at application shutdown the
|
||||
plugin will be destructed first. Thus by the time this DSO is
|
||||
destructed we will be calling dlclose on an object that has already
|
||||
been destructed. It is allowed to call dlclose in this way and
|
||||
should not assert. */
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
/* Plugin to load. */
|
||||
static void *plugin_lib = NULL;
|
||||
/* Plugin function. */
|
||||
static void (*plugin_func) (void);
|
||||
#define LIB_PLUGIN "tst-nodelete-dlclose-plugin.so"
|
||||
|
||||
/* This function is never called but the plugin references it.
|
||||
We do this to avoid any future --as-needed from removing the
|
||||
plugin's DT_NEEDED on this DSO (required for the test). */
|
||||
void
|
||||
primary_reference (void)
|
||||
{
|
||||
printf ("INFO: Called primary_reference function.\n");
|
||||
}
|
||||
|
||||
void
|
||||
primary (void)
|
||||
{
|
||||
char *error;
|
||||
|
||||
plugin_lib = dlopen (LIB_PLUGIN, RTLD_NOW | RTLD_LOCAL | RTLD_NODELETE);
|
||||
if (plugin_lib == NULL)
|
||||
{
|
||||
printf ("ERROR: Unable to load plugin library.\n");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
dlerror ();
|
||||
|
||||
plugin_func = (void (*) (void)) dlsym (plugin_lib, "plugin_func");
|
||||
error = dlerror ();
|
||||
if (error != NULL)
|
||||
{
|
||||
printf ("ERROR: Unable to find symbol with error \"%s\".",
|
||||
error);
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
__attribute__ ((destructor))
|
||||
static void
|
||||
primary_dtor (void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
printf ("INFO: Calling primary destructor.\n");
|
||||
|
||||
/* The destructor runs in the test driver also, which
|
||||
hasn't called primary, in that case do nothing. */
|
||||
if (plugin_lib == NULL)
|
||||
return;
|
||||
|
||||
ret = dlclose (plugin_lib);
|
||||
if (ret != 0)
|
||||
{
|
||||
printf ("ERROR: Calling dlclose failed with \"%s\"\n",
|
||||
dlerror ());
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/* Bug 11941: Improper assert map->l_init_called in dlclose.
|
||||
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/>. */
|
||||
|
||||
/* This DSO simulates a plugin with a dependency on the
|
||||
primary DSO loaded by the appliation. */
|
||||
#include <stdio.h>
|
||||
|
||||
extern void primary_reference (void);
|
||||
|
||||
void
|
||||
plugin_func (void)
|
||||
{
|
||||
printf ("INFO: Calling plugin function.\n");
|
||||
/* Need a reference to the DSO to ensure that a potential --as-needed
|
||||
doesn't remove the DT_NEEDED entry which we rely upon to ensure
|
||||
destruction ordering. */
|
||||
primary_reference ();
|
||||
}
|
||||
|
||||
__attribute__ ((destructor))
|
||||
static void
|
||||
plugin_dtor (void)
|
||||
{
|
||||
printf ("INFO: Calling plugin destructor.\n");
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/* Bug 11941: Improper assert map->l_init_called in dlclose.
|
||||
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/>. */
|
||||
|
||||
/* This simulates an application using the primary DSO which loads the
|
||||
plugin DSO. */
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
extern void primary (void);
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
printf ("INFO: Starting application.\n");
|
||||
primary ();
|
||||
printf ("INFO: Exiting application.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define TEST_FUNCTION do_test ()
|
||||
#include "../test-skeleton.c"
|
||||
@@ -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),\
|
||||
|
||||
+17
-1
@@ -85,6 +85,14 @@ __copy_grp (const struct group srcgrp, const size_t buflen,
|
||||
}
|
||||
members[i] = NULL;
|
||||
|
||||
/* Align for pointers. We can't simply align C because we need to
|
||||
align destbuf[c]. */
|
||||
if ((((uintptr_t)destbuf + c) & (__alignof__(char **) - 1)) != 0)
|
||||
{
|
||||
uintptr_t mis_align = ((uintptr_t)destbuf + c) & (__alignof__(char **) - 1);
|
||||
c += __alignof__(char **) - mis_align;
|
||||
}
|
||||
|
||||
/* Copy the pointers from the members array into the buffer and assign them
|
||||
to the gr_mem member of destgrp. */
|
||||
destgrp->gr_mem = (char **) &destbuf[c];
|
||||
@@ -129,7 +137,7 @@ __merge_grp (struct group *savedgrp, char *savedbuf, char *savedend,
|
||||
|
||||
/* Get the count of group members from the last sizeof (size_t) bytes in the
|
||||
mergegrp buffer. */
|
||||
savedmemcount = (size_t) *(savedend - sizeof (size_t));
|
||||
savedmemcount = *(size_t *) (savedend - sizeof (size_t));
|
||||
|
||||
/* Get the count of new members to add. */
|
||||
for (memcount = 0; mergegrp->gr_mem[memcount]; memcount++)
|
||||
@@ -168,6 +176,14 @@ __merge_grp (struct group *savedgrp, char *savedbuf, char *savedend,
|
||||
/* Add the NULL-terminator. */
|
||||
members[savedmemcount + memcount] = NULL;
|
||||
|
||||
/* Align for pointers. We can't simply align C because we need to
|
||||
align savedbuf[c]. */
|
||||
if ((((uintptr_t)savedbuf + c) & (__alignof__(char **) - 1)) != 0)
|
||||
{
|
||||
uintptr_t mis_align = ((uintptr_t)savedbuf + c) & (__alignof__(char **) - 1);
|
||||
c += __alignof__(char **) - mis_align;
|
||||
}
|
||||
|
||||
/* Copy the member array back into the buffer after the member list and free
|
||||
the member array. */
|
||||
savedgrp->gr_mem = (char **) &savedbuf[c];
|
||||
|
||||
+1
-1
@@ -139,7 +139,7 @@ typedef struct __gconv_info
|
||||
{
|
||||
size_t __nsteps;
|
||||
struct __gconv_step *__steps;
|
||||
__extension__ struct __gconv_step_data __data __flexarr;
|
||||
__extension__ struct __gconv_step_data __data[0];
|
||||
} *__gconv_t;
|
||||
|
||||
/* Transliteration using the locale's data. */
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
#ifndef _ARPA_NAMESER_COMPAT_
|
||||
#include <resolv/arpa/nameser_compat.h>
|
||||
|
||||
/* Picksome unused number to represent lookups of IPv4 and IPv6 (i.e.,
|
||||
T_A and T_AAAA). */
|
||||
#define T_UNSPEC 62321
|
||||
/* The number is outside the 16-bit RR type range and is used
|
||||
internally by the implementation. */
|
||||
#define T_QUERY_A_AND_AAAA 439963904
|
||||
|
||||
#endif
|
||||
|
||||
@@ -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 */
|
||||
@@ -193,7 +193,7 @@ FTS *__REDIRECT (fts_open, (char * const *, int,
|
||||
int (*)(const FTSENT **, const FTSENT **)),
|
||||
fts64_open);
|
||||
FTSENT *__REDIRECT (fts_read, (FTS *), fts64_read);
|
||||
int __REDIRECT (fts_set, (FTS *, FTSENT *, int), fts64_set) __THROW;
|
||||
int __REDIRECT_NTH (fts_set, (FTS *, FTSENT *, int), fts64_set);
|
||||
# else
|
||||
# define fts_children fts64_children
|
||||
# define fts_close fts64_close
|
||||
|
||||
@@ -87,6 +87,11 @@ _IO_check_libio (void)
|
||||
stdout->_vtable_offset = stderr->_vtable_offset =
|
||||
((int) sizeof (struct _IO_FILE)
|
||||
- (int) sizeof (struct _IO_FILE_complete));
|
||||
|
||||
if (_IO_stdin_.vtable != &_IO_old_file_jumps
|
||||
|| _IO_stdout_.vtable != &_IO_old_file_jumps
|
||||
|| _IO_stderr_.vtable != &_IO_old_file_jumps)
|
||||
IO_set_accept_foreign_vtables (&_IO_vtable_check);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -70,3 +70,19 @@ _IO_vtable_check (void)
|
||||
|
||||
__libc_fatal ("Fatal error: glibc detected an invalid stdio handle\n");
|
||||
}
|
||||
|
||||
/* Some variants of libstdc++ interpose _IO_2_1_stdin_ etc. and
|
||||
install their own vtables directly, without calling _IO_init or
|
||||
other functions. Detect this by looking at the vtables values
|
||||
during startup, and disable vtable validation in this case. */
|
||||
#ifdef SHARED
|
||||
__attribute__ ((constructor))
|
||||
static void
|
||||
check_stdfiles_vtables (void)
|
||||
{
|
||||
if (_IO_2_1_stdin_.vtable != &_IO_file_jumps
|
||||
|| _IO_2_1_stdout_.vtable != &_IO_file_jumps
|
||||
|| _IO_2_1_stderr_.vtable != &_IO_file_jumps)
|
||||
IO_set_accept_foreign_vtables (&_IO_vtable_check);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1,3 +1,17 @@
|
||||
2017-06-11 Santhosh Thottingal <santhosh.thottingal@gmail.com>
|
||||
|
||||
[BZ #19922]
|
||||
* locales/iso14651_t1_common: Add collation rules for U+07DA to U+07DF.
|
||||
|
||||
[BZ #19919]
|
||||
* locales/iso14651_t1_common: Correct collation of U+0D36 and U+0D37.
|
||||
|
||||
2016-12-30 Mike Frysinger <vapier@gentoo.org>
|
||||
|
||||
[BZ #20974]
|
||||
* localedata/bs_BA (LC_MESSAGES): Delete "*." from the end of
|
||||
yesexpr and noexpr.
|
||||
|
||||
2016-07-07 Aurelien Jarno <aurelien@aurel32.net>
|
||||
|
||||
* locales/de_LI (postal_fmt): Fix indentation.
|
||||
|
||||
@@ -148,8 +148,8 @@ copy "en_DK"
|
||||
END LC_CTYPE
|
||||
|
||||
LC_MESSAGES
|
||||
yesexpr "<U005E><U005B><U002B><U0031><U0064><U0044><U0079><U0059><U005D><U002A><U002E>"
|
||||
noexpr "<U005E><U005B><U002D><U0030><U006E><U004E><U005D><U002A><U002E>"
|
||||
yesexpr "<U005E><U005B><U002B><U0031><U0064><U0044><U0079><U0059><U005D>"
|
||||
noexpr "<U005E><U005B><U002D><U0030><U006E><U004E><U005D>"
|
||||
yesstr "<U0064><U0061>"
|
||||
nostr "<U006E><U0065>"
|
||||
END LC_MESSAGES
|
||||
|
||||
@@ -1042,9 +1042,9 @@ collating-element <ml-bh> from "<U0D2D><U0D4D>"
|
||||
collating-element <ml-m> from "<U0D2E><U0D4D>"
|
||||
collating-element <ml-y> from "<U0D2F><U0D4D>"
|
||||
collating-element <ml-v> from "<U0D35><U0D4D>"
|
||||
collating-element <ml-s> from "<U0D38><U0D4D>"
|
||||
collating-element <ml-ss> from "<U0D36><U0D4D>"
|
||||
collating-element <ml-sh> from "<U0D37><U0D4D>"
|
||||
collating-element <ml-s> from "<U0D38><U0D4D>"
|
||||
collating-element <ml-h> from "<U0D39><U0D4D>"
|
||||
collating-element <ml-zh> from "<U0D34><U0D4D>"
|
||||
collating-element <ml-rr> from "<U0D31><U0D4D>"
|
||||
@@ -1103,8 +1103,8 @@ collating-symbol <ml-rra>
|
||||
collating-symbol <ml-la>
|
||||
collating-symbol <ml-lla>
|
||||
collating-symbol <ml-va>
|
||||
collating-symbol <ml-sha>
|
||||
collating-symbol <ml-ssa>
|
||||
collating-symbol <ml-sha>
|
||||
collating-symbol <ml-sa>
|
||||
collating-symbol <ml-ha>
|
||||
collating-symbol <ml-avagrah>
|
||||
@@ -1126,6 +1126,12 @@ collating-symbol <mlvs-o>
|
||||
collating-symbol <mlvs-au>
|
||||
collating-symbol <ml-visarga>
|
||||
collating-symbol <ml-virama>
|
||||
collating-symbol <ml-atomic-chillu-k>
|
||||
collating-symbol <ml-atomic-chillu-n>
|
||||
collating-symbol <ml-atomic-chillu-nn>
|
||||
collating-symbol <ml-atomic-chillu-l>
|
||||
collating-symbol <ml-atomic-chillu-ll>
|
||||
collating-symbol <ml-atomic-chillu-r>
|
||||
#
|
||||
# <BENGALI>
|
||||
#
|
||||
@@ -4552,6 +4558,12 @@ collating-symbol <TIB-subA>
|
||||
<mlvs-o>
|
||||
<mlvs-au>
|
||||
<ml-visarga>
|
||||
<ml-atomic-chillu-k>
|
||||
<ml-atomic-chillu-n>
|
||||
<ml-atomic-chillu-nn>
|
||||
<ml-atomic-chillu-l>
|
||||
<ml-atomic-chillu-ll>
|
||||
<ml-atomic-chillu-r>
|
||||
#
|
||||
# <BENGALI>
|
||||
#
|
||||
@@ -7252,6 +7264,7 @@ order_start <MALAYALAM>;forward;forward;forward;forward,position
|
||||
<U0D13> <mlvw-o>;<BAS>;<MIN>;IGNORE
|
||||
<U0D14> <mlvw-au>;<BAS>;<MIN>;IGNORE
|
||||
<ml-chillu-k> "<ml-ka><ml-virama>";<BAS>;<MIN>;IGNORE
|
||||
<U0D7F> "<ml-ka><ml-virama>";<ml-atomic-chillu-k>;<MIN>;IGNORE
|
||||
<U0D15> "<ml-ka><ml-virama><mlvw-shorta>";<BAS>;<MIN>;IGNORE
|
||||
<ml-kh> "<ml-kha><ml-virama>";<BAS>;<MIN>;IGNORE
|
||||
<U0D16> "<ml-kha><ml-virama><mlvw-shorta>";<BAS>;<MIN>;IGNORE
|
||||
@@ -7280,6 +7293,7 @@ order_start <MALAYALAM>;forward;forward;forward;forward,position
|
||||
<ml-dh> "<ml-dha><ml-virama>";<BAS>;<MIN>;IGNORE
|
||||
<U0D22> "<ml-dha><ml-virama><mlvw-shorta>";<BAS>;<MIN>;IGNORE
|
||||
<ml-chillu-nn> "<ml-nna><ml-virama>";<BAS>;<MIN>;IGNORE # ണ് = ണ + ് + zwj
|
||||
<U0D7A> "<ml-nna><ml-virama>";<ml-atomic-chillu-nn>;<MIN>;IGNORE
|
||||
<U0D23> "<ml-nna><ml-virama><mlvw-shorta>";<BAS>;<MIN>;IGNORE # ണ = ണ + ് + അ
|
||||
<ml-th> "<ml-tha><ml-virama>";<BAS>;<MIN>;IGNORE
|
||||
<U0D24> "<ml-tha><ml-virama><mlvw-shorta>";<BAS>;<MIN>;IGNORE
|
||||
@@ -7290,6 +7304,7 @@ order_start <MALAYALAM>;forward;forward;forward;forward,position
|
||||
<ml-ddh> "<ml-ddha><ml-virama>";<BAS>;<MIN>;IGNORE
|
||||
<U0D27> "<ml-ddha><ml-virama><mlvw-shorta>";<BAS>;<MIN>;IGNORE
|
||||
<ml-chillu-n> "<ml-na><ml-virama>";<BAS>;<MIN>;IGNORE # ന്= ന + ് + zwj
|
||||
<U0D7B> "<ml-na><ml-virama>";<ml-atomic-chillu-n>;<MIN>;IGNORE
|
||||
<U0D28> "<ml-na><ml-virama><mlvw-shorta>";<BAS>;<MIN>;IGNORE #ന = ന + ് + അ
|
||||
<ml-p> "<ml-pa><ml-virama>";<BAS>;<MIN>;IGNORE
|
||||
<U0D2A> "<ml-pa><ml-virama><mlvw-shorta>";<BAS>;<MIN>;IGNORE
|
||||
@@ -7305,20 +7320,23 @@ order_start <MALAYALAM>;forward;forward;forward;forward,position
|
||||
<ml-y> "<ml-ya><ml-virama>";<BAS>;<MIN>;IGNORE
|
||||
<U0D2F> "<ml-ya><ml-virama><mlvw-shorta>";<BAS>;<MIN>;IGNORE
|
||||
<ml-chillu-r> "<ml-ra><ml-virama>";<BAS>;<MIN>;IGNORE # ര = ര + ് + zwj
|
||||
<U0D7C> "<ml-ra><ml-virama>";<ml-atomic-chillu-r>;<MIN>;IGNORE
|
||||
<U0D30> "<ml-ra><ml-virama><mlvw-shorta>";<BAS>;<MIN>;IGNORE # ര = ര + ് + അ
|
||||
<ml-chillu-l> <ml-la>;<BAS>;<MIN>;IGNORE # ല് = ല + ് + zwj
|
||||
<U0D7D> "<ml-la><ml-virama>";<ml-atomic-chillu-l>;<MIN>;IGNORE
|
||||
<U0D32> "<ml-la><ml-virama><mlvw-shorta>";<BAS>;<MIN>;IGNORE # ല = ല + ് + അ
|
||||
<ml-v> "<ml-va><ml-virama>";<BAS>;<MIN>;IGNORE
|
||||
<U0D35> "<ml-va><ml-virama><mlvw-shorta>";<BAS>;<MIN>;IGNORE
|
||||
<ml-ss> "<ml-ssa><ml-virama>";<BAS>;<MIN>;IGNORE
|
||||
<U0D37> "<ml-ssa><ml-virama><mlvw-shorta>";<BAS>;<MIN>;IGNORE
|
||||
<U0D36> "<ml-ssa><ml-virama><mlvw-shorta>";<BAS>;<MIN>;IGNORE
|
||||
<ml-sh> "<ml-sha><ml-virama>";<BAS>;<MIN>;IGNORE
|
||||
<U0D36> "<ml-sha><ml-virama><mlvw-shorta>";<BAS>;<MIN>;IGNORE
|
||||
<U0D37> "<ml-sha><ml-virama><mlvw-shorta>";<BAS>;<MIN>;IGNORE
|
||||
<ml-s> "<ml-sa><ml-virama>";<BAS>;<MIN>;IGNORE
|
||||
<U0D38> "<ml-sa><ml-virama><mlvw-shorta>";<BAS>;<MIN>;IGNORE
|
||||
<ml-h> "<ml-ha><ml-virama>";<BAS>;<MIN>;IGNORE
|
||||
<U0D39> "<ml-ha><ml-virama><mlvw-shorta>";<BAS>;<MIN>;IGNORE
|
||||
<ml-chillu-ll> "<ml-lla><ml-virama>";<BAS>;<MIN>;IGNORE # ള് = ള + ് + zwj
|
||||
<U0D7E> "<ml-lla><ml-virama>";<ml-atomic-chillu-ll>;<MIN>;IGNORE
|
||||
<U0D33> "<ml-lla><ml-virama><mlvw-shorta>";<BAS>;<MIN>;IGNORE # ള = ള + ് + അ
|
||||
<ml-zh> "<ml-zha><ml-virama>";<BAS>;<MIN>;IGNORE
|
||||
<U0D34> "<ml-zha><ml-virama><mlvw-shorta>";<BAS>;<MIN>;IGNORE
|
||||
|
||||
+36
-5
@@ -702,8 +702,7 @@ _int_new_arena (size_t size)
|
||||
}
|
||||
|
||||
|
||||
/* Remove an arena from free_list. The arena may be in use because it
|
||||
was attached concurrently to a thread by reused_arena below. */
|
||||
/* Remove an arena from free_list. */
|
||||
static mstate
|
||||
get_free_list (void)
|
||||
{
|
||||
@@ -718,7 +717,8 @@ get_free_list (void)
|
||||
free_list = result->next_free;
|
||||
|
||||
/* The arena will be attached to this thread. */
|
||||
++result->attached_threads;
|
||||
assert (result->attached_threads == 0);
|
||||
result->attached_threads = 1;
|
||||
|
||||
detach_arena (replaced_arena);
|
||||
}
|
||||
@@ -735,6 +735,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. */
|
||||
@@ -782,14 +802,25 @@ reused_arena (mstate avoid_arena)
|
||||
(void) mutex_lock (&result->mutex);
|
||||
|
||||
out:
|
||||
/* Attach the arena to the current thread. Note that we may have
|
||||
selected an arena which was on free_list. */
|
||||
/* Attach the arena to the current thread. */
|
||||
{
|
||||
/* Update the arena thread attachment counters. */
|
||||
mstate replaced_arena = thread_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);
|
||||
}
|
||||
|
||||
|
||||
+1
-42
@@ -4271,11 +4271,6 @@ _int_realloc(mstate av, mchunkptr oldp, INTERNAL_SIZE_T oldsize,
|
||||
mchunkptr bck; /* misc temp for linking */
|
||||
mchunkptr fwd; /* misc temp for linking */
|
||||
|
||||
unsigned long copysize; /* bytes to copy */
|
||||
unsigned int ncopies; /* INTERNAL_SIZE_T words to copy */
|
||||
INTERNAL_SIZE_T* s; /* copy source */
|
||||
INTERNAL_SIZE_T* d; /* copy destination */
|
||||
|
||||
const char *errstr = NULL;
|
||||
|
||||
/* oldmem size */
|
||||
@@ -4353,43 +4348,7 @@ _int_realloc(mstate av, mchunkptr oldp, INTERNAL_SIZE_T oldsize,
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
Unroll copy of <= 36 bytes (72 if 8byte sizes)
|
||||
We know that contents have an odd number of
|
||||
INTERNAL_SIZE_T-sized words; minimally 3.
|
||||
*/
|
||||
|
||||
copysize = oldsize - SIZE_SZ;
|
||||
s = (INTERNAL_SIZE_T *) (chunk2mem (oldp));
|
||||
d = (INTERNAL_SIZE_T *) (newmem);
|
||||
ncopies = copysize / sizeof (INTERNAL_SIZE_T);
|
||||
assert (ncopies >= 3);
|
||||
|
||||
if (ncopies > 9)
|
||||
memcpy (d, s, copysize);
|
||||
|
||||
else
|
||||
{
|
||||
*(d + 0) = *(s + 0);
|
||||
*(d + 1) = *(s + 1);
|
||||
*(d + 2) = *(s + 2);
|
||||
if (ncopies > 4)
|
||||
{
|
||||
*(d + 3) = *(s + 3);
|
||||
*(d + 4) = *(s + 4);
|
||||
if (ncopies > 6)
|
||||
{
|
||||
*(d + 5) = *(s + 5);
|
||||
*(d + 6) = *(s + 6);
|
||||
if (ncopies > 8)
|
||||
{
|
||||
*(d + 7) = *(s + 7);
|
||||
*(d + 8) = *(s + 8);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
memcpy (newmem, chunk2mem (oldp), oldsize - SIZE_SZ);
|
||||
_int_free (av, oldp, 1);
|
||||
check_inuse_chunk (av, newp);
|
||||
return chunk2mem (newp);
|
||||
|
||||
+5
-4
@@ -29,14 +29,15 @@
|
||||
|
||||
#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_23)
|
||||
|
||||
/* Define the variables used for the interface. */
|
||||
char *loc1;
|
||||
char *loc2;
|
||||
/* Define the variables used for the interface. Avoid .symver on common
|
||||
symbol, which just creates a new common symbol, not an alias. */
|
||||
char *loc1 __attribute__ ((nocommon));
|
||||
char *loc2 __attribute__ ((nocommon));
|
||||
compat_symbol (libc, loc1, loc1, GLIBC_2_0);
|
||||
compat_symbol (libc, loc2, loc2, GLIBC_2_0);
|
||||
|
||||
/* Although we do not support the use we define this variable as well. */
|
||||
char *locs;
|
||||
char *locs __attribute__ ((nocommon));
|
||||
compat_symbol (libc, locs, locs, GLIBC_2_0);
|
||||
|
||||
|
||||
|
||||
@@ -291,7 +291,7 @@ _nss_nisplus_getaliasbyname_r (const char *name, struct aliasent *alias,
|
||||
return status;
|
||||
}
|
||||
|
||||
if (name != NULL)
|
||||
if (name == NULL)
|
||||
{
|
||||
*errnop = EINVAL;
|
||||
return NSS_STATUS_UNAVAIL;
|
||||
|
||||
+5
-2
@@ -268,7 +268,7 @@ tests = tst-typesizes \
|
||||
tst-flock1 tst-flock2 \
|
||||
tst-signal1 tst-signal2 tst-signal3 tst-signal4 tst-signal5 \
|
||||
tst-signal6 tst-signal7 \
|
||||
tst-exec1 tst-exec2 tst-exec3 tst-exec4 \
|
||||
tst-exec1 tst-exec2 tst-exec3 tst-exec4 tst-exec5 \
|
||||
tst-exit1 tst-exit2 tst-exit3 \
|
||||
tst-stdio1 tst-stdio2 \
|
||||
tst-stack1 tst-stack2 tst-stack3 tst-stack4 tst-pthread-getattr \
|
||||
@@ -290,7 +290,10 @@ tests = tst-typesizes \
|
||||
tst-initializers1 $(addprefix tst-initializers1-,\
|
||||
c89 gnu89 c99 gnu99 c11 gnu11) \
|
||||
tst-bad-schedattr \
|
||||
tst-thread_local1 tst-mutex-errorcheck tst-robust10
|
||||
tst-thread_local1 tst-mutex-errorcheck tst-robust10 \
|
||||
tst-minstack-cancel tst-minstack-exit \
|
||||
tst-create-detached
|
||||
|
||||
xtests = tst-setuid1 tst-setuid1-static tst-setuid2 \
|
||||
tst-mutexpp1 tst-mutexpp6 tst-mutexpp10
|
||||
test-srcs = tst-oddstacklimit
|
||||
|
||||
+6
-18
@@ -440,9 +440,6 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
|
||||
SETUP_THREAD_SYSINFO (pd);
|
||||
#endif
|
||||
|
||||
/* The process ID is also the same as that of the caller. */
|
||||
pd->pid = THREAD_GETMEM (THREAD_SELF, pid);
|
||||
|
||||
/* Don't allow setxid until cloned. */
|
||||
pd->setxid_futex = -1;
|
||||
|
||||
@@ -487,6 +484,10 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
|
||||
/* Make sure the size of the stack is enough for the guard and
|
||||
eventually the thread descriptor. */
|
||||
guardsize = (attr->guardsize + pagesize_m1) & ~pagesize_m1;
|
||||
if (guardsize < attr->guardsize || size + guardsize < guardsize)
|
||||
/* Arithmetic overflow. */
|
||||
return EINVAL;
|
||||
size += guardsize;
|
||||
if (__builtin_expect (size < ((guardsize + __static_tls_size
|
||||
+ MINIMAL_REST_STACK + pagesize_m1)
|
||||
& ~pagesize_m1),
|
||||
@@ -579,9 +580,6 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
|
||||
/* Don't allow setxid until cloned. */
|
||||
pd->setxid_futex = -1;
|
||||
|
||||
/* The process ID is also the same as that of the caller. */
|
||||
pd->pid = THREAD_GETMEM (THREAD_SELF, pid);
|
||||
|
||||
/* Allocate the DTV for this thread. */
|
||||
if (_dl_allocate_tls (TLS_TPADJ (pd)) == NULL)
|
||||
{
|
||||
@@ -875,9 +873,6 @@ __reclaim_stacks (void)
|
||||
/* This marks the stack as free. */
|
||||
curp->tid = 0;
|
||||
|
||||
/* The PID field must be initialized for the new process. */
|
||||
curp->pid = self->pid;
|
||||
|
||||
/* Account for the size of the stack. */
|
||||
stack_cache_actsize += curp->stackblock_size;
|
||||
|
||||
@@ -903,13 +898,6 @@ __reclaim_stacks (void)
|
||||
}
|
||||
}
|
||||
|
||||
/* Reset the PIDs in any cached stacks. */
|
||||
list_for_each (runp, &stack_cache)
|
||||
{
|
||||
struct pthread *curp = list_entry (runp, struct pthread, list);
|
||||
curp->pid = self->pid;
|
||||
}
|
||||
|
||||
/* Add the stack of all running threads to the cache. */
|
||||
list_splice (&stack_used, &stack_cache);
|
||||
|
||||
@@ -1054,9 +1042,9 @@ setxid_signal_thread (struct xid_command *cmdp, struct pthread *t)
|
||||
return 0;
|
||||
|
||||
int val;
|
||||
pid_t pid = __getpid ();
|
||||
INTERNAL_SYSCALL_DECL (err);
|
||||
val = INTERNAL_SYSCALL (tgkill, err, 3, THREAD_GETMEM (THREAD_SELF, pid),
|
||||
t->tid, SIGSETXID);
|
||||
val = INTERNAL_SYSCALL_CALL (tgkill, err, pid, t->tid, SIGSETXID);
|
||||
|
||||
/* If this failed, it must have had not started yet or else exited. */
|
||||
if (!INTERNAL_SYSCALL_ERROR_P (val, err))
|
||||
|
||||
+4
-6
@@ -25,16 +25,14 @@
|
||||
|
||||
static int
|
||||
create_thread (struct pthread *pd, const struct pthread_attr *attr,
|
||||
bool stopped_start, STACK_VARIABLES_PARMS, bool *thread_ran)
|
||||
bool *stopped_start, STACK_VARIABLES_PARMS, bool *thread_ran)
|
||||
{
|
||||
/* If the implementation needs to do some tweaks to the thread after
|
||||
it has been created at the OS level, it can set STOPPED_START here. */
|
||||
|
||||
pd->stopped_start = stopped_start;
|
||||
if (__glibc_unlikely (stopped_start))
|
||||
/* We make sure the thread does not run far by forcing it to get a
|
||||
lock. We lock it here too so that the new thread cannot continue
|
||||
until we tell it to. */
|
||||
pd->stopped_start = *stopped_start;
|
||||
if (__glibc_unlikely (*stopped_start))
|
||||
/* See CONCURRENCY NOTES in nptl/pthread_create.c. */
|
||||
lll_lock (pd->lock, LLL_PRIVATE);
|
||||
|
||||
return ENOSYS;
|
||||
|
||||
+4
-4
@@ -167,8 +167,8 @@ struct pthread
|
||||
therefore stack) used' flag. */
|
||||
pid_t tid;
|
||||
|
||||
/* Process ID - thread group ID in kernel speak. */
|
||||
pid_t pid;
|
||||
/* Ununsed. */
|
||||
pid_t pid_ununsed;
|
||||
|
||||
/* List of robust mutexes the thread is holding. */
|
||||
#ifdef __PTHREAD_MUTEX_HAVE_PREV
|
||||
@@ -363,9 +363,9 @@ struct pthread
|
||||
/* Machine-specific unwind info. */
|
||||
struct _Unwind_Exception exc;
|
||||
|
||||
/* If nonzero pointer to area allocated for the stack and its
|
||||
size. */
|
||||
/* If nonzero, pointer to the area allocated for the stack and guard. */
|
||||
void *stackblock;
|
||||
/* Size of the stackblock area including the guard. */
|
||||
size_t stackblock_size;
|
||||
/* Size of the included guard area. */
|
||||
size_t guardsize;
|
||||
|
||||
+3
-17
@@ -184,18 +184,12 @@ __nptl_set_robust (struct pthread *self)
|
||||
static void
|
||||
sigcancel_handler (int sig, siginfo_t *si, void *ctx)
|
||||
{
|
||||
/* Determine the process ID. It might be negative if the thread is
|
||||
in the middle of a fork() call. */
|
||||
pid_t pid = THREAD_GETMEM (THREAD_SELF, pid);
|
||||
if (__glibc_unlikely (pid < 0))
|
||||
pid = -pid;
|
||||
|
||||
/* Safety check. It would be possible to call this function for
|
||||
other signals and send a signal from another process. This is not
|
||||
correct and might even be a security problem. Try to catch as
|
||||
many incorrect invocations as possible. */
|
||||
if (sig != SIGCANCEL
|
||||
|| si->si_pid != pid
|
||||
|| si->si_pid != __getpid()
|
||||
|| si->si_code != SI_TKILL)
|
||||
return;
|
||||
|
||||
@@ -243,19 +237,14 @@ struct xid_command *__xidcmd attribute_hidden;
|
||||
static void
|
||||
sighandler_setxid (int sig, siginfo_t *si, void *ctx)
|
||||
{
|
||||
/* Determine the process ID. It might be negative if the thread is
|
||||
in the middle of a fork() call. */
|
||||
pid_t pid = THREAD_GETMEM (THREAD_SELF, pid);
|
||||
int result;
|
||||
if (__glibc_unlikely (pid < 0))
|
||||
pid = -pid;
|
||||
|
||||
/* Safety check. It would be possible to call this function for
|
||||
other signals and send a signal from another process. This is not
|
||||
correct and might even be a security problem. Try to catch as
|
||||
many incorrect invocations as possible. */
|
||||
if (sig != SIGSETXID
|
||||
|| si->si_pid != pid
|
||||
|| si->si_pid != __getpid ()
|
||||
|| si->si_code != SI_TKILL)
|
||||
return;
|
||||
|
||||
@@ -504,8 +493,5 @@ strong_alias (__pthread_initialize_minimal_internal,
|
||||
size_t
|
||||
__pthread_get_minstack (const pthread_attr_t *attr)
|
||||
{
|
||||
struct pthread_attr *iattr = (struct pthread_attr *) attr;
|
||||
|
||||
return (GLRO(dl_pagesize) + __static_tls_size + PTHREAD_STACK_MIN
|
||||
+ iattr->guardsize);
|
||||
return GLRO(dl_pagesize) + __static_tls_size + PTHREAD_STACK_MIN;
|
||||
}
|
||||
|
||||
+5
-13
@@ -22,7 +22,7 @@
|
||||
#include "pthreadP.h"
|
||||
#include <atomic.h>
|
||||
#include <sysdep.h>
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
int
|
||||
pthread_cancel (pthread_t th)
|
||||
@@ -66,19 +66,11 @@ pthread_cancel (pthread_t th)
|
||||
#ifdef SIGCANCEL
|
||||
/* The cancellation handler will take care of marking the
|
||||
thread as canceled. */
|
||||
pid_t pid = getpid ();
|
||||
|
||||
INTERNAL_SYSCALL_DECL (err);
|
||||
|
||||
/* One comment: The PID field in the TCB can temporarily be
|
||||
changed (in fork). But this must not affect this code
|
||||
here. Since this function would have to be called while
|
||||
the thread is executing fork, it would have to happen in
|
||||
a signal handler. But this is no allowed, pthread_cancel
|
||||
is not guaranteed to be async-safe. */
|
||||
int val;
|
||||
val = INTERNAL_SYSCALL (tgkill, err, 3,
|
||||
THREAD_GETMEM (THREAD_SELF, pid), pd->tid,
|
||||
SIGCANCEL);
|
||||
|
||||
int val = INTERNAL_SYSCALL_CALL (tgkill, err, pid, pd->tid,
|
||||
SIGCANCEL);
|
||||
if (INTERNAL_SYSCALL_ERROR_P (val, err))
|
||||
result = INTERNAL_SYSCALL_ERRNO (val, err);
|
||||
#else
|
||||
|
||||
+174
-33
@@ -54,25 +54,141 @@ unsigned int __nptl_nthreads = 1;
|
||||
/* Code to allocate and deallocate a stack. */
|
||||
#include "allocatestack.c"
|
||||
|
||||
/* createthread.c defines this function, and two macros:
|
||||
/* CONCURRENCY NOTES:
|
||||
|
||||
Understanding who is the owner of the 'struct pthread' or 'PD'
|
||||
(refers to the value of the 'struct pthread *pd' function argument)
|
||||
is critically important in determining exactly which operations are
|
||||
allowed and which are not and when, particularly when it comes to the
|
||||
implementation of pthread_create, pthread_join, pthread_detach, and
|
||||
other functions which all operate on PD.
|
||||
|
||||
The owner of PD is responsible for freeing the final resources
|
||||
associated with PD, and may examine the memory underlying PD at any
|
||||
point in time until it frees it back to the OS or to reuse by the
|
||||
runtime.
|
||||
|
||||
The thread which calls pthread_create is called the creating thread.
|
||||
The creating thread begins as the owner of PD.
|
||||
|
||||
During startup the new thread may examine PD in coordination with the
|
||||
owner thread (which may be itself).
|
||||
|
||||
The four cases of ownership transfer are:
|
||||
|
||||
(1) Ownership of PD is released to the process (all threads may use it)
|
||||
after the new thread starts in a joinable state
|
||||
i.e. pthread_create returns a usable pthread_t.
|
||||
|
||||
(2) Ownership of PD is released to the new thread starting in a detached
|
||||
state.
|
||||
|
||||
(3) Ownership of PD is dynamically released to a running thread via
|
||||
pthread_detach.
|
||||
|
||||
(4) Ownership of PD is acquired by the thread which calls pthread_join.
|
||||
|
||||
Implementation notes:
|
||||
|
||||
The PD->stopped_start and thread_ran variables are used to determine
|
||||
exactly which of the four ownership states we are in and therefore
|
||||
what actions can be taken. For example after (2) we cannot read or
|
||||
write from PD anymore since the thread may no longer exist and the
|
||||
memory may be unmapped. The most complicated cases happen during
|
||||
thread startup:
|
||||
|
||||
(a) If the created thread is in a detached (PTHREAD_CREATE_DETACHED),
|
||||
or joinable (default PTHREAD_CREATE_JOINABLE) state and
|
||||
STOPPED_START is true, then the creating thread has ownership of
|
||||
PD until the PD->lock is released by pthread_create. If any
|
||||
errors occur we are in states (c), (d), or (e) below.
|
||||
|
||||
(b) If the created thread is in a detached state
|
||||
(PTHREAD_CREATED_DETACHED), and STOPPED_START is false, then the
|
||||
creating thread has ownership of PD until it invokes the OS
|
||||
kernel's thread creation routine. If this routine returns
|
||||
without error, then the created thread owns PD; otherwise, see
|
||||
(c) and (e) below.
|
||||
|
||||
(c) If the detached thread setup failed and THREAD_RAN is true, then
|
||||
the creating thread releases ownership to the new thread by
|
||||
sending a cancellation signal. All threads set THREAD_RAN to
|
||||
true as quickly as possible after returning from the OS kernel's
|
||||
thread creation routine.
|
||||
|
||||
(d) If the joinable thread setup failed and THREAD_RAN is true, then
|
||||
then the creating thread retains ownership of PD and must cleanup
|
||||
state. Ownership cannot be released to the process via the
|
||||
return of pthread_create since a non-zero result entails PD is
|
||||
undefined and therefore cannot be joined to free the resources.
|
||||
We privately call pthread_join on the thread to finish handling
|
||||
the resource shutdown (Or at least we should, see bug 19511).
|
||||
|
||||
(e) If the thread creation failed and THREAD_RAN is false, then the
|
||||
creating thread retains ownership of PD and must cleanup state.
|
||||
No waiting for the new thread is required because it never
|
||||
started.
|
||||
|
||||
The nptl_db interface:
|
||||
|
||||
The interface with nptl_db requires that we enqueue PD into a linked
|
||||
list and then call a function which the debugger will trap. The PD
|
||||
will then be dequeued and control returned to the thread. The caller
|
||||
at the time must have ownership of PD and such ownership remains
|
||||
after control returns to thread. The enqueued PD is removed from the
|
||||
linked list by the nptl_db callback td_thr_event_getmsg. The debugger
|
||||
must ensure that the thread does not resume execution, otherwise
|
||||
ownership of PD may be lost and examining PD will not be possible.
|
||||
|
||||
Note that the GNU Debugger as of (December 10th 2015) commit
|
||||
c2c2a31fdb228d41ce3db62b268efea04bd39c18 no longer uses
|
||||
td_thr_event_getmsg and several other related nptl_db interfaces. The
|
||||
principal reason for this is that nptl_db does not support non-stop
|
||||
mode where other threads can run concurrently and modify runtime
|
||||
structures currently in use by the debugger and the nptl_db
|
||||
interface.
|
||||
|
||||
Axioms:
|
||||
|
||||
* The create_thread function can never set stopped_start to false.
|
||||
* The created thread can read stopped_start but never write to it.
|
||||
* The variable thread_ran is set some time after the OS thread
|
||||
creation routine returns, how much time after the thread is created
|
||||
is unspecified, but it should be as quickly as possible.
|
||||
|
||||
*/
|
||||
|
||||
/* CREATE THREAD NOTES:
|
||||
|
||||
createthread.c defines the create_thread function, and two macros:
|
||||
START_THREAD_DEFN and START_THREAD_SELF (see below).
|
||||
|
||||
create_thread is obliged to initialize PD->stopped_start. It
|
||||
should be true if the STOPPED_START parameter is true, or if
|
||||
create_thread needs the new thread to synchronize at startup for
|
||||
some other implementation reason. If PD->stopped_start will be
|
||||
true, then create_thread is obliged to perform the operation
|
||||
"lll_lock (PD->lock, LLL_PRIVATE)" before starting the thread.
|
||||
create_thread must initialize PD->stopped_start. It should be true
|
||||
if the STOPPED_START parameter is true, or if create_thread needs the
|
||||
new thread to synchronize at startup for some other implementation
|
||||
reason. If STOPPED_START will be true, then create_thread is obliged
|
||||
to lock PD->lock before starting the thread. Then pthread_create
|
||||
unlocks PD->lock which synchronizes-with START_THREAD_DEFN in the
|
||||
child thread which does an acquire/release of PD->lock as the last
|
||||
action before calling the user entry point. The goal of all of this
|
||||
is to ensure that the required initial thread attributes are applied
|
||||
(by the creating thread) before the new thread runs user code. Note
|
||||
that the the functions pthread_getschedparam, pthread_setschedparam,
|
||||
pthread_setschedprio, __pthread_tpp_change_priority, and
|
||||
__pthread_current_priority reuse the same lock, PD->lock, for a
|
||||
similar purpose e.g. synchronizing the setting of similar thread
|
||||
attributes. These functions are never called before the thread is
|
||||
created, so don't participate in startup syncronization, but given
|
||||
that the lock is present already and in the unlocked state, reusing
|
||||
it saves space.
|
||||
|
||||
The return value is zero for success or an errno code for failure.
|
||||
If the return value is ENOMEM, that will be translated to EAGAIN,
|
||||
so create_thread need not do that. On failure, *THREAD_RAN should
|
||||
be set to true iff the thread actually started up and then got
|
||||
cancelled before calling user code (*PD->start_routine), in which
|
||||
case it is responsible for doing its own cleanup. */
|
||||
|
||||
canceled before calling user code (*PD->start_routine). */
|
||||
static int create_thread (struct pthread *pd, const struct pthread_attr *attr,
|
||||
bool stopped_start, STACK_VARIABLES_PARMS,
|
||||
bool *stopped_start, STACK_VARIABLES_PARMS,
|
||||
bool *thread_ran);
|
||||
|
||||
#include <createthread.c>
|
||||
@@ -314,12 +430,19 @@ START_THREAD_DEFN
|
||||
/* Store the new cleanup handler info. */
|
||||
THREAD_SETMEM (pd, cleanup_jmp_buf, &unwind_buf);
|
||||
|
||||
/* We are either in (a) or (b), and in either case we either own
|
||||
PD already (2) or are about to own PD (1), and so our only
|
||||
restriction would be that we can't free PD until we know we
|
||||
have ownership (see CONCURRENCY NOTES above). */
|
||||
if (__glibc_unlikely (pd->stopped_start))
|
||||
{
|
||||
int oldtype = CANCEL_ASYNC ();
|
||||
|
||||
/* Get the lock the parent locked to force synchronization. */
|
||||
lll_lock (pd->lock, LLL_PRIVATE);
|
||||
|
||||
/* We have ownership of PD now. */
|
||||
|
||||
/* And give it up right away. */
|
||||
lll_unlock (pd->lock, LLL_PRIVATE);
|
||||
|
||||
@@ -378,7 +501,8 @@ START_THREAD_DEFN
|
||||
pd, pd->nextevent));
|
||||
}
|
||||
|
||||
/* Now call the function to signal the event. */
|
||||
/* Now call the function which signals the event. See
|
||||
CONCURRENCY NOTES for the nptl_db interface comments. */
|
||||
__nptl_death_event ();
|
||||
}
|
||||
}
|
||||
@@ -642,19 +766,28 @@ __pthread_create_2_1 (pthread_t *newthread, const pthread_attr_t *attr,
|
||||
that cares whether the thread count is correct. */
|
||||
atomic_increment (&__nptl_nthreads);
|
||||
|
||||
bool thread_ran = false;
|
||||
/* Our local value of stopped_start and thread_ran can be accessed at
|
||||
any time. The PD->stopped_start may only be accessed if we have
|
||||
ownership of PD (see CONCURRENCY NOTES above). */
|
||||
bool stopped_start = false; bool thread_ran = false;
|
||||
|
||||
/* Start the thread. */
|
||||
if (__glibc_unlikely (report_thread_creation (pd)))
|
||||
{
|
||||
/* Create the thread. We always create the thread stopped
|
||||
so that it does not get far before we tell the debugger. */
|
||||
retval = create_thread (pd, iattr, true, STACK_VARIABLES_ARGS,
|
||||
&thread_ran);
|
||||
stopped_start = true;
|
||||
|
||||
/* We always create the thread stopped at startup so we can
|
||||
notify the debugger. */
|
||||
retval = create_thread (pd, iattr, &stopped_start,
|
||||
STACK_VARIABLES_ARGS, &thread_ran);
|
||||
if (retval == 0)
|
||||
{
|
||||
/* create_thread should have set this so that the logic below can
|
||||
test it. */
|
||||
/* We retain ownership of PD until (a) (see CONCURRENCY NOTES
|
||||
above). */
|
||||
|
||||
/* Assert stopped_start is true in both our local copy and the
|
||||
PD copy. */
|
||||
assert (stopped_start);
|
||||
assert (pd->stopped_start);
|
||||
|
||||
/* Now fill in the information about the new thread in
|
||||
@@ -671,26 +804,30 @@ __pthread_create_2_1 (pthread_t *newthread, const pthread_attr_t *attr,
|
||||
pd, pd->nextevent)
|
||||
!= 0);
|
||||
|
||||
/* Now call the function which signals the event. */
|
||||
/* Now call the function which signals the event. See
|
||||
CONCURRENCY NOTES for the nptl_db interface comments. */
|
||||
__nptl_create_event ();
|
||||
}
|
||||
}
|
||||
else
|
||||
retval = create_thread (pd, iattr, false, STACK_VARIABLES_ARGS,
|
||||
&thread_ran);
|
||||
retval = create_thread (pd, iattr, &stopped_start,
|
||||
STACK_VARIABLES_ARGS, &thread_ran);
|
||||
|
||||
if (__glibc_unlikely (retval != 0))
|
||||
{
|
||||
/* If thread creation "failed", that might mean that the thread got
|
||||
created and ran a little--short of running user code--but then
|
||||
create_thread cancelled it. In that case, the thread will do all
|
||||
its own cleanup just like a normal thread exit after a successful
|
||||
creation would do. */
|
||||
|
||||
if (thread_ran)
|
||||
assert (pd->stopped_start);
|
||||
/* State (c) or (d) and we may not have PD ownership (see
|
||||
CONCURRENCY NOTES above). We can assert that STOPPED_START
|
||||
must have been true because thread creation didn't fail, but
|
||||
thread attribute setting did. */
|
||||
/* See bug 19511 which explains why doing nothing here is a
|
||||
resource leak for a joinable thread. */
|
||||
assert (stopped_start);
|
||||
else
|
||||
{
|
||||
/* State (e) and we have ownership of PD (see CONCURRENCY
|
||||
NOTES above). */
|
||||
|
||||
/* Oops, we lied for a second. */
|
||||
atomic_decrement (&__nptl_nthreads);
|
||||
|
||||
@@ -710,10 +847,14 @@ __pthread_create_2_1 (pthread_t *newthread, const pthread_attr_t *attr,
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pd->stopped_start)
|
||||
/* The thread blocked on this lock either because we're doing TD_CREATE
|
||||
event reporting, or for some other reason that create_thread chose.
|
||||
Now let it run free. */
|
||||
/* We don't know if we have PD ownership. Once we check the local
|
||||
stopped_start we'll know if we're in state (a) or (b) (see
|
||||
CONCURRENCY NOTES above). */
|
||||
if (stopped_start)
|
||||
/* State (a), we own PD. The thread blocked on this lock either
|
||||
because we're doing TD_CREATE event reporting, or for some
|
||||
other reason that create_thread chose. Now let it run
|
||||
free. */
|
||||
lll_unlock (pd->lock, LLL_PRIVATE);
|
||||
|
||||
/* We now have for sure more than one thread. The main thread might
|
||||
|
||||
@@ -57,9 +57,12 @@ pthread_getattr_np (pthread_t thread_id, pthread_attr_t *attr)
|
||||
/* The sizes are subject to alignment. */
|
||||
if (__glibc_likely (thread->stackblock != NULL))
|
||||
{
|
||||
iattr->stacksize = thread->stackblock_size;
|
||||
/* The stack size reported to the user should not include the
|
||||
guard size. */
|
||||
iattr->stacksize = thread->stackblock_size - thread->guardsize;
|
||||
#if _STACK_GROWS_DOWN
|
||||
iattr->stackaddr = (char *) thread->stackblock + iattr->stacksize;
|
||||
iattr->stackaddr = (char *) thread->stackblock
|
||||
+ thread->stackblock_size;
|
||||
#else
|
||||
iattr->stackaddr = (char *) thread->stackblock;
|
||||
#endif
|
||||
@@ -68,7 +71,6 @@ pthread_getattr_np (pthread_t thread_id, pthread_attr_t *attr)
|
||||
{
|
||||
/* No stack information available. This must be for the initial
|
||||
thread. Get the info in some magical way. */
|
||||
assert (abs (thread->pid) == thread->tid);
|
||||
|
||||
/* Stack size limit. */
|
||||
struct rlimit rl;
|
||||
|
||||
@@ -35,6 +35,7 @@ __pthread_getschedparam (pthread_t threadid, int *policy,
|
||||
|
||||
int result = 0;
|
||||
|
||||
/* See CREATE THREAD NOTES in nptl/pthread_create.c. */
|
||||
lll_lock (pd->lock, LLL_PRIVATE);
|
||||
|
||||
/* The library is responsible for maintaining the values at all
|
||||
|
||||
@@ -36,6 +36,7 @@ __pthread_setschedparam (pthread_t threadid, int policy,
|
||||
|
||||
int result = 0;
|
||||
|
||||
/* See CREATE THREAD NOTES in nptl/pthread_create.c. */
|
||||
lll_lock (pd->lock, LLL_PRIVATE);
|
||||
|
||||
struct sched_param p;
|
||||
|
||||
@@ -38,6 +38,7 @@ pthread_setschedprio (pthread_t threadid, int prio)
|
||||
struct sched_param param;
|
||||
param.sched_priority = prio;
|
||||
|
||||
/* See CREATE THREAD NOTES in nptl/pthread_create.c. */
|
||||
lll_lock (pd->lock, LLL_PRIVATE);
|
||||
|
||||
/* If the thread should have higher priority because of some
|
||||
|
||||
@@ -114,6 +114,7 @@ __pthread_tpp_change_priority (int previous_prio, int new_prio)
|
||||
if (priomax == newpriomax)
|
||||
return 0;
|
||||
|
||||
/* See CREATE THREAD NOTES in nptl/pthread_create.c. */
|
||||
lll_lock (self->lock, LLL_PRIVATE);
|
||||
|
||||
tpp->priomax = newpriomax;
|
||||
@@ -165,6 +166,7 @@ __pthread_current_priority (void)
|
||||
|
||||
int result = 0;
|
||||
|
||||
/* See CREATE THREAD NOTES in nptl/pthread_create.c. */
|
||||
lll_lock (self->lock, LLL_PRIVATE);
|
||||
|
||||
if ((self->flags & ATTR_FLAG_SCHED_SET) == 0)
|
||||
|
||||
@@ -0,0 +1,137 @@
|
||||
/* Bug 20116: Test rapid creation of detached threads.
|
||||
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; see the file COPYING.LIB. If
|
||||
not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
/* The goal of the test is to trigger a failure if the parent touches
|
||||
any part of the thread descriptor after the detached thread has
|
||||
exited. We test this by creating many detached threads with large
|
||||
stacks. The stacks quickly fill the the stack cache and subsequent
|
||||
threads will start to cause the thread stacks to be immediately
|
||||
unmapped to satisfy the stack cache max. With the stacks being
|
||||
unmapped the parent's read of any part of the thread descriptor will
|
||||
trigger a segfault. That segfault is what we are trying to cause,
|
||||
since any segfault is a defect in the implementation. */
|
||||
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <stdbool.h>
|
||||
#include <sys/resource.h>
|
||||
#include <support/xthread.h>
|
||||
|
||||
/* Number of threads to create. */
|
||||
enum { threads_to_create = 100000 };
|
||||
|
||||
/* Number of threads which should spawn other threads. */
|
||||
enum { creator_threads = 2 };
|
||||
|
||||
/* Counter of threads created so far. This is incremented by all the
|
||||
running creator threads. */
|
||||
static unsigned threads_created;
|
||||
|
||||
/* Thread callback which does nothing, so that the thread exits
|
||||
immediatedly. */
|
||||
static void *
|
||||
do_nothing (void *arg)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Attribute indicating that the thread should be created in a detached
|
||||
fashion. */
|
||||
static pthread_attr_t detached;
|
||||
|
||||
/* Barrier to synchronize initialization. */
|
||||
static pthread_barrier_t barrier;
|
||||
|
||||
static void *
|
||||
creator_thread (void *arg)
|
||||
{
|
||||
int ret;
|
||||
xpthread_barrier_wait (&barrier);
|
||||
|
||||
while (true)
|
||||
{
|
||||
pthread_t thr;
|
||||
/* Thread creation will fail if the kernel does not free old
|
||||
threads quickly enough, so we do not report errors. */
|
||||
ret = pthread_create (&thr, &detached, do_nothing, NULL);
|
||||
if (ret == 0 && __atomic_add_fetch (&threads_created, 1, __ATOMIC_SEQ_CST)
|
||||
>= threads_to_create)
|
||||
break;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
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 ("FAIL: getrlimit (RLIMIT_AS) failed: %m\n");
|
||||
return 1;
|
||||
}
|
||||
/* This limit, 800MB, is just a heuristic. Any value can be
|
||||
picked. */
|
||||
long target = 800 * 1024 * 1024;
|
||||
if (limit.rlim_cur == RLIM_INFINITY || limit.rlim_cur > target)
|
||||
{
|
||||
limit.rlim_cur = target;
|
||||
if (setrlimit (RLIMIT_AS, &limit) != 0)
|
||||
{
|
||||
printf ("FAIL: setrlimit (RLIMIT_AS) failed: %m\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
xpthread_attr_init (&detached);
|
||||
|
||||
xpthread_attr_setdetachstate (&detached, PTHREAD_CREATE_DETACHED);
|
||||
|
||||
/* A large thread stack seems beneficial for reproducing a race
|
||||
condition in detached thread creation. The goal is to reach the
|
||||
limit of the runtime thread stack cache such that the detached
|
||||
thread's stack is unmapped after exit and causes a segfault when
|
||||
the parent reads the thread descriptor data stored on the the
|
||||
unmapped stack. */
|
||||
xpthread_attr_setstacksize (&detached, 16 * 1024 * 1024);
|
||||
|
||||
xpthread_barrier_init (&barrier, NULL, creator_threads);
|
||||
|
||||
pthread_t threads[creator_threads];
|
||||
|
||||
for (int i = 0; i < creator_threads; ++i)
|
||||
threads[i] = xpthread_create (NULL, creator_thread, NULL);
|
||||
|
||||
for (int i = 0; i < creator_threads; ++i)
|
||||
xpthread_join (threads[i]);
|
||||
|
||||
xpthread_attr_destroy (&detached);
|
||||
|
||||
xpthread_barrier_destroy (&barrier);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include <support/test-driver.c>
|
||||
@@ -0,0 +1,196 @@
|
||||
/* Check if posix_spawn does not act as a cancellation entrypoint.
|
||||
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 <paths.h>
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
#include <spawn.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
static int do_test (void);
|
||||
#define TEST_FUNCTION do_test ()
|
||||
#include <test-skeleton.c>
|
||||
|
||||
static pthread_barrier_t b;
|
||||
|
||||
static pid_t pid;
|
||||
static int pipefd[2];
|
||||
|
||||
static void *
|
||||
tf (void *arg)
|
||||
{
|
||||
int r = pthread_barrier_wait (&b);
|
||||
if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
|
||||
{
|
||||
puts ("error: pthread_barrier_wait failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
posix_spawn_file_actions_t a;
|
||||
if (posix_spawn_file_actions_init (&a) != 0)
|
||||
{
|
||||
puts ("error: spawn_file_actions_init failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (posix_spawn_file_actions_adddup2 (&a, pipefd[1], STDOUT_FILENO) != 0)
|
||||
{
|
||||
puts ("error: spawn_file_actions_adddup2 failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (posix_spawn_file_actions_addclose (&a, pipefd[0]) != 0)
|
||||
{
|
||||
puts ("error: spawn_file_actions_addclose");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
char *argv[] = { (char *) _PATH_BSHELL, (char *) "-c", (char *) "echo $$",
|
||||
NULL };
|
||||
if (posix_spawn (&pid, _PATH_BSHELL, &a, NULL, argv, NULL) != 0)
|
||||
{
|
||||
puts ("error: spawn failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
/* The test basically pipe a 'echo $$' created by a thread with a
|
||||
cancellation pending. It then checks if the thread is not cancelled,
|
||||
the process is created and if the output is the expected one. */
|
||||
|
||||
if (pipe (pipefd) != 0)
|
||||
{
|
||||
puts ("error: pipe failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
/* Not interested in knowing when the pipe is closed. */
|
||||
if (sigignore (SIGPIPE) != 0)
|
||||
{
|
||||
puts ("error: sigignore failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
/* To synchronize with the thread. */
|
||||
if (pthread_barrier_init (&b, NULL, 2) != 0)
|
||||
{
|
||||
puts ("error: pthread_barrier_init failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
pthread_t th;
|
||||
if (pthread_create (&th, NULL, &tf, NULL) != 0)
|
||||
{
|
||||
puts ("error: pthread_create failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (pthread_cancel (th) != 0)
|
||||
{
|
||||
puts ("error: pthread_cancel failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
int r = pthread_barrier_wait (&b);
|
||||
if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
|
||||
{
|
||||
puts ("error: pthread_barrier_wait");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
void *retval;
|
||||
if (pthread_join (th, &retval) != 0)
|
||||
{
|
||||
puts ("error: pthread_join failed\n");
|
||||
}
|
||||
if (retval == PTHREAD_CANCELED)
|
||||
{
|
||||
puts ("error: thread cancelled");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
close (pipefd[1]);
|
||||
|
||||
/* The global 'pid' should be set by thread posix_spawn calling. Check
|
||||
below if it was executed correctly and with expected output. */
|
||||
|
||||
char buf[64];
|
||||
ssize_t n;
|
||||
bool seen_pid = false;
|
||||
while (TEMP_FAILURE_RETRY ((n = read (pipefd[0], buf, sizeof (buf)))) > 0)
|
||||
{
|
||||
/* We only expect to read the PID. */
|
||||
char *endp;
|
||||
long int rpid = strtol (buf, &endp, 10);
|
||||
|
||||
if (*endp != '\n')
|
||||
{
|
||||
printf ("error: didn't parse whole line: \"%s\"\n", buf);
|
||||
exit (1);
|
||||
}
|
||||
if (endp == buf)
|
||||
{
|
||||
puts ("error: read empty line");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (rpid != pid)
|
||||
{
|
||||
printf ("error: found \"%s\", expected PID %ld\n", buf,
|
||||
(long int) pid);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (seen_pid)
|
||||
{
|
||||
puts ("error: found more than one PID line");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
seen_pid = true;
|
||||
}
|
||||
|
||||
close (pipefd[0]);
|
||||
|
||||
int status;
|
||||
int err = waitpid (pid, &status, 0);
|
||||
if (err != pid)
|
||||
{
|
||||
puts ("errnor: waitpid failed");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (!seen_pid)
|
||||
{
|
||||
puts ("error: didn't get PID");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/* Test cancellation with a minimal stack size.
|
||||
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/>. */
|
||||
|
||||
/* Note: This test is similar to tst-minstack-exit, but is separate to
|
||||
avoid spurious test passes due to warm-up effects. */
|
||||
|
||||
#include <limits.h>
|
||||
#include <unistd.h>
|
||||
#include <support/check.h>
|
||||
#include <support/xthread.h>
|
||||
|
||||
static void *
|
||||
threadfunc (void *closure)
|
||||
{
|
||||
while (1)
|
||||
pause ();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
pthread_attr_t attr;
|
||||
xpthread_attr_init (&attr);
|
||||
xpthread_attr_setstacksize (&attr, PTHREAD_STACK_MIN);
|
||||
pthread_t thr = xpthread_create (&attr, threadfunc, NULL);
|
||||
xpthread_cancel (thr);
|
||||
TEST_VERIFY (xpthread_join (thr) == PTHREAD_CANCELED);
|
||||
xpthread_attr_destroy (&attr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include <support/test-driver.c>
|
||||
@@ -0,0 +1,46 @@
|
||||
/* Test that pthread_exit works with the minimum stack size.
|
||||
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/>. */
|
||||
|
||||
/* Note: This test is similar to tst-minstack-cancel, but is separate
|
||||
to avoid spurious test passes due to warm-up effects. */
|
||||
|
||||
#include <limits.h>
|
||||
#include <unistd.h>
|
||||
#include <support/check.h>
|
||||
#include <support/xthread.h>
|
||||
|
||||
static void *
|
||||
threadfunc (void *closure)
|
||||
{
|
||||
pthread_exit (threadfunc);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
pthread_attr_t attr;
|
||||
xpthread_attr_init (&attr);
|
||||
xpthread_attr_setstacksize (&attr, PTHREAD_STACK_MIN);
|
||||
pthread_t thr = xpthread_create (&attr, threadfunc, NULL);
|
||||
TEST_VERIFY (xpthread_join (thr) == threadfunc);
|
||||
xpthread_attr_destroy (&attr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include <support/test-driver.c>
|
||||
@@ -75,5 +75,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"
|
||||
|
||||
@@ -48,7 +48,6 @@ DB_STRUCT (pthread)
|
||||
DB_STRUCT_FIELD (pthread, list)
|
||||
DB_STRUCT_FIELD (pthread, report_events)
|
||||
DB_STRUCT_FIELD (pthread, tid)
|
||||
DB_STRUCT_FIELD (pthread, pid)
|
||||
DB_STRUCT_FIELD (pthread, start_routine)
|
||||
DB_STRUCT_FIELD (pthread, cancelhandling)
|
||||
DB_STRUCT_FIELD (pthread, schedpolicy)
|
||||
|
||||
+18
-38
@@ -76,48 +76,28 @@ iterate_thread_list (td_thragent_t *ta, td_thr_iter_f *callback,
|
||||
if (ps_pdread (ta->ph, addr, copy, ta->ta_sizeof_pthread) != PS_OK)
|
||||
return TD_ERR;
|
||||
|
||||
/* Verify that this thread's pid field matches the child PID.
|
||||
If its pid field is negative, it's about to do a fork or it
|
||||
is the sole thread in a fork child. */
|
||||
psaddr_t pid;
|
||||
err = DB_GET_FIELD_LOCAL (pid, ta, copy, pthread, pid, 0);
|
||||
if (err == TD_OK && (pid_t) (uintptr_t) pid < 0)
|
||||
{
|
||||
if (-(pid_t) (uintptr_t) pid == match_pid)
|
||||
/* It is about to do a fork, but is really still the parent PID. */
|
||||
pid = (psaddr_t) (uintptr_t) match_pid;
|
||||
else
|
||||
/* It must be a fork child, whose new PID is in the tid field. */
|
||||
err = DB_GET_FIELD_LOCAL (pid, ta, copy, pthread, tid, 0);
|
||||
}
|
||||
err = DB_GET_FIELD_LOCAL (schedpolicy, ta, copy, pthread,
|
||||
schedpolicy, 0);
|
||||
if (err != TD_OK)
|
||||
break;
|
||||
err = DB_GET_FIELD_LOCAL (schedprio, ta, copy, pthread,
|
||||
schedparam_sched_priority, 0);
|
||||
if (err != TD_OK)
|
||||
break;
|
||||
|
||||
if ((pid_t) (uintptr_t) pid == match_pid)
|
||||
/* Now test whether this thread matches the specified conditions. */
|
||||
|
||||
/* Only if the priority level is as high or higher. */
|
||||
int descr_pri = ((uintptr_t) schedpolicy == SCHED_OTHER
|
||||
? 0 : (uintptr_t) schedprio);
|
||||
if (descr_pri >= ti_pri)
|
||||
{
|
||||
err = DB_GET_FIELD_LOCAL (schedpolicy, ta, copy, pthread,
|
||||
schedpolicy, 0);
|
||||
if (err != TD_OK)
|
||||
break;
|
||||
err = DB_GET_FIELD_LOCAL (schedprio, ta, copy, pthread,
|
||||
schedparam_sched_priority, 0);
|
||||
if (err != TD_OK)
|
||||
break;
|
||||
|
||||
/* Now test whether this thread matches the specified conditions. */
|
||||
|
||||
/* Only if the priority level is as high or higher. */
|
||||
int descr_pri = ((uintptr_t) schedpolicy == SCHED_OTHER
|
||||
? 0 : (uintptr_t) schedprio);
|
||||
if (descr_pri >= ti_pri)
|
||||
{
|
||||
/* Yep, it matches. Call the callback function. */
|
||||
td_thrhandle_t th;
|
||||
th.th_ta_p = (td_thragent_t *) ta;
|
||||
th.th_unique = addr;
|
||||
if (callback (&th, cbdata_p) != 0)
|
||||
return TD_DBERR;
|
||||
}
|
||||
/* Yep, it matches. Call the callback function. */
|
||||
td_thrhandle_t th;
|
||||
th.th_ta_p = (td_thragent_t *) ta;
|
||||
th.th_unique = addr;
|
||||
if (callback (&th, cbdata_p) != 0)
|
||||
return TD_DBERR;
|
||||
}
|
||||
|
||||
/* Get the pointer to the next element. */
|
||||
|
||||
@@ -80,28 +80,5 @@ td_thr_validate (const td_thrhandle_t *th)
|
||||
err = TD_OK;
|
||||
}
|
||||
|
||||
if (err == TD_OK)
|
||||
{
|
||||
/* Verify that this is not a stale element in a fork child. */
|
||||
pid_t match_pid = ps_getpid (th->th_ta_p->ph);
|
||||
psaddr_t pid;
|
||||
err = DB_GET_FIELD (pid, th->th_ta_p, th->th_unique, pthread, pid, 0);
|
||||
if (err == TD_OK && (pid_t) (uintptr_t) pid < 0)
|
||||
{
|
||||
/* This was a thread that was about to fork, or it is the new sole
|
||||
thread in a fork child. In the latter case, its tid was stored
|
||||
via CLONE_CHILD_SETTID and so is already the proper child PID. */
|
||||
if (-(pid_t) (uintptr_t) pid == match_pid)
|
||||
/* It is about to do a fork, but is really still the parent PID. */
|
||||
pid = (psaddr_t) (uintptr_t) match_pid;
|
||||
else
|
||||
/* It must be a fork child, whose new PID is in the tid field. */
|
||||
err = DB_GET_FIELD (pid, th->th_ta_p, th->th_unique,
|
||||
pthread, tid, 0);
|
||||
}
|
||||
if (err == TD_OK && (pid_t) (uintptr_t) pid != match_pid)
|
||||
err = TD_NOTHR;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: GNU libc 2.22-pre1\n"
|
||||
"POT-Creation-Date: 2015-07-31 00:10-0400\n"
|
||||
"PO-Revision-Date: 2015-08-31 18:30+0200\n"
|
||||
"PO-Revision-Date: 2016-04-22 18:44+0200\n"
|
||||
"Last-Translator: Jochen Hein <jochen@jochen.org>\n"
|
||||
"Language-Team: German <translation-team-de@lists.sourceforge.net>\n"
|
||||
"Language: de\n"
|
||||
@@ -4479,13 +4479,13 @@ msgstr ""
|
||||
"%15s Cache ist dauerhaft\n"
|
||||
"%15s Cache wird gemeinsam verwendet\n"
|
||||
"%15Zu vorgeschlagene Größe\n"
|
||||
"%15Zu Gesamtröße des Data-Pools\n"
|
||||
"%15Zu Gesamtgröße des Data-Pools\n"
|
||||
"%15Zu Benutzter Speicher im Data-Pool\n"
|
||||
"%15lu Time to Live für positive Einträge in Sekunden\n"
|
||||
"%15lu Time to Live für negative Einträge in Sekunden\n"
|
||||
"%15<PRIuMAX> Cache-Hits bei positiven Einträgen\n"
|
||||
"%15<PRIuMAX> Cache-Hits bei positiven Einträgen\n"
|
||||
"%15<PRIuMAX> Cache-Misses bei positiven Einträgen\n"
|
||||
"%15<PRIuMAX> Cache-Misses bei positiven Einträgen\n"
|
||||
"%15<PRIuMAX> Cache-Misses bei negativen Einträgen\n"
|
||||
"%15lu%% Cache-Hit Verhältnis\n"
|
||||
"%15zu aktuelle Anzahl der Werte im Cache\n"
|
||||
|
||||
@@ -24,16 +24,16 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: libc 2.21-pre1\n"
|
||||
"Project-Id-Version: libc 2.22-pre1\n"
|
||||
"POT-Creation-Date: 2015-07-31 00:10-0400\n"
|
||||
"PO-Revision-Date: 2015-07-28 20:29+0300\n"
|
||||
"PO-Revision-Date: 2016-05-26 21:14+0300\n"
|
||||
"Last-Translator: Lauri Nurmi <lanurmi@iki.fi>\n"
|
||||
"Language-Team: Finnish <translation-team-fi@lists.sourceforge.net>\n"
|
||||
"Language: fi\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Generator: Poedit 1.8.3\n"
|
||||
"X-Generator: Poedit 1.8.7\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: argp/argp-help.c:227
|
||||
@@ -126,7 +126,7 @@ msgid "%s%s%s:%u: %s%sUnexpected error: %s.\n"
|
||||
msgstr "%s%s%s:%u: %s%sOdottamaton virhe: %s.\n"
|
||||
|
||||
#: assert/assert.c:101
|
||||
#, fuzzy, c-format
|
||||
#, c-format
|
||||
msgid ""
|
||||
"%s%s%s:%u: %s%sAssertion `%s' failed.\n"
|
||||
"%n"
|
||||
@@ -169,12 +169,12 @@ msgstr ""
|
||||
#: malloc/memusagestat.c:563 nss/getent.c:973 nss/makedb.c:369
|
||||
#: posix/getconf.c:486 sunrpc/rpcinfo.c:691
|
||||
#: sysdeps/unix/sysv/linux/lddlibc4.c:61
|
||||
#, fuzzy, c-format
|
||||
#, c-format
|
||||
msgid ""
|
||||
"For bug reporting instructions, please see:\n"
|
||||
"%s.\n"
|
||||
msgstr ""
|
||||
"Ohjeet ohjelmistovioista ilmoittamiseen ovat osoitteessa\n"
|
||||
"Katso ohjeet vikailmoitusten tekemiseen osoitteesta:\n"
|
||||
"%s.\n"
|
||||
|
||||
#: catgets/gencat.c:245 debug/pcprofiledump.c:225 debug/xtrace.sh:64
|
||||
@@ -321,9 +321,8 @@ msgstr "Käyttö: xtrace [VALITSIN]... OHJELMA [OHJELMANVALITSIN]...\\n"
|
||||
|
||||
#: debug/xtrace.sh:32 elf/sotruss.sh:56 elf/sotruss.sh:67 elf/sotruss.sh:135
|
||||
#: malloc/memusage.sh:26
|
||||
#, fuzzy
|
||||
msgid "Try \\`%s --help' or \\`%s --usage' for more information.\\n"
|
||||
msgstr "Kokeile ”%s --help” tai ”%s --usage” saadaksesi lisää tietoa.\n"
|
||||
msgstr "Kokeile ”%s --help” tai ”%s --usage” saadaksesi lisää tietoa.\\n"
|
||||
|
||||
#: debug/xtrace.sh:38
|
||||
#, fuzzy
|
||||
@@ -594,9 +593,8 @@ msgid "cannot enable executable stack as shared object requires"
|
||||
msgstr "jaettua objektikahvaa ei voi luoda"
|
||||
|
||||
#: elf/dl-load.c:1339
|
||||
#, fuzzy
|
||||
msgid "cannot close file descriptor"
|
||||
msgstr "tiedostoa %s ei voi sulkea"
|
||||
msgstr "tiedostokahvaa ei voi sulkea"
|
||||
|
||||
#: elf/dl-load.c:1568
|
||||
msgid "file too short"
|
||||
@@ -796,9 +794,8 @@ msgid "Format to use: new, old or compat (default)"
|
||||
msgstr "Käytettävä muoto: ”new”, ”old” tai ”compat” (oletus)"
|
||||
|
||||
#: elf/ldconfig.c:151
|
||||
#, fuzzy
|
||||
msgid "Ignore auxiliary cache file"
|
||||
msgstr "Käytä CACHEa välimuistitiedostona"
|
||||
msgstr "Jätä huomiotta apuvälimuistitiedosto"
|
||||
|
||||
#: elf/ldconfig.c:159
|
||||
msgid "Configure Dynamic Linker Run Time Bindings."
|
||||
@@ -1087,9 +1084,9 @@ msgid "invalid process ID '%s'"
|
||||
msgstr "virheellinen prosessi-ID ”%s”"
|
||||
|
||||
#: elf/pldd.c:120
|
||||
#, fuzzy, c-format
|
||||
#, c-format
|
||||
msgid "cannot open %s"
|
||||
msgstr "laitetta %s ei voi avata"
|
||||
msgstr "tiedostoa %s ei voi avata"
|
||||
|
||||
#: elf/pldd.c:152
|
||||
#, fuzzy, c-format
|
||||
@@ -1102,24 +1099,24 @@ msgid "cannot prepare reading %s/task"
|
||||
msgstr "ei voi avata laitetta %s lukutilaan"
|
||||
|
||||
#: elf/pldd.c:168
|
||||
#, fuzzy, c-format
|
||||
#, c-format
|
||||
msgid "invalid thread ID '%s'"
|
||||
msgstr "virheellinen prosessi-ID ”%s”"
|
||||
msgstr "virheellinen säie-ID ”%s”"
|
||||
|
||||
#: elf/pldd.c:179
|
||||
#, fuzzy, c-format
|
||||
#, c-format
|
||||
msgid "cannot attach to process %lu"
|
||||
msgstr "tiedostoa ”%s” ei voi avata"
|
||||
msgstr "ei voida kiinnittyä prosessiin %lu"
|
||||
|
||||
#: elf/pldd.c:294
|
||||
#, c-format
|
||||
msgid "cannot get information about process %lu"
|
||||
msgstr ""
|
||||
msgstr "tietojen saaminen prosessista %lu ei onnistu"
|
||||
|
||||
#: elf/pldd.c:307
|
||||
#, fuzzy, c-format
|
||||
#, c-format
|
||||
msgid "process %lu is no ELF program"
|
||||
msgstr "ohjelma %lu ei ole käytettävissä\n"
|
||||
msgstr "prosessi %lu ei ole ELF-ohjelma"
|
||||
|
||||
#: elf/readelflib.c:34
|
||||
#, c-format
|
||||
@@ -1203,7 +1200,7 @@ msgstr "%s kohde ei saa olla hakemisto\n"
|
||||
#: elf/sln.c:184
|
||||
#, c-format
|
||||
msgid "%s: failed to remove the old destination\n"
|
||||
msgstr ""
|
||||
msgstr "%s: vanhan kohteen poistaminen epäonnistui\n"
|
||||
|
||||
#: elf/sln.c:192
|
||||
#, c-format
|
||||
@@ -1237,9 +1234,8 @@ msgid "Mandatory arguments to long options are also mandatory for any correspond
|
||||
msgstr "Pakolliset argumentit pitkille valitsimille ovat pakollisia kaikille vastaaville lyhyille valitsimille.\\n"
|
||||
|
||||
#: elf/sotruss.sh:55
|
||||
#, fuzzy
|
||||
msgid "%s: option requires an argument -- '%s'\\n"
|
||||
msgstr "%s: valitsin ”%s” vaatii argumentin\n"
|
||||
msgstr "%s: valitsin vaatii argumentin -- ”%c”\\n"
|
||||
|
||||
#: elf/sotruss.sh:61
|
||||
msgid "%s: option is ambiguous; possibilities:"
|
||||
@@ -1507,7 +1503,6 @@ msgid "unknown iconv() error %d"
|
||||
msgstr "tuntematon iconv()-virhe %d"
|
||||
|
||||
#: iconv/iconv_prog.c:791
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"The following list contains all the coded character sets known. This does\n"
|
||||
"not necessarily mean that all combinations of these names can be used for\n"
|
||||
@@ -1516,9 +1511,9 @@ msgid ""
|
||||
"\n"
|
||||
" "
|
||||
msgstr ""
|
||||
"Seuraavassa listassa ovat kaikki tunnetut koodatut merkistöt. Se ei\n"
|
||||
"Seuraavassa listassa ovat kaikki tunnetut koodatut merkistöt. Tämä ei\n"
|
||||
"kuitenkaan välttämättä tarkoita sitä, että kaikkia näiden nimien\n"
|
||||
"yhdistelmiä voidaan käyttää FROM- ja TO-komentoriviparametreina. Yksi\n"
|
||||
"yhdistelmiä voisi käyttää FROM- ja TO-komentoriviparametreina. Yksi\n"
|
||||
"koodattu merkistö voi olla listalla useilla eri nimillä (aliaksilla).\n"
|
||||
"\n"
|
||||
" "
|
||||
@@ -2733,14 +2728,12 @@ msgid "locale.alias file to consult when making archive"
|
||||
msgstr "Arkistoa luotaessa käytettävä locale.alias-tiedosto"
|
||||
|
||||
#: locale/programs/localedef.c:150
|
||||
#, fuzzy
|
||||
msgid "Generate little-endian output"
|
||||
msgstr "Tuota little-endian-koodia"
|
||||
msgstr "Tuota little-endian-muotoa"
|
||||
|
||||
#: locale/programs/localedef.c:152
|
||||
#, fuzzy
|
||||
msgid "Generate big-endian output"
|
||||
msgstr "Tuota big-endian-koodia"
|
||||
msgstr "Tuota big-endian-muotoa"
|
||||
|
||||
#: locale/programs/localedef.c:157
|
||||
msgid "Compile locale specification"
|
||||
@@ -4275,10 +4268,9 @@ msgid ""
|
||||
msgstr ""
|
||||
|
||||
#: nscd/nscd.c:635
|
||||
#, fuzzy, c-format
|
||||
#| msgid "lstat failed"
|
||||
#, c-format
|
||||
msgid "'wait' failed\n"
|
||||
msgstr "tiedoston tilan luku epäonnistui"
|
||||
msgstr "”wait” epäonnistui\n"
|
||||
|
||||
#: nscd/nscd.c:642
|
||||
#, c-format
|
||||
@@ -4670,9 +4662,9 @@ msgid "cannot create temporary file"
|
||||
msgstr "tilapäistä tiedostoa ei voi luoda"
|
||||
|
||||
#: nss/makedb.c:304
|
||||
#, fuzzy, c-format
|
||||
#, c-format
|
||||
msgid "cannot stat newly created file"
|
||||
msgstr "tiedoston ”%s” tilaa ei voi lukea: %s"
|
||||
msgstr "juuri luodun tiedoston tilaa ei voi lukea"
|
||||
|
||||
#: nss/makedb.c:315
|
||||
#, c-format
|
||||
@@ -4680,9 +4672,9 @@ msgid "cannot rename temporary file"
|
||||
msgstr "tilapäistä tiedostoa ei voi nimetä uudelleen"
|
||||
|
||||
#: nss/makedb.c:531 nss/makedb.c:554
|
||||
#, fuzzy, c-format
|
||||
#, c-format
|
||||
msgid "cannot create search tree"
|
||||
msgstr "hakupolulle ei voi luoda välimuistia"
|
||||
msgstr "hakupuuta ei voi luoda"
|
||||
|
||||
#: nss/makedb.c:560
|
||||
msgid "duplicate key"
|
||||
@@ -4699,9 +4691,9 @@ msgid "failed to write new database file"
|
||||
msgstr "uuden tietokantatiedoston kirjoittaminen epäonnistui"
|
||||
|
||||
#: nss/makedb.c:812
|
||||
#, fuzzy, c-format
|
||||
#, c-format
|
||||
msgid "cannot stat database file"
|
||||
msgstr "tiedoston ”%s” tilaa ei voi lukea: %s"
|
||||
msgstr "tietokantatiedoston tilaa ei voi lukea"
|
||||
|
||||
#: nss/makedb.c:817
|
||||
#, fuzzy, c-format
|
||||
@@ -4709,9 +4701,9 @@ msgid "cannot map database file"
|
||||
msgstr "Karttatietokannassa ei ole enempää tietueita"
|
||||
|
||||
#: nss/makedb.c:820
|
||||
#, fuzzy, c-format
|
||||
#, c-format
|
||||
msgid "file not a database file"
|
||||
msgstr "luettaessa profilointidatatiedoston tilaa"
|
||||
msgstr "tiedosto ei ole tietokantatiedosto"
|
||||
|
||||
#: nss/makedb.c:871
|
||||
#, fuzzy, c-format
|
||||
@@ -4726,7 +4718,7 @@ msgstr "Käyttö: %s [-v määrittely] muuttujanimi [polku]\n"
|
||||
#: posix/getconf.c:403
|
||||
#, c-format
|
||||
msgid " %s -a [pathname]\n"
|
||||
msgstr ""
|
||||
msgstr " %s -a [polku]\n"
|
||||
|
||||
#: posix/getconf.c:479
|
||||
#, c-format
|
||||
@@ -5094,11 +5086,11 @@ msgstr "Laitetta irrotettu"
|
||||
|
||||
#: stdio-common/psiginfo.c:139
|
||||
msgid "Signal sent by kill()"
|
||||
msgstr ""
|
||||
msgstr "Signaalin lähetti kill()"
|
||||
|
||||
#: stdio-common/psiginfo.c:142
|
||||
msgid "Signal sent by sigqueue()"
|
||||
msgstr ""
|
||||
msgstr "Signaalin lähetti sigqueue()"
|
||||
|
||||
#: stdio-common/psiginfo.c:145
|
||||
msgid "Signal generated by the expiration of a timer"
|
||||
@@ -5114,7 +5106,7 @@ msgstr ""
|
||||
|
||||
#: stdio-common/psiginfo.c:157
|
||||
msgid "Signal sent by tkill()"
|
||||
msgstr ""
|
||||
msgstr "Signaalin lähetti tkill()"
|
||||
|
||||
#: stdio-common/psiginfo.c:162
|
||||
msgid "Signal generated by the completion of an asynchronous name lookup request"
|
||||
@@ -5296,9 +5288,8 @@ msgid "Failed (unspecified error)"
|
||||
msgstr "Epäonnistui (määrittelemätön virhe)"
|
||||
|
||||
#: sunrpc/clnt_raw.c:115
|
||||
#, fuzzy
|
||||
msgid "clnt_raw.c: fatal header serialization error"
|
||||
msgstr "clnt_raw.c: vakava otsikon serialisointivirhe"
|
||||
msgstr "clnt_raw.c: vakava otsikon sarjallistamisvirhe"
|
||||
|
||||
#: sunrpc/pm_getmaps.c:77
|
||||
msgid "pmap_getmaps.c: rpc problem"
|
||||
@@ -6825,9 +6816,8 @@ msgid "Interrupted by a signal"
|
||||
msgstr "Signaalin keskeyttämä"
|
||||
|
||||
#: sysdeps/posix/gai_strerror-strs.h:17
|
||||
#, fuzzy
|
||||
msgid "Parameter string not correctly encoded"
|
||||
msgstr "Parametrimerkkijono on väärin koodattu"
|
||||
msgstr "Parametrimerkkijono ei ole koodattu oikein"
|
||||
|
||||
#: sysdeps/unix/sysv/linux/i386/readelflib.c:65
|
||||
#, c-format
|
||||
|
||||
@@ -1,13 +1,17 @@
|
||||
# GNU libc message catalog for Swedish
|
||||
# Copyright © 1996, 1998, 2001, 2002, 2003, 2006, 2008, 2009, 2011, 2012, 2013, 2014, 2015 Free Software Foundation, Inc.
|
||||
# Copyright © 1996, 1998, 2001, 2002, 2003, 2006, 2008, 2009, 2011, 2012, 2013, 2014, 2015, 2016 Free Software Foundation, Inc.
|
||||
# This file is distributed under the same license as the glibc package.
|
||||
# Jan Djärv <jan.h.d@swipnet.se>, 1996, 1998, 2001, 2002, 2003, 2006, 2007, 2008, 2009, 2011, 2012, 2013, 2014, 2015
|
||||
#
|
||||
# Jan Djärv <jan.h.d@swipnet.se>, 1996, 1998, 2001, 2002, 2003, 2006, 2007, 2008, 2009, 2011, 2012, 2013, 2014, 2015.
|
||||
# Göran Uddeborg <goeran@uddeborg.se>, 2016.
|
||||
#
|
||||
# $Revision: 1.3 $
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: libc 2.21-pre1\n"
|
||||
"Project-Id-Version: libc 2.22-pre1\n"
|
||||
"POT-Creation-Date: 2015-07-31 00:10-0400\n"
|
||||
"PO-Revision-Date: 2015-01-24 10:35+0100\n"
|
||||
"Last-Translator: Jan Djärv <jan.h.d@swipnet.se>\n"
|
||||
"PO-Revision-Date: 2016-08-02 17:17+0200\n"
|
||||
"Last-Translator: Göran Uddeborg <goeran@uddeborg.se>\n"
|
||||
"Language-Team: Swedish <tp-sv@listor.tp-sv.se>\n"
|
||||
"Language: sv\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
@@ -48,7 +52,7 @@ msgstr " [FLAGGA...]"
|
||||
#: argp/argp-help.c:1643
|
||||
#, c-format
|
||||
msgid "Try `%s --help' or `%s --usage' for more information.\n"
|
||||
msgstr "Försök med \"%s --help\" eller \"%s --usage\" för mer information\n"
|
||||
msgstr "Försök med ”%s --help” eller ”%s --usage” för mer information.\n"
|
||||
|
||||
#: argp/argp-help.c:1671
|
||||
#, c-format
|
||||
@@ -304,11 +308,11 @@ msgstr "Användning: xtrace [FLAGGA]... PROGRAM [PROGRAMFLAGGA}...\\n"
|
||||
#: debug/xtrace.sh:32 elf/sotruss.sh:56 elf/sotruss.sh:67 elf/sotruss.sh:135
|
||||
#: malloc/memusage.sh:26
|
||||
msgid "Try \\`%s --help' or \\`%s --usage' for more information.\\n"
|
||||
msgstr "Försök med \\\"%s --help\\\" eller \\\"%s --usage\\\" för mer information\\n"
|
||||
msgstr "Försök med ”%s --help” eller ”%s --usage” för mer information\\n"
|
||||
|
||||
#: debug/xtrace.sh:38
|
||||
msgid "%s: option '%s' requires an argument.\\n"
|
||||
msgstr "%s: flaggan \\\"%s\\\" kräver ett argument\\n"
|
||||
msgstr "%s: flaggan ”%s” kräver ett argument.\\n"
|
||||
|
||||
#: debug/xtrace.sh:45
|
||||
msgid ""
|
||||
@@ -332,19 +336,17 @@ msgstr ""
|
||||
" --usage Visa en kort hjälptext\n"
|
||||
" -V,--version Visa versionsinformation och avsluta\n"
|
||||
"\n"
|
||||
"Obligatoriska argument för långa flaggor är obligatoriska även för\n"
|
||||
"Obligatoriska argument för långa flaggor är obligatoriska även för\n"
|
||||
"motsvarande korta.\n"
|
||||
|
||||
#: debug/xtrace.sh:57 elf/ldd.bash.in:55 elf/sotruss.sh:49
|
||||
#: malloc/memusage.sh:64
|
||||
msgid "For bug reporting instructions, please see:\\\\n%s.\\\\n"
|
||||
msgstr ""
|
||||
"För felrapporteringsinstruktioner, se:\\\\n%s.\\\\n\n"
|
||||
"Rapportera fel eller synpunkter på översättningen till <tp-sv@listor.tp-sv.se>.\\\\n"
|
||||
msgstr "För felrapporteringsinstruktioner, se:\\\\n%s.\\\\nRapportera fel eller synpunkter på översättningen till:\\\\n<tp-sv@listor.tp-sv.se>.\\\\n"
|
||||
|
||||
#: debug/xtrace.sh:125
|
||||
msgid "xtrace: unrecognized option \\`$1'\\n"
|
||||
msgstr "xtrace: okänd flagga \"$1\"\\n"
|
||||
msgstr "xtrace: okänd flagga ”$1”\\n"
|
||||
|
||||
#: debug/xtrace.sh:138
|
||||
msgid "No program name given\\n"
|
||||
@@ -353,12 +355,12 @@ msgstr "Inget programnamn givet\\n"
|
||||
#: debug/xtrace.sh:146
|
||||
#, sh-format
|
||||
msgid "executable \\`$program' not found\\n"
|
||||
msgstr "program \"$program\" hittades inte\\n"
|
||||
msgstr "program ”$program” hittades inte\\n"
|
||||
|
||||
#: debug/xtrace.sh:150
|
||||
#, sh-format
|
||||
msgid "\\`$program' is no executable\\n"
|
||||
msgstr "\"$program\" är inte en körbar binär\\n"
|
||||
msgstr "”$program” är inte en körbar binär\\n"
|
||||
|
||||
#: dlfcn/dlinfo.c:63
|
||||
msgid "RTLD_SELF used in code not dynamically loaded"
|
||||
@@ -396,7 +398,7 @@ msgstr ", OS ABI: %s %d.%d.%d"
|
||||
#: elf/cache.c:157 elf/ldconfig.c:1340
|
||||
#, c-format
|
||||
msgid "Can't open cache file %s\n"
|
||||
msgstr "Kan inte öppna cache-fil \"%s\"\n"
|
||||
msgstr "Kan inte öppna cache-filen %s\n"
|
||||
|
||||
#: elf/cache.c:171
|
||||
#, c-format
|
||||
@@ -416,7 +418,7 @@ msgstr "%d bibliotek hittades i cache \"%s\"\n"
|
||||
#: elf/cache.c:426
|
||||
#, c-format
|
||||
msgid "Can't create temporary cache file %s"
|
||||
msgstr "Kan inte skapa temporär cache-fil \"%s\""
|
||||
msgstr "Kan inte skapa en temporär cache-fil %s"
|
||||
|
||||
#: elf/cache.c:434 elf/cache.c:444 elf/cache.c:448 elf/cache.c:453
|
||||
#, c-format
|
||||
@@ -829,7 +831,7 @@ msgstr "Kan inte ta status (lstat) på %s"
|
||||
#: elf/ldconfig.c:609
|
||||
#, c-format
|
||||
msgid "Ignored file %s since it is not a regular file."
|
||||
msgstr "Ignorerar fil %s eftersom den inte är en vanlig fil"
|
||||
msgstr "Ignorerar fil %s eftersom den inte är en vanlig fil."
|
||||
|
||||
#: elf/ldconfig.c:618
|
||||
#, c-format
|
||||
@@ -951,7 +953,7 @@ msgstr ""
|
||||
|
||||
#: elf/ldd.bash.in:80
|
||||
msgid "ldd: option \\`$1' is ambiguous"
|
||||
msgstr "ldd: flaggan \"$1\" är tvetydig"
|
||||
msgstr "ldd: flaggan ”$1” är tvetydig"
|
||||
|
||||
#: elf/ldd.bash.in:87
|
||||
msgid "unrecognized option"
|
||||
@@ -959,7 +961,7 @@ msgstr "okänd flagga"
|
||||
|
||||
#: elf/ldd.bash.in:88 elf/ldd.bash.in:125
|
||||
msgid "Try \\`ldd --help' for more information."
|
||||
msgstr "Försök med \"ldd --help\" för mer information"
|
||||
msgstr "Försök med \"ldd --help\" för mer information."
|
||||
|
||||
#: elf/ldd.bash.in:124
|
||||
msgid "missing file arguments"
|
||||
@@ -1028,10 +1030,9 @@ msgid "cannot read object name"
|
||||
msgstr "kan inte läsa objektnamn"
|
||||
|
||||
#: elf/pldd-xx.c:219
|
||||
#, fuzzy, c-format
|
||||
#| msgid "cannot allocate memory for program header"
|
||||
#, c-format
|
||||
msgid "cannot allocate buffer for object name"
|
||||
msgstr "kan inte allokera minne för programhuvud"
|
||||
msgstr "kan inte allokera en buffert för objektnamn"
|
||||
|
||||
#: elf/pldd.c:64
|
||||
msgid "List dynamic shared objects loaded into process."
|
||||
@@ -1212,11 +1213,11 @@ msgstr ""
|
||||
|
||||
#: elf/sotruss.sh:46
|
||||
msgid "Mandatory arguments to long options are also mandatory for any corresponding\\nshort options.\\n"
|
||||
msgstr "Obligatoriska respektive valfria argument för långa flaggor är obligatoriska respektive\\nvalfria även för korta.\\n"
|
||||
msgstr "Obligatoriska respektive valfria argument för långa flaggor är obligatoriska\\nrespektive valfria även för korta.\\n"
|
||||
|
||||
#: elf/sotruss.sh:55
|
||||
msgid "%s: option requires an argument -- '%s'\\n"
|
||||
msgstr "%s: flaggan kräver ett argument -- \\\"%s\\\"\\n"
|
||||
msgstr "%s: flaggan kräver ett argument — ”%s”\\n"
|
||||
|
||||
#: elf/sotruss.sh:61
|
||||
msgid "%s: option is ambiguous; possibilities:"
|
||||
@@ -1240,7 +1241,7 @@ msgstr ""
|
||||
|
||||
#: elf/sotruss.sh:134
|
||||
msgid "%s: unrecognized option '%c%s'\\n"
|
||||
msgstr "%s: okänd flagga \\\"%c%s\\\"\\n"
|
||||
msgstr "%s: okänd flagga ”%c%s”\\n"
|
||||
|
||||
#: elf/sprof.c:77
|
||||
msgid "Output selection:"
|
||||
@@ -1260,7 +1261,7 @@ msgstr "generera anropsgraf"
|
||||
|
||||
#: elf/sprof.c:89
|
||||
msgid "Read and display shared object profiling data."
|
||||
msgstr "Läs och visa profildata för delat objekt"
|
||||
msgstr "Läs och visa profildata för delat objekt."
|
||||
|
||||
#: elf/sprof.c:94
|
||||
msgid "SHOBJ [PROFDATA]"
|
||||
@@ -1622,7 +1623,7 @@ msgstr "Fel: .netrc kan läsas av andra."
|
||||
|
||||
#: inet/ruserpass.c:185
|
||||
msgid "Remove password or make file unreadable by others."
|
||||
msgstr "Ta bort lösenord eller gör filen oläsbar för andra"
|
||||
msgstr "Ta bort lösenord eller gör filen oläsbar för andra."
|
||||
|
||||
#: inet/ruserpass.c:277
|
||||
#, c-format
|
||||
@@ -2182,12 +2183,12 @@ msgstr "Inget namn definierat i teckenuppsättning"
|
||||
#: locale/programs/ld-ctype.c:479
|
||||
#, c-format
|
||||
msgid "character L'\\u%0*x' in class `%s' must be in class `%s'"
|
||||
msgstr "tecken L\"\\u%0*x\" i klass \"%s\" måste vara i klass \"%s\""
|
||||
msgstr "tecken L'\\u%0*x' i klassen ”%s” måste vara i klassen ”%s”"
|
||||
|
||||
#: locale/programs/ld-ctype.c:494
|
||||
#, c-format
|
||||
msgid "character L'\\u%0*x' in class `%s' must not be in class `%s'"
|
||||
msgstr "tecken L\"\\u%0*x\" i klass \"%s\" får inte vara i klass \"%s\""
|
||||
msgstr "tecken L'\\u%0*x' i klassen ”%s” får inte vara i klassen ”%s”"
|
||||
|
||||
#: locale/programs/ld-ctype.c:508 locale/programs/ld-ctype.c:566
|
||||
#, c-format
|
||||
@@ -2611,7 +2612,7 @@ msgstr "Skriv mer information"
|
||||
|
||||
#: locale/programs/locale.c:85
|
||||
msgid "Get locale-specific information."
|
||||
msgstr "Hämta lokalspecifik information"
|
||||
msgstr "Hämta lokalspecifik information."
|
||||
|
||||
#: locale/programs/locale.c:88
|
||||
msgid ""
|
||||
@@ -3022,7 +3023,7 @@ msgstr "felaktig mcheck_status, biblioteket är felaktigt\n"
|
||||
|
||||
#: malloc/memusage.sh:32
|
||||
msgid "%s: option '%s' requires an argument\\n"
|
||||
msgstr "%s: flaggan \\\"%s\\\" kräver ett argument\\n"
|
||||
msgstr "%s: flaggan ”%s” kräver ett argument\\n"
|
||||
|
||||
#: malloc/memusage.sh:38
|
||||
msgid ""
|
||||
@@ -3091,11 +3092,11 @@ msgstr ""
|
||||
|
||||
#: malloc/memusage.sh:191
|
||||
msgid "memusage: option \\`${1##*=}' is ambiguous"
|
||||
msgstr "memusage: flaggan \"${1##*=}\" är tvetydig"
|
||||
msgstr "memusage: flaggan ”${1##*=}” är tvetydig"
|
||||
|
||||
#: malloc/memusage.sh:200
|
||||
msgid "memusage: unrecognized option \\`$1'"
|
||||
msgstr "memusage: okänd flagga \"$1\""
|
||||
msgstr "memusage: okänd flagga ”$1”"
|
||||
|
||||
#: malloc/memusage.sh:213
|
||||
msgid "No program name given"
|
||||
@@ -3341,7 +3342,7 @@ msgstr "Kan inte skapa process hos server"
|
||||
|
||||
#: nis/nis_error.h:48
|
||||
msgid "Master server busy, full dump rescheduled."
|
||||
msgstr "Huvudserver är upptagen, full dump åter schemalagd"
|
||||
msgstr "Huvudserver är upptagen, full dump åter schemalagd."
|
||||
|
||||
#: nis/nis_local_names.c:121
|
||||
#, c-format
|
||||
@@ -3511,7 +3512,7 @@ msgstr "\t\tRättigheter : "
|
||||
|
||||
#: nis/nis_print.c:290
|
||||
msgid "Linked Object Type : "
|
||||
msgstr "Länkad objekttyp: "
|
||||
msgstr "Länkad objekttyp : "
|
||||
|
||||
#: nis/nis_print.c:292
|
||||
#, c-format
|
||||
@@ -3802,15 +3803,14 @@ msgid " (first)"
|
||||
msgstr " (första)"
|
||||
|
||||
#: nscd/cache.c:288
|
||||
#, fuzzy, c-format
|
||||
#| msgid "cannot stat() file `%s': %s"
|
||||
#, c-format
|
||||
msgid "checking for monitored file `%s': %s"
|
||||
msgstr "kan inte ta status på fil \"%s\": %s"
|
||||
msgstr "kontrollerar den övervakade filen ”%s”: %s"
|
||||
|
||||
#: nscd/cache.c:298
|
||||
#, c-format
|
||||
msgid "monitored file `%s` changed (mtime)"
|
||||
msgstr ""
|
||||
msgstr "den övervakade filen ”%s” ändrades (mtime)"
|
||||
|
||||
#: nscd/cache.c:341
|
||||
#, c-format
|
||||
@@ -3906,34 +3906,32 @@ msgstr "kan inte få uttag (socket) att acceptera förbindelser: %s"
|
||||
#: nscd/connections.c:973
|
||||
#, c-format
|
||||
msgid "disabled inotify-based monitoring for file `%s': %s"
|
||||
msgstr ""
|
||||
msgstr "avaktiverade inotify-baserad övervakning för filen ”%s”: %s"
|
||||
|
||||
#: nscd/connections.c:977
|
||||
#, c-format
|
||||
msgid "monitoring file `%s` (%d)"
|
||||
msgstr ""
|
||||
msgstr "övervakar filen ”%s” (%d)"
|
||||
|
||||
#: nscd/connections.c:990
|
||||
#, c-format
|
||||
msgid "disabled inotify-based monitoring for directory `%s': %s"
|
||||
msgstr ""
|
||||
msgstr "avaktiverade inotify-baserad övervakning av katalogen ”%s”: %s"
|
||||
|
||||
#: nscd/connections.c:994
|
||||
#, fuzzy, c-format
|
||||
#| msgid "Can't open directory %s"
|
||||
#, c-format
|
||||
msgid "monitoring directory `%s` (%d)"
|
||||
msgstr "Kan inte öppna katalog %s"
|
||||
msgstr "övervakar katalogen ”%s” (%d)"
|
||||
|
||||
#: nscd/connections.c:1022
|
||||
#, fuzzy, c-format
|
||||
#| msgid "register trace file %s for database %s"
|
||||
#, c-format
|
||||
msgid "monitoring file %s for database %s"
|
||||
msgstr "registrera spårningsfil %s för databas %s"
|
||||
msgstr "övervakar filen %s för databas %s"
|
||||
|
||||
#: nscd/connections.c:1032
|
||||
#, c-format
|
||||
msgid "stat failed for file `%s'; will try again later: %s"
|
||||
msgstr ""
|
||||
msgstr "stat misslyckades för filen ”%s”; kommer försöka igen senare: %s"
|
||||
|
||||
#: nscd/connections.c:1151
|
||||
#, c-format
|
||||
@@ -4032,44 +4030,42 @@ msgstr "handle_request: begäran mottagen (Version = %d)"
|
||||
#: nscd/connections.c:1963
|
||||
#, c-format
|
||||
msgid "ignored inotify event for `%s` (file exists)"
|
||||
msgstr ""
|
||||
msgstr "ignorerade inotify-händelse för ”%s” (filen finns)"
|
||||
|
||||
#: nscd/connections.c:1968
|
||||
#, c-format
|
||||
msgid "monitored file `%s` was %s, removing watch"
|
||||
msgstr ""
|
||||
msgstr "den övervakade filen ”%s” var %s, tar bort vakten"
|
||||
|
||||
#: nscd/connections.c:1976 nscd/connections.c:2018
|
||||
#, c-format
|
||||
msgid "failed to remove file watch `%s`: %s"
|
||||
msgstr ""
|
||||
msgstr "misslyckades att ta bort filvakt ”%s”: %s"
|
||||
|
||||
#: nscd/connections.c:1991
|
||||
#, c-format
|
||||
msgid "monitored file `%s` was written to"
|
||||
msgstr ""
|
||||
msgstr "den övervakade filen ”%s” skrevs till"
|
||||
|
||||
#: nscd/connections.c:2015
|
||||
#, c-format
|
||||
msgid "monitored parent directory `%s` was %s, removing watch on `%s`"
|
||||
msgstr ""
|
||||
msgstr "den övervakade föräldrakatalogen ”%s” var %s, tar bort vakten av ”%s”"
|
||||
|
||||
#: nscd/connections.c:2041
|
||||
#, c-format
|
||||
msgid "monitored file `%s` was %s, adding watch"
|
||||
msgstr ""
|
||||
msgstr "den övervakade filen ”%s” var %s, lägger till vakt"
|
||||
|
||||
#: nscd/connections.c:2053
|
||||
#, fuzzy, c-format
|
||||
#| msgid "failed to load shared object `%s'"
|
||||
#, c-format
|
||||
msgid "failed to add file watch `%s`: %s"
|
||||
msgstr "misslyckades med att ladda delat objekt \"%s\""
|
||||
msgstr "misslyckades med att lägga till filvakt ”%s”: %s"
|
||||
|
||||
#: nscd/connections.c:2247 nscd/connections.c:2428
|
||||
#, fuzzy, c-format
|
||||
#| msgid "disabled inotify after read error %d"
|
||||
#, c-format
|
||||
msgid "disabled inotify-based monitoring after read error %d"
|
||||
msgstr "inaktiverade inotify efter läsfel %d"
|
||||
msgstr "avaktiverade inotify-baserad övervakning efter läsfel %d"
|
||||
|
||||
#: nscd/connections.c:2543
|
||||
msgid "could not initialize conditional variable"
|
||||
@@ -4199,7 +4195,7 @@ msgstr "Använd separat cache för varje användare"
|
||||
|
||||
#: nscd/nscd.c:122
|
||||
msgid "Name Service Cache Daemon."
|
||||
msgstr "Namntjänst cache-demon"
|
||||
msgstr "Cache-demon för namntjänsten."
|
||||
|
||||
#: nscd/nscd.c:155 nss/getent.c:1007 nss/makedb.c:206
|
||||
#, c-format
|
||||
@@ -4531,11 +4527,11 @@ msgstr "Access Vector Cache (AVC) startad"
|
||||
|
||||
#: nscd/selinux.c:368
|
||||
msgid "Error querying policy for undefined object classes or permissions."
|
||||
msgstr "Fel när policy för odefinierade objektklasser eller rättigheter hämtades"
|
||||
msgstr "Fel när policy för odefinierade objektklasser eller rättigheter hämtades."
|
||||
|
||||
#: nscd/selinux.c:375
|
||||
msgid "Error getting security class for nscd."
|
||||
msgstr "Fel när säkerhetsklass för nscd hämtades"
|
||||
msgstr "Fel när säkerhetsklass för nscd hämtades."
|
||||
|
||||
#: nscd/selinux.c:380
|
||||
#, c-format
|
||||
@@ -4609,7 +4605,7 @@ msgstr "inaktivera DIN-kodning"
|
||||
|
||||
#: nss/getent.c:64
|
||||
msgid "Get entries from administrative database."
|
||||
msgstr "Hämta poster från den administrativa databasen"
|
||||
msgstr "Hämta poster från den administrativa databasen."
|
||||
|
||||
#: nss/getent.c:148 nss/getent.c:477 nss/getent.c:522
|
||||
#, c-format
|
||||
@@ -4652,7 +4648,7 @@ msgstr "Genererad rad som inte ingår i iterationen"
|
||||
|
||||
#: nss/makedb.c:131
|
||||
msgid "Create simple database from textual input."
|
||||
msgstr "Skapa en enkel databas från textuell indata"
|
||||
msgstr "Skapa en enkel databas från textuell indata."
|
||||
|
||||
#: nss/makedb.c:134
|
||||
msgid ""
|
||||
@@ -5412,7 +5408,7 @@ msgstr "Kan inte ange netid-flaggan utan TIRPC!\n"
|
||||
#: sunrpc/rpc_main.c:1374
|
||||
#, c-format
|
||||
msgid "Cannot use table flags with newstyle!\n"
|
||||
msgstr "Kan inte ange tabellflaggor med ny stil\n"
|
||||
msgstr "Kan inte ange tabellflaggor med ny stil!\n"
|
||||
|
||||
#: sunrpc/rpc_main.c:1393
|
||||
#, c-format
|
||||
@@ -7270,18 +7266,9 @@ msgstr "tidszonsförkortning skiljer sig från POSIX-standarden"
|
||||
|
||||
#: timezone/zic.c:2789
|
||||
msgid "too many, or too long, time zone abbreviations"
|
||||
msgstr "för många eller för långa tidszonförkortningar"
|
||||
msgstr "för många eller för långa tidszonsförkortningar"
|
||||
|
||||
#: timezone/zic.c:2829
|
||||
#, c-format
|
||||
msgid "%s: Can't create directory %s: %s\n"
|
||||
msgstr "%s: Kan inte skapa katalog %s: %s\n"
|
||||
|
||||
#~ msgid "cannot load any more object with static TLS"
|
||||
#~ msgstr "kan inte ladda fler objekt med statiskt TLS"
|
||||
|
||||
#~ msgid "%s: no PLTREL found in object %s\n"
|
||||
#~ msgstr "%s: hittade inga PLTREL i objekt %s\n"
|
||||
|
||||
#~ msgid "cannot create internal descriptors"
|
||||
#~ msgstr "kan inte skapa interna deskriptorer"
|
||||
|
||||
+10
-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 \
|
||||
@@ -90,7 +90,7 @@ tests := tstgetopt testfnm runtests runptests \
|
||||
bug-getopt5 tst-getopt_long1 bug-regex34 bug-regex35 \
|
||||
tst-pathconf tst-getaddrinfo4 tst-rxspencer-no-utf8 \
|
||||
tst-fnmatch3 bug-regex36 tst-getaddrinfo5 \
|
||||
tst-posix_spawn-fd
|
||||
tst-posix_spawn-fd tst-glob-tilde
|
||||
xtests := bug-ga2
|
||||
ifeq (yes,$(build-shared))
|
||||
test-srcs := globtest
|
||||
@@ -133,7 +133,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
|
||||
|
||||
@@ -340,6 +341,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 ,\
|
||||
|
||||
+10
-5
@@ -48,12 +48,13 @@ maybe_script_execute (const char *file, char *const argv[], char *const envp[])
|
||||
}
|
||||
}
|
||||
|
||||
/* Construct an argument list for the shell. */
|
||||
/* Construct an argument list for the shell. It will contain at minimum 3
|
||||
arguments (current shell, script, and an ending NULL. */
|
||||
char *new_argv[argc + 1];
|
||||
new_argv[0] = (char *) _PATH_BSHELL;
|
||||
new_argv[1] = (char *) file;
|
||||
if (argc > 1)
|
||||
memcpy (new_argv + 2, argv + 1, argc * sizeof(char *));
|
||||
memcpy (new_argv + 2, argv + 1, (argc - 1) * sizeof(char *));
|
||||
else
|
||||
new_argv[2] = NULL;
|
||||
|
||||
@@ -91,10 +92,11 @@ __execvpe (const char *file, char *const argv[], char *const envp[])
|
||||
/* Although GLIBC does not enforce NAME_MAX, we set it as the maximum
|
||||
size to avoid unbounded stack allocation. Same applies for
|
||||
PATH_MAX. */
|
||||
size_t file_len = __strnlen (file, NAME_MAX + 1);
|
||||
size_t file_len = __strnlen (file, NAME_MAX) + 1;
|
||||
size_t path_len = __strnlen (path, PATH_MAX - 1) + 1;
|
||||
|
||||
if ((file_len > NAME_MAX)
|
||||
/* NAME_MAX does not include the terminating null character. */
|
||||
if (((file_len-1) > NAME_MAX)
|
||||
|| !__libc_alloca_cutoff (path_len + file_len + 1))
|
||||
{
|
||||
errno = ENAMETOOLONG;
|
||||
@@ -103,6 +105,9 @@ __execvpe (const char *file, char *const argv[], char *const envp[])
|
||||
|
||||
const char *subp;
|
||||
bool got_eacces = false;
|
||||
/* The resulting string maximum size would be potentially a entry
|
||||
in PATH plus '/' (path_len + 1) and then the the resulting file name
|
||||
plus '\0' (file_len since it already accounts for the '\0'). */
|
||||
char buffer[path_len + file_len + 1];
|
||||
for (const char *p = path; ; p = subp)
|
||||
{
|
||||
@@ -123,7 +128,7 @@ __execvpe (const char *file, char *const argv[], char *const envp[])
|
||||
execute. */
|
||||
char *pend = mempcpy (buffer, p, subp - p);
|
||||
*pend = '/';
|
||||
memcpy (pend + (p < subp), file, file_len + 1);
|
||||
memcpy (pend + (p < subp), file, file_len);
|
||||
|
||||
__execve (buffer, argv, envp);
|
||||
|
||||
|
||||
@@ -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))
|
||||
+373
-407
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
|
||||
@@ -1,6 +1,6 @@
|
||||
/* Copyright (C) 1997-2016 Free Software Foundation, Inc.
|
||||
/* 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.
|
||||
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
@@ -16,8 +16,16 @@
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
/* SH4 ABI does not really require argument alignment for 64-bits, but
|
||||
the kernel interface for pread adds a dummy long argument before the
|
||||
offset. */
|
||||
#define __ALIGNMENT_ARG
|
||||
#include <sysdeps/unix/sysv/linux/pread.c>
|
||||
#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,143 @@
|
||||
/* Check for GLOB_TIDLE heap allocation issues (bugs 22320, 22325, 22332).
|
||||
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;
|
||||
|
||||
/* Flag which indicates whether to pass the GLOB_NOESCAPE flag. */
|
||||
static int do_noescape;
|
||||
|
||||
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;
|
||||
if (do_noescape)
|
||||
flags |= GLOB_NOESCAPE;
|
||||
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 (do_noescape = 0; do_noescape < 2; ++do_noescape)
|
||||
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");
|
||||
one_test ("~", user_name, "x\\x\\x////x\\a");
|
||||
}
|
||||
|
||||
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>
|
||||
@@ -40,6 +40,9 @@ ifeq ($(have-thread-library),yes)
|
||||
extra-libs += libanl
|
||||
routines += gai_sigqueue
|
||||
tests += tst-res_hconf_reorder
|
||||
|
||||
# This test sends millions of packets and is rather slow.
|
||||
xtests += tst-resolv-qtypes
|
||||
endif
|
||||
extra-libs-others = $(extra-libs)
|
||||
libresolv-routines := gethnamaddr res_comp res_debug \
|
||||
@@ -117,3 +120,5 @@ tst-leaks2-ENV = MALLOC_TRACE=$(objpfx)tst-leaks2.mtrace
|
||||
$(objpfx)mtrace-tst-leaks2.out: $(objpfx)tst-leaks2.out
|
||||
$(common-objpfx)malloc/mtrace $(objpfx)tst-leaks2.mtrace > $@; \
|
||||
$(evaluate-test)
|
||||
|
||||
$(objpfx)tst-resolv-qtypes: $(objpfx)libresolv.so $(shared-thread-library)
|
||||
|
||||
@@ -323,7 +323,7 @@ _nss_dns_gethostbyname4_r (const char *name, struct gaih_addrtuple **pat,
|
||||
|
||||
int olderr = errno;
|
||||
enum nss_status status;
|
||||
int n = __libc_res_nsearch (&_res, name, C_IN, T_UNSPEC,
|
||||
int n = __libc_res_nsearch (&_res, name, C_IN, T_QUERY_A_AND_AAAA,
|
||||
host_buffer.buf->buf, 2048, &host_buffer.ptr,
|
||||
&ans2p, &nans2p, &resplen2, &ans2p_malloced);
|
||||
if (n >= 0)
|
||||
|
||||
@@ -103,6 +103,10 @@ res_nmkquery(res_state statp,
|
||||
int n;
|
||||
u_char *dnptrs[20], **dpp, **lastdnptr;
|
||||
|
||||
if (class < 0 || class > 65535
|
||||
|| type < 0 || type > 65535)
|
||||
return -1;
|
||||
|
||||
#ifdef DEBUG
|
||||
if (statp->options & RES_DEBUG)
|
||||
printf(";; res_nmkquery(%s, %s, %s, %s)\n",
|
||||
|
||||
+3
-3
@@ -122,7 +122,7 @@ __libc_res_nquery(res_state statp,
|
||||
int n, use_malloc = 0;
|
||||
u_int oflags = statp->_flags;
|
||||
|
||||
size_t bufsize = (type == T_UNSPEC ? 2 : 1) * QUERYSIZE;
|
||||
size_t bufsize = (type == T_QUERY_A_AND_AAAA ? 2 : 1) * QUERYSIZE;
|
||||
u_char *buf = alloca (bufsize);
|
||||
u_char *query1 = buf;
|
||||
int nquery1 = -1;
|
||||
@@ -137,7 +137,7 @@ __libc_res_nquery(res_state statp,
|
||||
printf(";; res_query(%s, %d, %d)\n", name, class, type);
|
||||
#endif
|
||||
|
||||
if (type == T_UNSPEC)
|
||||
if (type == T_QUERY_A_AND_AAAA)
|
||||
{
|
||||
n = res_nmkquery(statp, QUERY, name, class, T_A, NULL, 0, NULL,
|
||||
query1, bufsize);
|
||||
@@ -190,7 +190,7 @@ __libc_res_nquery(res_state statp,
|
||||
if (__builtin_expect (n <= 0, 0) && !use_malloc) {
|
||||
/* Retry just in case res_nmkquery failed because of too
|
||||
short buffer. Shouldn't happen. */
|
||||
bufsize = (type == T_UNSPEC ? 2 : 1) * MAXPACKET;
|
||||
bufsize = (type == T_QUERY_A_AND_AAAA ? 2 : 1) * MAXPACKET;
|
||||
buf = malloc (bufsize);
|
||||
if (buf != NULL) {
|
||||
query1 = buf;
|
||||
|
||||
@@ -0,0 +1,185 @@
|
||||
/* Exercise low-level query functions with different QTYPEs.
|
||||
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 <resolv.h>
|
||||
#include <string.h>
|
||||
#include <support/check.h>
|
||||
#include <support/check_nss.h>
|
||||
#include <support/resolv_test.h>
|
||||
#include <support/support.h>
|
||||
#include <support/test-driver.h>
|
||||
#include <support/xmemstream.h>
|
||||
|
||||
/* If ture, the response function will send the actual response packet
|
||||
over TCP instead of UDP. */
|
||||
static volatile bool force_tcp;
|
||||
|
||||
/* Send back a fake resource record matching the QTYPE. */
|
||||
static void
|
||||
response (const struct resolv_response_context *ctx,
|
||||
struct resolv_response_builder *b,
|
||||
const char *qname, uint16_t qclass, uint16_t qtype)
|
||||
{
|
||||
if (force_tcp && ctx->tcp)
|
||||
{
|
||||
resolv_response_init (b, (struct resolv_response_flags) { .tc = 1 });
|
||||
resolv_response_add_question (b, qname, qclass, qtype);
|
||||
return;
|
||||
}
|
||||
|
||||
resolv_response_init (b, (struct resolv_response_flags) { });
|
||||
resolv_response_add_question (b, qname, qclass, qtype);
|
||||
resolv_response_section (b, ns_s_an);
|
||||
resolv_response_open_record (b, qname, qclass, qtype, 0);
|
||||
resolv_response_add_data (b, &qtype, sizeof (qtype));
|
||||
resolv_response_close_record (b);
|
||||
}
|
||||
|
||||
static const const char *domain = "www.example.com";
|
||||
|
||||
static int
|
||||
wrap_res_query (int type, unsigned char *answer, int answer_length)
|
||||
{
|
||||
return res_query (domain, C_IN, type, answer, answer_length);
|
||||
}
|
||||
|
||||
static int
|
||||
wrap_res_search (int type, unsigned char *answer, int answer_length)
|
||||
{
|
||||
return res_query (domain, C_IN, type, answer, answer_length);
|
||||
}
|
||||
|
||||
static int
|
||||
wrap_res_querydomain (int type, unsigned char *answer, int answer_length)
|
||||
{
|
||||
return res_querydomain ("www", "example.com", C_IN, type,
|
||||
answer, answer_length);
|
||||
}
|
||||
|
||||
static int
|
||||
wrap_res_send (int type, unsigned char *answer, int answer_length)
|
||||
{
|
||||
unsigned char buf[512];
|
||||
int ret = res_mkquery (QUERY, domain, C_IN, type,
|
||||
(const unsigned char *) "", 0, NULL,
|
||||
buf, sizeof (buf));
|
||||
if (type < 0 || type >= 65536)
|
||||
{
|
||||
/* res_mkquery fails for out-of-range record types. */
|
||||
TEST_VERIFY_EXIT (ret == -1);
|
||||
return -1;
|
||||
}
|
||||
TEST_VERIFY_EXIT (ret > 12); /* DNS header length. */
|
||||
return res_send (buf, ret, answer, answer_length);
|
||||
}
|
||||
|
||||
static int
|
||||
wrap_res_nquery (int type, unsigned char *answer, int answer_length)
|
||||
{
|
||||
return res_nquery (&_res, domain, C_IN, type, answer, answer_length);
|
||||
}
|
||||
|
||||
static int
|
||||
wrap_res_nsearch (int type, unsigned char *answer, int answer_length)
|
||||
{
|
||||
return res_nquery (&_res, domain, C_IN, type, answer, answer_length);
|
||||
}
|
||||
|
||||
static int
|
||||
wrap_res_nquerydomain (int type, unsigned char *answer, int answer_length)
|
||||
{
|
||||
return res_nquerydomain (&_res, "www", "example.com", C_IN, type,
|
||||
answer, answer_length);
|
||||
}
|
||||
|
||||
static int
|
||||
wrap_res_nsend (int type, unsigned char *answer, int answer_length)
|
||||
{
|
||||
unsigned char buf[512];
|
||||
int ret = res_nmkquery (&_res, QUERY, domain, C_IN, type,
|
||||
(const unsigned char *) "", 0, NULL,
|
||||
buf, sizeof (buf));
|
||||
if (type < 0 || type >= 65536)
|
||||
{
|
||||
/* res_mkquery fails for out-of-range record types. */
|
||||
TEST_VERIFY_EXIT (ret == -1);
|
||||
return -1;
|
||||
}
|
||||
TEST_VERIFY_EXIT (ret > 12); /* DNS header length. */
|
||||
return res_nsend (&_res, buf, ret, answer, answer_length);
|
||||
}
|
||||
|
||||
static void
|
||||
test_function (const char *fname,
|
||||
int (*func) (int type,
|
||||
unsigned char *answer, int answer_length))
|
||||
{
|
||||
unsigned char buf[512];
|
||||
for (int tcp = 0; tcp < 2; ++tcp)
|
||||
{
|
||||
force_tcp = tcp;
|
||||
for (unsigned int type = 1; type <= 65535; ++type)
|
||||
{
|
||||
if (test_verbose)
|
||||
printf ("info: sending QTYPE %d with %s (tcp=%d)\n",
|
||||
type, fname, tcp);
|
||||
int ret = func (type, buf, sizeof (buf));
|
||||
if (ret != 47)
|
||||
FAIL_EXIT1 ("%s tcp=%d qtype=%d return value %d",
|
||||
fname,tcp, type, ret);
|
||||
/* One question, one answer record. */
|
||||
TEST_VERIFY (memcmp (buf + 4, "\0\1\0\1\0\0\0\0", 8) == 0);
|
||||
/* Question section. */
|
||||
static const char qname[] = "\3www\7example\3com";
|
||||
size_t qname_length = sizeof (qname);
|
||||
TEST_VERIFY (memcmp (buf + 12, qname, qname_length) == 0);
|
||||
/* RDATA part of answer. */
|
||||
uint16_t type16 = type;
|
||||
TEST_VERIFY (memcmp (buf + ret - 2, &type16, sizeof (type16)) == 0);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_VERIFY (func (-1, buf, sizeof (buf) == -1));
|
||||
TEST_VERIFY (func (65536, buf, sizeof (buf) == -1));
|
||||
}
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
struct resolv_redirect_config config =
|
||||
{
|
||||
.response_callback = response,
|
||||
};
|
||||
struct resolv_test *obj = resolv_test_start (config);
|
||||
|
||||
test_function ("res_query", &wrap_res_query);
|
||||
test_function ("res_search", &wrap_res_search);
|
||||
test_function ("res_querydomain", &wrap_res_querydomain);
|
||||
test_function ("res_send", &wrap_res_send);
|
||||
|
||||
test_function ("res_nquery", &wrap_res_nquery);
|
||||
test_function ("res_nsearch", &wrap_res_nsearch);
|
||||
test_function ("res_nquerydomain", &wrap_res_nquerydomain);
|
||||
test_function ("res_nsend", &wrap_res_nsend);
|
||||
|
||||
resolv_test_end (obj);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define TIMEOUT 300
|
||||
#include <support/test-driver.c>
|
||||
@@ -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
|
||||
+1
-1
@@ -77,7 +77,7 @@ tests := tst-strtol tst-strtod testmb testrand testsort testdiv \
|
||||
tst-tininess tst-strtod-underflow tst-tls-atexit \
|
||||
tst-setcontext3 tst-tls-atexit-nodelete \
|
||||
tst-strtol-locale tst-strtod-nan-locale tst-strfmon_l \
|
||||
tst-quick_exit tst-thread-quick_exit
|
||||
tst-quick_exit tst-thread-quick_exit test-bz22786
|
||||
tests-static := tst-secure-getenv
|
||||
ifeq ($(have-cxx-thread_local),yes)
|
||||
CFLAGS-tst-quick_exit.o = -std=c++11
|
||||
|
||||
@@ -181,7 +181,7 @@ __realpath (const char *name, char *resolved)
|
||||
extra_buf = __alloca (path_max);
|
||||
|
||||
len = strlen (end);
|
||||
if ((long int) (n + len) >= path_max)
|
||||
if (path_max - n <= len)
|
||||
{
|
||||
__set_errno (ENAMETOOLONG);
|
||||
goto error;
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
/* Bug 22786: test for buffer overflow in realpath.
|
||||
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/>. */
|
||||
|
||||
/* This file must be run from within a directory called "stdlib". */
|
||||
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <support/test-driver.h>
|
||||
#include <libc-internal.h>
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
const char dir[] = "bz22786";
|
||||
const char lnk[] = "bz22786/symlink";
|
||||
|
||||
rmdir (dir);
|
||||
if (mkdir (dir, 0755) != 0 && errno != EEXIST)
|
||||
{
|
||||
printf ("mkdir %s: %m\n", dir);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
if (symlink (".", lnk) != 0 && errno != EEXIST)
|
||||
{
|
||||
printf ("symlink (%s, %s): %m\n", dir, lnk);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
const size_t path_len = (size_t) INT_MAX + 1;
|
||||
|
||||
DIAG_PUSH_NEEDS_COMMENT;
|
||||
#if __GNUC_PREREQ (7, 0)
|
||||
/* GCC 7 warns about too-large allocations; here we need such
|
||||
allocation to succeed for the test to work. */
|
||||
DIAG_IGNORE_NEEDS_COMMENT (7, "-Walloc-size-larger-than=");
|
||||
#endif
|
||||
char *path = malloc (path_len);
|
||||
DIAG_POP_NEEDS_COMMENT;
|
||||
|
||||
if (path == NULL)
|
||||
{
|
||||
printf ("malloc (%zu): %m\n", path_len);
|
||||
return EXIT_UNSUPPORTED;
|
||||
}
|
||||
|
||||
/* Construct very long path = "bz22786/symlink/aaaa....." */
|
||||
char *p = mempcpy (path, lnk, sizeof (lnk) - 1);
|
||||
*(p++) = '/';
|
||||
memset (p, 'a', path_len - (path - p) - 2);
|
||||
p[path_len - (path - p) - 1] = '\0';
|
||||
|
||||
/* This call crashes before the fix for bz22786 on 32-bit platforms. */
|
||||
p = realpath (path, NULL);
|
||||
|
||||
if (p != NULL || errno != ENAMETOOLONG)
|
||||
{
|
||||
printf ("realpath: %s (%m)", p);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
/* Cleanup. */
|
||||
unlink (lnk);
|
||||
rmdir (dir);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define TEST_FUNCTION do_test
|
||||
#include <support/test-driver.c>
|
||||
@@ -245,6 +245,60 @@ do_random_tests (void)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
do_test2 (void)
|
||||
{
|
||||
size_t size = 0x20000000;
|
||||
uint32_t * large_buf;
|
||||
|
||||
large_buf = mmap ((void*) 0x70000000, size, PROT_READ | PROT_WRITE,
|
||||
MAP_PRIVATE | MAP_ANON, -1, 0);
|
||||
|
||||
if (large_buf == MAP_FAILED)
|
||||
error (77, errno, "Large mmap failed");
|
||||
|
||||
if ((uintptr_t) large_buf > 0x80000000 - 128
|
||||
|| 0x80000000 - (uintptr_t) large_buf > 0x20000000)
|
||||
{
|
||||
error (0, 0, "Large mmap allocated improperly");
|
||||
ret = 77;
|
||||
munmap ((void *) large_buf, size);
|
||||
return;
|
||||
}
|
||||
|
||||
size_t bytes_move = 0x80000000 - (uintptr_t) large_buf;
|
||||
size_t arr_size = bytes_move / sizeof (uint32_t);
|
||||
size_t i;
|
||||
|
||||
FOR_EACH_IMPL (impl, 0)
|
||||
{
|
||||
for (i = 0; i < arr_size; i++)
|
||||
large_buf[i] = (uint32_t) i;
|
||||
|
||||
uint32_t * dst = &large_buf[33];
|
||||
|
||||
#ifdef TEST_BCOPY
|
||||
CALL (impl, (char *) large_buf, (char *) dst, bytes_move);
|
||||
#else
|
||||
CALL (impl, (char *) dst, (char *) large_buf, bytes_move);
|
||||
#endif
|
||||
|
||||
for (i = 0; i < arr_size; i++)
|
||||
{
|
||||
if (dst[i] != (uint32_t) i)
|
||||
{
|
||||
error (0, 0,
|
||||
"Wrong result in function %s dst \"%p\" src \"%p\" offset \"%zd\"",
|
||||
impl->name, dst, large_buf, i);
|
||||
ret = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
munmap ((void *) large_buf, size);
|
||||
}
|
||||
|
||||
int
|
||||
test_main (void)
|
||||
{
|
||||
@@ -284,6 +338,9 @@ test_main (void)
|
||||
}
|
||||
|
||||
do_random_tests ();
|
||||
|
||||
do_test2 ();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#define MEMCPY_RESULT(dst, len) (dst) + (len)
|
||||
#define MIN_PAGE_SIZE 131072
|
||||
#define TEST_MAIN
|
||||
#define TEST_NAME "mempcpy"
|
||||
#include "test-string.h"
|
||||
|
||||
+13
-1
@@ -96,13 +96,18 @@ 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)
|
||||
xtests += thrsvc
|
||||
endif
|
||||
|
||||
ifeq ($(run-built-tests),yes)
|
||||
rpcgen-tests := $(objpfx)bug20790.out
|
||||
tests-special += $(rpcgen-tests)
|
||||
endif
|
||||
|
||||
headers += $(rpcsvc:%.x=rpcsvc/%.h)
|
||||
extra-libs := librpcsvc
|
||||
extra-libs-others := librpcsvc # Make it in `others' pass, not `lib' pass.
|
||||
@@ -153,6 +158,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))
|
||||
|
||||
@@ -225,3 +231,9 @@ endif
|
||||
endif
|
||||
|
||||
$(objpfx)thrsvc: $(common-objpfx)linkobj/libc.so $(shared-thread-library)
|
||||
|
||||
ifeq ($(run-built-tests),yes)
|
||||
$(rpcgen-tests): $(objpfx)%.out: %.x $(objpfx)rpcgen
|
||||
$(built-program-cmd) -c $< -o $@; \
|
||||
$(evaluate-test)
|
||||
endif
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
program TPROG { version TVERS { int FUNC(int aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) = 1; } = 1; } = 1;
|
||||
+1
-1
@@ -421,9 +421,9 @@ send_again:
|
||||
cmsg = CMSG_NXTHDR (&msg, cmsg))
|
||||
if (cmsg->cmsg_level == SOL_IP && cmsg->cmsg_type == IP_RECVERR)
|
||||
{
|
||||
free (cbuf);
|
||||
e = (struct sock_extended_err *) CMSG_DATA(cmsg);
|
||||
cu->cu_error.re_errno = e->ee_errno;
|
||||
free (cbuf);
|
||||
return (cu->cu_error.re_status = RPC_CANTRECV);
|
||||
}
|
||||
free (cbuf);
|
||||
|
||||
+1
-1
@@ -521,7 +521,7 @@ static void
|
||||
get_prog_declaration (declaration * dec, defkind dkind, int num /* arg number */ )
|
||||
{
|
||||
token tok;
|
||||
char name[10]; /* argument name */
|
||||
char name[MAXLINESIZE]; /* argument name */
|
||||
|
||||
if (dkind == DEF_PROGRAM)
|
||||
{
|
||||
|
||||
@@ -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
|
||||
@@ -0,0 +1,29 @@
|
||||
This subdirectory contains infrastructure which is not put into
|
||||
installed libraries, but may be linked into programs (installed or
|
||||
not) and tests.
|
||||
|
||||
# Error-checking wrappers
|
||||
|
||||
These wrappers test for error return codes an terminate the process on
|
||||
error. They are declared in these header files:
|
||||
|
||||
* support.h
|
||||
* xsignal.h
|
||||
* xthread.h
|
||||
|
||||
In general, new wrappers should be added to support.h if possible.
|
||||
However, support.h must remain fully compatible with C90 and therefore
|
||||
cannot include headers which use identifers not reserved in C90. If
|
||||
the wrappers need additional types, additional headers such as
|
||||
signal.h need to be introduced.
|
||||
|
||||
# Test framework
|
||||
|
||||
The test framework provides a main program for tests, including a
|
||||
timeout for hanging tests. See README-testing.c for a minimal
|
||||
example, and test-driver.c for details how to use it. The following
|
||||
header files provide related declarations:
|
||||
|
||||
* check.h
|
||||
* temp_file.h
|
||||
* test-driver.h
|
||||
@@ -0,0 +1,19 @@
|
||||
/* This file contains an example test case which shows minimal use of
|
||||
the test framework. Additional testing hooks are described in
|
||||
<support/test-driver.c>. */
|
||||
|
||||
/* This function will be called from the test driver. */
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
if (3 == 5)
|
||||
/* Indicate failure. */
|
||||
return 1;
|
||||
else
|
||||
/* Indicate success. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This file references do_test above and contains the definition of
|
||||
the main function. */
|
||||
#include <support/test-driver.c>
|
||||
@@ -0,0 +1,61 @@
|
||||
/* Capture output from a subprocess.
|
||||
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 SUPPORT_CAPTURE_SUBPROCESS_H
|
||||
#define SUPPORT_CAPTURE_SUBPROCESS_H
|
||||
|
||||
#include <support/xmemstream.h>
|
||||
|
||||
struct support_capture_subprocess
|
||||
{
|
||||
struct xmemstream out;
|
||||
struct xmemstream err;
|
||||
int status;
|
||||
};
|
||||
|
||||
/* Invoke CALLBACK (CLOSURE) in a subprocess and capture standard
|
||||
output, standard error, and the exit status. The out.buffer and
|
||||
err.buffer members in the result are null-terminated strings which
|
||||
can be examined by the caller (out.out and err.out are NULL). */
|
||||
struct support_capture_subprocess support_capture_subprocess
|
||||
(void (*callback) (void *), void *closure);
|
||||
|
||||
/* Deallocate the subprocess data captured by
|
||||
support_capture_subprocess. */
|
||||
void support_capture_subprocess_free (struct support_capture_subprocess *);
|
||||
|
||||
enum support_capture_allow
|
||||
{
|
||||
/* No output is allowed. */
|
||||
sc_allow_none = 0x01,
|
||||
/* Output to stdout is permitted. */
|
||||
sc_allow_stdout = 0x02,
|
||||
/* Output to standard error is permitted. */
|
||||
sc_allow_stderr = 0x04,
|
||||
};
|
||||
|
||||
/* Check that the subprocess exited with STATUS and that only the
|
||||
allowed outputs happened. ALLOWED is a combination of
|
||||
support_capture_allow flags. Report errors under the CONTEXT
|
||||
message. */
|
||||
void support_capture_subprocess_check (struct support_capture_subprocess *,
|
||||
const char *context, int status,
|
||||
int allowed)
|
||||
__attribute__ ((nonnull (1, 2)));
|
||||
|
||||
#endif /* SUPPORT_CAPTURE_SUBPROCESS_H */
|
||||
@@ -0,0 +1,57 @@
|
||||
/* Support code for reporting test results.
|
||||
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/>. */
|
||||
|
||||
#include <support/check.h>
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <support/test-driver.h>
|
||||
|
||||
static void
|
||||
print_failure (const char *file, int line, const char *format, va_list ap)
|
||||
{
|
||||
printf ("error: %s:%d: ", file, line);
|
||||
vprintf (format, ap);
|
||||
puts ("");
|
||||
}
|
||||
|
||||
int
|
||||
support_print_failure_impl (const char *file, int line,
|
||||
const char *format, ...)
|
||||
{
|
||||
support_record_failure ();
|
||||
va_list ap;
|
||||
va_start (ap, format);
|
||||
print_failure (file, line, format, ap);
|
||||
va_end (ap);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
support_exit_failure_impl (int status, const char *file, int line,
|
||||
const char *format, ...)
|
||||
{
|
||||
if (status != EXIT_SUCCESS && status != EXIT_UNSUPPORTED)
|
||||
support_record_failure ();
|
||||
va_list ap;
|
||||
va_start (ap, format);
|
||||
print_failure (file, line, format, ap);
|
||||
va_end (ap);
|
||||
exit (status);
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
/* Functionality for reporting test results.
|
||||
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/>. */
|
||||
|
||||
#ifndef SUPPORT_CHECK_H
|
||||
#define SUPPORT_CHECK_H
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
/* Record a test failure, print the failure message to standard output
|
||||
and return 1. */
|
||||
#define FAIL_RET(...) \
|
||||
return support_print_failure_impl (__FILE__, __LINE__, __VA_ARGS__)
|
||||
|
||||
/* Print the failure message and terminate the process with STATUS.
|
||||
Record a the process as failed if STATUS is neither EXIT_SUCCESS
|
||||
nor EXIT_UNSUPPORTED. */
|
||||
#define FAIL_EXIT(status, ...) \
|
||||
support_exit_failure_impl (status, __FILE__, __LINE__, __VA_ARGS__)
|
||||
|
||||
/* Record a test failure, print the failure message and terminate with
|
||||
exit status 1. */
|
||||
#define FAIL_EXIT1(...) \
|
||||
support_exit_failure_impl (1, __FILE__, __LINE__, __VA_ARGS__)
|
||||
|
||||
/* Print failure message and terminate with as unsupported test (exit
|
||||
status of 77). */
|
||||
#define FAIL_UNSUPPORTED(...) \
|
||||
support_exit_failure_impl (77, __FILE__, __LINE__, __VA_ARGS__)
|
||||
|
||||
/* Record a test failure (but continue executing) if EXPR evaluates to
|
||||
false. */
|
||||
#define TEST_VERIFY(expr) \
|
||||
({ \
|
||||
if (expr) \
|
||||
; \
|
||||
else \
|
||||
support_test_verify_impl (-1, __FILE__, __LINE__, #expr); \
|
||||
})
|
||||
|
||||
/* Record a test failure and exit if EXPR evaluates to false. */
|
||||
#define TEST_VERIFY_EXIT(expr) \
|
||||
({ \
|
||||
if (expr) \
|
||||
; \
|
||||
else \
|
||||
support_test_verify_impl (1, __FILE__, __LINE__, #expr); \
|
||||
})
|
||||
|
||||
int support_print_failure_impl (const char *file, int line,
|
||||
const char *format, ...)
|
||||
__attribute__ ((nonnull (1), format (printf, 3, 4)));
|
||||
void support_exit_failure_impl (int exit_status,
|
||||
const char *file, int line,
|
||||
const char *format, ...)
|
||||
__attribute__ ((noreturn, nonnull (2), format (printf, 4, 5)));
|
||||
void support_test_verify_impl (int status, const char *file, int line,
|
||||
const char *expr);
|
||||
|
||||
/* Record a test failure. This function returns and does not
|
||||
terminate the process. The failure counter is stored in a shared
|
||||
memory mapping, so that failures reported in child processes are
|
||||
visible to the parent process and test driver. This function
|
||||
depends on initialization by an ELF constructor, so it can only be
|
||||
invoked after the test driver has run. Note that this function
|
||||
does not support reporting failures from a DSO. */
|
||||
void support_record_failure (void);
|
||||
|
||||
/* Internal function called by the test driver. */
|
||||
int support_report_failure (int status)
|
||||
__attribute__ ((weak, warn_unused_result));
|
||||
|
||||
/* Internal function used to test the failure recording framework. */
|
||||
void support_record_failure_reset (void);
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif /* SUPPORT_CHECK_H */
|
||||
@@ -0,0 +1,42 @@
|
||||
/* Compare struct addrinfo values against a formatted string.
|
||||
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/>. */
|
||||
|
||||
#include <support/check_nss.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <support/check.h>
|
||||
#include <support/format_nss.h>
|
||||
#include <support/run_diff.h>
|
||||
|
||||
void
|
||||
check_addrinfo (const char *query_description, struct addrinfo *ai, int ret,
|
||||
const char *expected)
|
||||
{
|
||||
char *formatted = support_format_addrinfo (ai, ret);
|
||||
if (strcmp (formatted, expected) != 0)
|
||||
{
|
||||
support_record_failure ();
|
||||
printf ("error: addrinfo comparison failure\n");
|
||||
if (query_description != NULL)
|
||||
printf ("query: %s\n", query_description);
|
||||
support_run_diff ("expected", expected,
|
||||
"actual", formatted);
|
||||
}
|
||||
free (formatted);
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/* Check that a DNS packet buffer has the expected contents.
|
||||
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/>. */
|
||||
|
||||
#include <support/check_nss.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <support/check.h>
|
||||
#include <support/format_nss.h>
|
||||
#include <support/run_diff.h>
|
||||
|
||||
void
|
||||
check_dns_packet (const char *query_description,
|
||||
const unsigned char *buffer, size_t length,
|
||||
const char *expected)
|
||||
{
|
||||
char *formatted = support_format_dns_packet (buffer, length);
|
||||
if (strcmp (formatted, expected) != 0)
|
||||
{
|
||||
support_record_failure ();
|
||||
printf ("error: packet comparison failure\n");
|
||||
if (query_description != NULL)
|
||||
printf ("query: %s\n", query_description);
|
||||
support_run_diff ("expected", expected, "actual", formatted);
|
||||
}
|
||||
free (formatted);
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/* Compare struct hostent values against a formatted string.
|
||||
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/>. */
|
||||
|
||||
#include <support/check_nss.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <support/check.h>
|
||||
#include <support/format_nss.h>
|
||||
#include <support/run_diff.h>
|
||||
|
||||
void
|
||||
check_hostent (const char *query_description, struct hostent *h,
|
||||
const char *expected)
|
||||
{
|
||||
char *formatted = support_format_hostent (h);
|
||||
if (strcmp (formatted, expected) != 0)
|
||||
{
|
||||
support_record_failure ();
|
||||
printf ("error: hostent comparison failure\n");
|
||||
if (query_description != NULL)
|
||||
printf ("query: %s\n", query_description);
|
||||
support_run_diff ("expected", expected,
|
||||
"actual", formatted);
|
||||
}
|
||||
free (formatted);
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/* Compare struct netent values against a formatted string.
|
||||
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/>. */
|
||||
|
||||
#include <support/check_nss.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <support/check.h>
|
||||
#include <support/format_nss.h>
|
||||
#include <support/run_diff.h>
|
||||
|
||||
void
|
||||
check_netent (const char *query_description, struct netent *e,
|
||||
const char *expected)
|
||||
{
|
||||
char *formatted = support_format_netent (e);
|
||||
if (strcmp (formatted, expected) != 0)
|
||||
{
|
||||
support_record_failure ();
|
||||
printf ("error: netent comparison failure\n");
|
||||
if (query_description != NULL)
|
||||
printf ("query: %s\n", query_description);
|
||||
support_run_diff ("expected", expected,
|
||||
"actual", formatted);
|
||||
}
|
||||
free (formatted);
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/* Test verification functions for NSS- and DNS-related data.
|
||||
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/>. */
|
||||
|
||||
#ifndef SUPPORT_CHECK_NSS_H
|
||||
#define SUPPORT_CHECK_NSS_H
|
||||
|
||||
#include <netdb.h>
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
/* Compare the data structures against the expected values (which have
|
||||
to be formatted according to the support_format_* functions in
|
||||
<support/format_nss.h>). If there is a difference, a delayed test
|
||||
failure is recorded, and a diff is written to standard output. */
|
||||
void check_addrinfo (const char *query_description,
|
||||
struct addrinfo *, int ret, const char *expected);
|
||||
void check_dns_packet (const char *query_description,
|
||||
const unsigned char *, size_t, const char *expected);
|
||||
void check_hostent (const char *query_description,
|
||||
struct hostent *, const char *expected);
|
||||
void check_netent (const char *query_description,
|
||||
struct netent *, const char *expected);
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif /* SUPPORT_CHECK_NSS_H */
|
||||
@@ -0,0 +1,55 @@
|
||||
/* Time-triggered process termination.
|
||||
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/>. */
|
||||
|
||||
#include <support/xthread.h>
|
||||
#include <support/xsignal.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <support/check.h>
|
||||
#include <time.h>
|
||||
|
||||
static void *
|
||||
delayed_exit_thread (void *seconds_as_ptr)
|
||||
{
|
||||
int seconds = (uintptr_t) seconds_as_ptr;
|
||||
struct timespec delay = { seconds, 0 };
|
||||
struct timespec remaining = { 0 };
|
||||
if (nanosleep (&delay, &remaining) != 0)
|
||||
FAIL_EXIT1 ("nanosleep: %m");
|
||||
/* Exit the process sucessfully. */
|
||||
exit (0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
delayed_exit (int seconds)
|
||||
{
|
||||
/* Create the new thread with all signals blocked. */
|
||||
sigset_t all_blocked;
|
||||
sigfillset (&all_blocked);
|
||||
sigset_t old_set;
|
||||
xpthread_sigmask (SIG_SETMASK, &all_blocked, &old_set);
|
||||
/* Create a detached thread. */
|
||||
pthread_t thr = xpthread_create
|
||||
(NULL, delayed_exit_thread, (void *) (uintptr_t) seconds);
|
||||
xpthread_detach (thr);
|
||||
/* Restore the original signal mask. */
|
||||
xpthread_sigmask (SIG_SETMASK, &old_set, NULL);
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/* String formatting functions for NSS- and DNS-related data.
|
||||
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/>. */
|
||||
|
||||
#ifndef SUPPORT_FORMAT_NSS_H
|
||||
#define SUPPORT_FORMAT_NSS_H
|
||||
|
||||
#include <netdb.h>
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
/* The following functions format their arguments as human-readable
|
||||
strings (which can span multiple lines). The caller must free the
|
||||
returned buffer. For NULL pointers or failure status arguments,
|
||||
error variables such as h_errno and errno are included in the
|
||||
result. */
|
||||
char *support_format_address_family (int);
|
||||
char *support_format_addrinfo (struct addrinfo *, int ret);
|
||||
char *support_format_dns_packet (const unsigned char *buffer, size_t length);
|
||||
char *support_format_herrno (int);
|
||||
char *support_format_hostent (struct hostent *);
|
||||
char *support_format_netent (struct netent *);
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif /* SUPPORT_FORMAT_NSS_H */
|
||||
@@ -0,0 +1,38 @@
|
||||
/* Avoid all the buffer overflow messages on stderr.
|
||||
Copyright (C) 2015-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 <support/support.h>
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <paths.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
void
|
||||
ignore_stderr (void)
|
||||
{
|
||||
int fd = open (_PATH_DEVNULL, O_WRONLY);
|
||||
if (fd == -1)
|
||||
close (STDERR_FILENO);
|
||||
else
|
||||
{
|
||||
dup2 (fd, STDERR_FILENO);
|
||||
close (fd);
|
||||
}
|
||||
setenv ("LIBC_FATAL_STDERR_", "1", 1);
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
/* Entering namespaces for test case isolation.
|
||||
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/>. */
|
||||
|
||||
#ifndef SUPPORT_NAMESPACE_H
|
||||
#define SUPPORT_NAMESPACE_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
/* Attempts to become root (or acquire root-like privileges), possibly
|
||||
with the help of user namespaces. Return true if (restricted) root
|
||||
privileges could be attained in some way. Print diagnostics to
|
||||
standard output.
|
||||
|
||||
Note that this function generally has to be called before a process
|
||||
becomes multi-threaded, otherwise it may fail with insufficient
|
||||
privileges on systems which would support this operation for
|
||||
single-threaded processes. */
|
||||
bool support_become_root (void);
|
||||
|
||||
/* Return true if this process can perform a chroot operation. In
|
||||
general, this is only possible if support_become_root has been
|
||||
called. Note that the actual test is performed in a subprocess,
|
||||
after fork, so that the file system root of the original process is
|
||||
not changed. */
|
||||
bool support_can_chroot (void);
|
||||
|
||||
/* Enter a network namespace (and a UTS namespace if possible) and
|
||||
configure the loopback interface. Return true if a network
|
||||
namespace could be created. Print diagnostics to standard output.
|
||||
If a network namespace could be created, but networking in it could
|
||||
not be configured, terminate the process. It is recommended to
|
||||
call support_become_root before this function so that the process
|
||||
has sufficient privileges. */
|
||||
bool support_enter_network_namespace (void);
|
||||
|
||||
/* Return true if support_enter_network_namespace managed to enter a
|
||||
UTS namespace. */
|
||||
bool support_in_uts_namespace (void);
|
||||
|
||||
/* Invoke CALLBACK (CLOSURE) in a subprocess created using fork.
|
||||
Terminate the calling process if the subprocess exits with a
|
||||
non-zero exit status. */
|
||||
void support_isolate_in_subprocess (void (*callback) (void *), void *closure);
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif
|
||||
@@ -1,7 +1,6 @@
|
||||
/* Compute positive difference, sparc 64-bit.
|
||||
Copyright (C) 2013-2016 Free Software Foundation, Inc.
|
||||
/* Reporting out-of-memory errors.
|
||||
Copyright (C) 2016-2017 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by David S. Miller <davem@davemloft.net>.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
@@ -17,15 +16,14 @@
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <sysdep.h>
|
||||
#include <support/support.h>
|
||||
|
||||
ENTRY(__fdimf)
|
||||
fcmps %f1, %f3
|
||||
fbug 1f
|
||||
nop
|
||||
fzeros %f1
|
||||
fnegs %f1, %f3
|
||||
1: retl
|
||||
fsubs %f1, %f3, %f0
|
||||
END(__fdimf)
|
||||
weak_alias (__fdimf, fdimf)
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
void
|
||||
oom_error (const char *function, size_t size)
|
||||
{
|
||||
printf ("%s: unable to allocate %zu bytes: %m\n", function, size);
|
||||
exit (1);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,180 @@
|
||||
/* DNS test framework and libresolv redirection.
|
||||
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/>. */
|
||||
|
||||
#ifndef SUPPORT_RESOLV_TEST_H
|
||||
#define SUPPORT_RESOLV_TEST_H
|
||||
|
||||
#include <arpa/nameser.h>
|
||||
#include <stdbool.h>
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
/* Information about EDNS properties of a DNS query. */
|
||||
struct resolv_edns_info
|
||||
{
|
||||
bool active;
|
||||
uint8_t extended_rcode;
|
||||
uint8_t version;
|
||||
uint16_t flags;
|
||||
uint16_t payload_size;
|
||||
};
|
||||
|
||||
/* This struct provides context information when the response callback
|
||||
specified in struct resolv_redirect_config is invoked. */
|
||||
struct resolv_response_context
|
||||
{
|
||||
const unsigned char *query_buffer;
|
||||
size_t query_length;
|
||||
int server_index;
|
||||
bool tcp;
|
||||
struct resolv_edns_info edns;
|
||||
};
|
||||
|
||||
/* This opaque struct is used to construct responses from within the
|
||||
response callback function. */
|
||||
struct resolv_response_builder;
|
||||
|
||||
/* This opaque struct collects information about the resolver testing
|
||||
currently in progress. */
|
||||
struct resolv_test;
|
||||
|
||||
enum
|
||||
{
|
||||
/* Maximum number of test servers supported by the framework. */
|
||||
resolv_max_test_servers = 3,
|
||||
};
|
||||
|
||||
/* Configuration settings specific to individual test servers. */
|
||||
struct resolv_redirect_server_config
|
||||
{
|
||||
bool disable_tcp; /* If true, no TCP server is listening. */
|
||||
bool disable_udp; /* If true, no UDP server is listening. */
|
||||
};
|
||||
|
||||
/* Instructions for setting up the libresolv redirection. */
|
||||
struct resolv_redirect_config
|
||||
{
|
||||
/* The response_callback function is called for every incoming DNS
|
||||
packet, over UDP or TCP. It must be specified, the other
|
||||
configuration settings are optional. */
|
||||
void (*response_callback) (const struct resolv_response_context *,
|
||||
struct resolv_response_builder *,
|
||||
const char *qname,
|
||||
uint16_t qclass, uint16_t qtype);
|
||||
|
||||
/* Per-server configuration. */
|
||||
struct resolv_redirect_server_config servers[resolv_max_test_servers];
|
||||
|
||||
/* Search path entries. The first entry serves as the default
|
||||
domain name as well. */
|
||||
const char *search[7];
|
||||
|
||||
/* Number of servers to activate in resolv. 0 means the default,
|
||||
resolv_max_test_servers. */
|
||||
int nscount;
|
||||
|
||||
/* If true, use a single thread to process all UDP queries. This
|
||||
may results in more predictable ordering of queries and
|
||||
responses. */
|
||||
bool single_thread_udp;
|
||||
};
|
||||
|
||||
/* Configure NSS to use, nss_dns only for aplicable databases, and try
|
||||
to put the process into a network namespace for better isolation.
|
||||
This may have to be called before resolv_test_start, before the
|
||||
process creates any threads. Otherwise, initialization is
|
||||
performed by resolv_test_start implicitly. */
|
||||
void resolv_test_init (void);
|
||||
|
||||
/* Initiate resolver testing. This updates the _res variable as
|
||||
needed. As a side effect, NSS is reconfigured to use nss_dns only
|
||||
for aplicable databases, and the process may enter a network
|
||||
namespace for better isolation. */
|
||||
struct resolv_test *resolv_test_start (struct resolv_redirect_config);
|
||||
|
||||
/* Call this function at the end of resolver testing, to free
|
||||
resources and report pending errors (if any). */
|
||||
void resolv_test_end (struct resolv_test *);
|
||||
|
||||
/* The remaining facilities in this file are used for constructing
|
||||
response packets from the response_callback function. */
|
||||
|
||||
/* Special settings for constructing responses from the callback. */
|
||||
struct resolv_response_flags
|
||||
{
|
||||
/* 4-bit response code to incorporate into the response. */
|
||||
unsigned char rcode;
|
||||
|
||||
/* If true, the TC (truncation) flag will be set. */
|
||||
bool tc;
|
||||
|
||||
/* Initial section count values. Can be used to artificially
|
||||
increase the counts, for malformed packet testing.*/
|
||||
unsigned short qdcount;
|
||||
unsigned short ancount;
|
||||
unsigned short nscount;
|
||||
unsigned short adcount;
|
||||
};
|
||||
|
||||
/* Begin a new response with the requested flags. Must be called
|
||||
first. */
|
||||
void resolv_response_init (struct resolv_response_builder *,
|
||||
struct resolv_response_flags);
|
||||
|
||||
/* Switches to the section in the response packet. Only forward
|
||||
movement is supported. */
|
||||
void resolv_response_section (struct resolv_response_builder *, ns_sect);
|
||||
|
||||
/* Add a question record to the question section. */
|
||||
void resolv_response_add_question (struct resolv_response_builder *,
|
||||
const char *name, uint16_t class,
|
||||
uint16_t type);
|
||||
/* Starts a new resource record with the specified owner name, class,
|
||||
type, and TTL. Data is supplied with resolv_response_add_data or
|
||||
resolv_response_add_name. */
|
||||
void resolv_response_open_record (struct resolv_response_builder *,
|
||||
const char *name, uint16_t class,
|
||||
uint16_t type, uint32_t ttl);
|
||||
|
||||
/* Add unstructed bytes to the RDATA part of a resource record. */
|
||||
void resolv_response_add_data (struct resolv_response_builder *,
|
||||
const void *, size_t);
|
||||
|
||||
/* Add a compressed domain name to the RDATA part of a resource
|
||||
record. */
|
||||
void resolv_response_add_name (struct resolv_response_builder *,
|
||||
const char *name);
|
||||
|
||||
/* Mark the end of the constructed record. Must be called last. */
|
||||
void resolv_response_close_record (struct resolv_response_builder *);
|
||||
|
||||
/* Drop this query packet (that is, do not send a response, not even
|
||||
an empty packet). */
|
||||
void resolv_response_drop (struct resolv_response_builder *);
|
||||
|
||||
/* In TCP mode, close the connection after this packet (if a response
|
||||
is sent). */
|
||||
void resolv_response_close (struct resolv_response_builder *);
|
||||
|
||||
/* The size of the response packet built so far. */
|
||||
size_t resolv_response_length (const struct resolv_response_builder *);
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif /* SUPPORT_RESOLV_TEST_H */
|
||||
@@ -0,0 +1,31 @@
|
||||
/* Invoke the system diff tool to compare two strings.
|
||||
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/>. */
|
||||
|
||||
#ifndef SUPPORT_RUN_DIFF_H
|
||||
#define SUPPORT_RUN_DIFF_H
|
||||
|
||||
/* Compare the two NUL-terminated strings LEFT and RIGHT using the
|
||||
diff tool. Label the sides of the diff with LEFT_LABEL and
|
||||
RIGHT_LABEL, respectively.
|
||||
|
||||
This function assumes that LEFT and RIGHT are different
|
||||
strings. */
|
||||
void support_run_diff (const char *left_label, const char *left,
|
||||
const char *right_label, const char *right);
|
||||
|
||||
#endif /* SUPPORT_RUN_DIFF_H */
|
||||
@@ -0,0 +1,34 @@
|
||||
/* Set signal handler for use in fortify tests.
|
||||
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/>. */
|
||||
|
||||
#include <support/support.h>
|
||||
|
||||
#include <signal.h>
|
||||
|
||||
void
|
||||
set_fortify_handler (void (*handler) (int sig))
|
||||
{
|
||||
struct sigaction sa;
|
||||
|
||||
sa.sa_handler = handler;
|
||||
sa.sa_flags = 0;
|
||||
sigemptyset (&sa.sa_mask);
|
||||
|
||||
sigaction (SIGABRT, &sa, NULL);
|
||||
ignore_stderr ();
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user