mirror of
git://sourceware.org/git/glibc.git
synced 2026-09-09 23:58:37 +08:00
Compare commits
109
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b039fd85db | ||
|
|
8337b12d0b | ||
|
|
fbd72f1490 | ||
|
|
26d289bb92 | ||
|
|
9d521f59de | ||
|
|
93710f5174 | ||
|
|
bc566388d6 | ||
|
|
4401ec26af | ||
|
|
d990d79610 | ||
|
|
901d3d5aaa | ||
|
|
03b0b2b471 | ||
|
|
8cc357efd3 | ||
|
|
efa26d9c13 | ||
|
|
9f172a30ac | ||
|
|
0be74c5c7c | ||
|
|
800f9aa06b | ||
|
|
da9f68f2b9 | ||
|
|
e9d53ff4d4 | ||
|
|
3a5aa2ee4f | ||
|
|
51a313c504 | ||
|
|
12bf4f130d | ||
|
|
85186de4f4 | ||
|
|
8ee1ecb99c | ||
|
|
a6a59e99d1 | ||
|
|
422facff9f | ||
|
|
6ab1e91474 | ||
|
|
0350824fab | ||
|
|
79312adef2 | ||
|
|
2eda04ec6f | ||
|
|
a86b1fac28 | ||
|
|
9e9fcd095a | ||
|
|
79ad3fa2b1 | ||
|
|
395b1b9cbf | ||
|
|
a69d26143b | ||
|
|
23446cad92 | ||
|
|
3a97372dbe | ||
|
|
0266710379 | ||
|
|
e3e0bedf69 | ||
|
|
bbe472f4e0 | ||
|
|
0903610fdc | ||
|
|
3d21617c43 | ||
|
|
6bf10d196d | ||
|
|
cacad9315e | ||
|
|
d16e36e575 | ||
|
|
80bf719031 | ||
|
|
321e1cef26 | ||
|
|
c2fba3b047 | ||
|
|
1915d6d182 | ||
|
|
e6eea05ee7 | ||
|
|
f222547511 | ||
|
|
bdce95930e | ||
|
|
25a34b0ac1 | ||
|
|
2143af6a47 | ||
|
|
a37d61a662 | ||
|
|
1a8a7c1295 | ||
|
|
24e2b1cede | ||
|
|
bbea74b299 | ||
|
|
a824d60958 | ||
|
|
80f87443ee | ||
|
|
c4294bd862 | ||
|
|
c87db3fcbd | ||
|
|
68302147ee | ||
|
|
90c0f166e9 | ||
|
|
4cf055a2a3 | ||
|
|
d603d94994 | ||
|
|
7fa9775594 | ||
|
|
075b2665b1 | ||
|
|
1e5ac8a1da | ||
|
|
730244f49a | ||
|
|
1e51b4d367 | ||
|
|
f233c608d1 | ||
|
|
49203a513f | ||
|
|
888d9a0146 | ||
|
|
927170dd59 | ||
|
|
2a71cf4096 | ||
|
|
a5c2f42566 | ||
|
|
f69ae17e84 | ||
|
|
4c4b3cbb46 | ||
|
|
2d1f679018 | ||
|
|
8a756c076e | ||
|
|
f8020794ae | ||
|
|
05d2606fa1 | ||
|
|
c5aae1035c | ||
|
|
e5bcbfc23b | ||
|
|
42a496388d | ||
|
|
28a87e0274 | ||
|
|
5769d5d17c | ||
|
|
f1e182acaa | ||
|
|
146b58d11f | ||
|
|
0eb234232e | ||
|
|
d93f04543c | ||
|
|
3a188eb4e6 | ||
|
|
73f158cef5 | ||
|
|
317da342ba | ||
|
|
33ab2ad58e | ||
|
|
b4456470a6 | ||
|
|
3ac64b00b5 | ||
|
|
0594fd0546 | ||
|
|
63ed4db4b4 | ||
|
|
9d1399e89d | ||
|
|
f23d7d2a84 | ||
|
|
0a321a461c | ||
|
|
d27dabc996 | ||
|
|
591b7e37e6 | ||
|
|
f0029f1bb3 | ||
|
|
6094fc2cf7 | ||
|
|
e742928c15 | ||
|
|
d3a793f7ee | ||
|
|
792c8ddc60 |
@@ -4,6 +4,59 @@ 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.23.1
|
||||
|
||||
Security related changes:
|
||||
|
||||
* The getnetbyname implementation in nss_dns had a potentially unbounded
|
||||
alloca call (in the form of a call to strdupa), leading to a stack
|
||||
overflow (stack exhaustion) and a crash if getnetbyname is invoked
|
||||
on a very long name. (CVE-2016-3075)
|
||||
|
||||
* The glob function suffered from a stack-based buffer overflow when it was
|
||||
called with the GLOB_ALTDIRFUNC flag and encountered a long file name.
|
||||
Reported by Alexander Cherepanov. (CVE-2016-1234)
|
||||
|
||||
* The Sun RPC UDP client could exhaust all available stack space when
|
||||
flooded with crafted ICMP and UDP messages. Reported by Aldy Hernandez'
|
||||
alloca plugin for GCC. (CVE-2016-4429)
|
||||
|
||||
* 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)
|
||||
|
||||
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:
|
||||
|
||||
[19679] gcc-4.9.3 C++ exception handling broken due to unaligned stack
|
||||
[19758] Or bit_Prefer_MAP_32BIT_EXEC in EXTRA_LD_ENVVARS
|
||||
[19759] Don't inline mempcpy for x86
|
||||
[19762] Use HAS_ARCH_FEATURE with Fast_Rep_String
|
||||
[19791] Assertion failure in res_query.c with un-connectable name server
|
||||
addresses
|
||||
[19792] MIPS: backtrace yields infinite backtrace with makecontext
|
||||
[19822] libm.so install clobbers old version
|
||||
[19879] network: nss_dns: Stack overflow in getnetbyname implementation
|
||||
(CVE-2016-3075)
|
||||
[20177] $dp is not initialized correctly in sysdeps/hppa/start.S
|
||||
[20357] Incorrect cos result for 1.5174239687223976
|
||||
[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
|
||||
[21624] Unsafe alloca allows local attackers to alias stack and heap (CVE-2017-1000366)
|
||||
[21666] Avoid .symver on common symbols
|
||||
[22641] x86: Fix mis-merge of XSAVE ld.so trampoline selection
|
||||
[22715] x86-64: Properly align La_x86_64_retval to VEC_SIZE
|
||||
[25204] Ignore LD_PREFER_MAP_32BIT_EXEC for SUID programs
|
||||
|
||||
|
||||
Version 2.23
|
||||
|
||||
@@ -38,7 +91,7 @@ Version 2.23
|
||||
unnecessary serialization of memory allocation requests across threads.
|
||||
The defect is now corrected. Users should see a substantial increase in
|
||||
the concurent throughput of allocation requests for applications which
|
||||
trigger this bug. Affected applications typically create create and
|
||||
trigger this bug. Affected applications typically create and
|
||||
destroy threads frequently. (Bug 19048 was reported and analyzed by
|
||||
Ericsson.)
|
||||
|
||||
|
||||
+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 */
|
||||
|
||||
+4
-1
@@ -1,4 +1,4 @@
|
||||
/* Definition of `struct sockaddr_*' common members. Generic/4.2 BSD version.
|
||||
/* Definition of struct sockaddr_* common members and sizes, generic version.
|
||||
Copyright (C) 1995-2016 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
@@ -36,4 +36,7 @@ typedef unsigned short int sa_family_t;
|
||||
|
||||
#define __SOCKADDR_COMMON_SIZE (sizeof (unsigned short int))
|
||||
|
||||
/* Size of struct sockaddr_storage. */
|
||||
#define _SS_SIZE 128
|
||||
|
||||
#endif /* bits/sockaddr.h */
|
||||
|
||||
+4
-4
@@ -152,20 +152,20 @@ struct sockaddr
|
||||
|
||||
|
||||
/* Structure large enough to hold any socket address (with the historical
|
||||
exception of AF_UNIX). We reserve 128 bytes. */
|
||||
exception of AF_UNIX). */
|
||||
#if ULONG_MAX > 0xffffffff
|
||||
# define __ss_aligntype __uint64_t
|
||||
#else
|
||||
# define __ss_aligntype __uint32_t
|
||||
#endif
|
||||
#define _SS_SIZE 128
|
||||
#define _SS_PADSIZE (_SS_SIZE - (2 * sizeof (__ss_aligntype)))
|
||||
#define _SS_PADSIZE \
|
||||
(_SS_SIZE - __SOCKADDR_COMMON_SIZE - sizeof (__ss_aligntype))
|
||||
|
||||
struct sockaddr_storage
|
||||
{
|
||||
__SOCKADDR_COMMON (ss_); /* Address family, etc. */
|
||||
__ss_aligntype __ss_align; /* Force desired alignment. */
|
||||
char __ss_padding[_SS_PADSIZE];
|
||||
__ss_aligntype __ss_align; /* Force desired alignment. */
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -3864,7 +3864,7 @@ if test -z "$enable_hacker_mode" && test x"$libc_config_ok" != xyes; then
|
||||
*** The GNU C library is currently unavailable for this platform.
|
||||
*** If you are interested in seeing glibc on this platform visit
|
||||
*** the \"How to submit a new port\" in the wiki:
|
||||
*** https://sourceware.org/glibc/wiki/HomePage#Development
|
||||
*** https://sourceware.org/glibc/wiki/#Development
|
||||
*** and join the community!" "$LINENO" 5
|
||||
;;
|
||||
esac
|
||||
@@ -6252,12 +6252,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
@@ -1603,12 +1603,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],
|
||||
|
||||
+6
-1
@@ -163,7 +163,8 @@ endif
|
||||
endif
|
||||
ifeq ($(run-built-tests),yes)
|
||||
tests-special += $(objpfx)tst-leaks1-mem.out \
|
||||
$(objpfx)tst-leaks1-static-mem.out $(objpfx)noload-mem.out
|
||||
$(objpfx)tst-leaks1-static-mem.out $(objpfx)noload-mem.out \
|
||||
$(objpfx)tst-ldconfig-X.out
|
||||
endif
|
||||
tlsmod17a-suffixes = 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
|
||||
tlsmod18a-suffixes = 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
|
||||
@@ -1252,3 +1253,7 @@ $(objpfx)tst-prelink-cmp.out: tst-prelink.exp \
|
||||
$(objpfx)tst-prelink-conflict.out
|
||||
cmp $^ > $@; \
|
||||
$(evaluate-test)
|
||||
|
||||
$(objpfx)tst-ldconfig-X.out : tst-ldconfig-X.sh $(objpfx)ldconfig
|
||||
$(SHELL) $< '$(common-objpfx)' '$(test-wrapper)' '$(test-wrapper-env)' > $@; \
|
||||
$(evaluate-test)
|
||||
|
||||
+4
-3
@@ -100,7 +100,8 @@ int opt_format = 1;
|
||||
/* Build cache. */
|
||||
static int opt_build_cache = 1;
|
||||
|
||||
/* Generate links. */
|
||||
/* Enable symbolic link processing. If set, create or update symbolic
|
||||
links, and remove stale symbolic links. */
|
||||
static int opt_link = 1;
|
||||
|
||||
/* Only process directories specified on the command line. */
|
||||
@@ -141,7 +142,7 @@ static const struct argp_option options[] =
|
||||
{ "print-cache", 'p', NULL, 0, N_("Print cache"), 0},
|
||||
{ "verbose", 'v', NULL, 0, N_("Generate verbose messages"), 0},
|
||||
{ NULL, 'N', NULL, 0, N_("Don't build cache"), 0},
|
||||
{ NULL, 'X', NULL, 0, N_("Don't generate links"), 0},
|
||||
{ NULL, 'X', NULL, 0, N_("Don't update symbolic links"), 0},
|
||||
{ NULL, 'r', N_("ROOT"), 0, N_("Change to and use ROOT as root directory"), 0},
|
||||
{ NULL, 'C', N_("CACHE"), 0, N_("Use CACHE as cache file"), 0},
|
||||
{ NULL, 'f', N_("CONF"), 0, N_("Use CONF as configuration file"), 0},
|
||||
@@ -800,7 +801,7 @@ search_dir (const struct dir_entry *entry)
|
||||
error (0, errno, _("Cannot stat %s"), file_name);
|
||||
|
||||
/* Remove stale symlinks. */
|
||||
if (strstr (direntry->d_name, ".so."))
|
||||
if (opt_link && strstr (direntry->d_name, ".so."))
|
||||
unlink (real_file_name);
|
||||
continue;
|
||||
}
|
||||
|
||||
+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;
|
||||
|
||||
@@ -164,11 +164,11 @@ makesymlinks (const char *file)
|
||||
static int
|
||||
makesymlink (const char *src, const char *dest)
|
||||
{
|
||||
struct stat stats;
|
||||
struct stat64 stats;
|
||||
const char *error;
|
||||
|
||||
/* Destination must not be a directory. */
|
||||
if (lstat (dest, &stats) == 0)
|
||||
if (lstat64 (dest, &stats) == 0)
|
||||
{
|
||||
if (S_ISDIR (stats.st_mode))
|
||||
{
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
#!/bin/sh
|
||||
# Test that ldconfig -X does not remove stale symbolic links.
|
||||
# Copyright (C) 2000-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/>.
|
||||
|
||||
set -ex
|
||||
|
||||
common_objpfx=$1
|
||||
test_wrapper_env=$2
|
||||
run_program_env=$3
|
||||
|
||||
testroot="${common_objpfx}elf/bug19610-test-directory"
|
||||
cleanup () {
|
||||
rm -rf "$testroot"
|
||||
}
|
||||
trap cleanup 0
|
||||
|
||||
rm -rf "$testroot"
|
||||
mkdir -p $testroot/lib $testroot/etc
|
||||
|
||||
# Relative symbolic link target.
|
||||
ln -s libdoesnotexist.so.1.1 $testroot/lib/libdoesnotexist.so.1
|
||||
|
||||
# Absolute symbolic link target.
|
||||
ln -s $testroot/opt/sw/lib/libdoesnotexist2.so.1.1 $testroot/lib/
|
||||
|
||||
errors=0
|
||||
check_files () {
|
||||
for name in libdoesnotexist.so.1 libdoesnotexist2.so.1.1 ; do
|
||||
path="$testroot/lib/$name"
|
||||
if test ! -h $path ; then
|
||||
echo "error: missing file: $path"
|
||||
errors=1
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
check_files
|
||||
|
||||
${test_wrapper_env} \
|
||||
${run_program_env} \
|
||||
${common_objpfx}elf/ldconfig -X -f /dev/null \
|
||||
-C $testroot/etc/ld.so.cache \
|
||||
$testroot/lib
|
||||
|
||||
check_files
|
||||
|
||||
exit $errors
|
||||
+1
-1
@@ -28,7 +28,7 @@ extra-libs-others = $(extra-libs)
|
||||
subdir-dirs = nss_hesiod
|
||||
vpath %.c nss_hesiod
|
||||
|
||||
libnss_hesiod-routines := hesiod hesiod-grp hesiod-init hesiod-proto \
|
||||
libnss_hesiod-routines := hesiod hesiod-grp hesiod-proto \
|
||||
hesiod-pwd hesiod-service
|
||||
# Build only shared library
|
||||
libnss_hesiod-inhibit-o = $(filter-out .os,$(object-suffixes))
|
||||
|
||||
+19
-70
@@ -1,6 +1,19 @@
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static const char rcsid[] = "$BINDId: hesiod.c,v 1.21 2000/02/28 14:51:08 vixie Exp $";
|
||||
#endif
|
||||
/* Copyright (C) 1997-2016 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1996,1999 by Internet Software Consortium.
|
||||
@@ -52,18 +65,9 @@ static const char rcsid[] = "$BINDId: hesiod.c,v 1.21 2000/02/28 14:51:08 vixie
|
||||
|
||||
/* Forward */
|
||||
|
||||
int hesiod_init(void **context);
|
||||
void hesiod_end(void *context);
|
||||
char * hesiod_to_bind(void *context, const char *name,
|
||||
const char *type);
|
||||
char ** hesiod_resolve(void *context, const char *name,
|
||||
const char *type);
|
||||
void hesiod_free_list(void *context, char **list);
|
||||
|
||||
static int parse_config_file(struct hesiod_p *ctx, const char *filename);
|
||||
static char ** get_txt_records(struct hesiod_p *ctx, int class,
|
||||
const char *name);
|
||||
static int init(struct hesiod_p *ctx);
|
||||
|
||||
/* Public */
|
||||
|
||||
@@ -82,7 +86,6 @@ hesiod_init(void **context) {
|
||||
|
||||
ctx->LHS = NULL;
|
||||
ctx->RHS = NULL;
|
||||
ctx->res = NULL;
|
||||
/* Set default query classes. */
|
||||
ctx->classes[0] = C_IN;
|
||||
ctx->classes[1] = C_HS;
|
||||
@@ -131,11 +134,6 @@ hesiod_init(void **context) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (res_ninit(ctx->res) < 0)
|
||||
goto cleanup;
|
||||
#endif
|
||||
|
||||
*context = ctx;
|
||||
return (0);
|
||||
|
||||
@@ -152,12 +150,8 @@ hesiod_end(void *context) {
|
||||
struct hesiod_p *ctx = (struct hesiod_p *) context;
|
||||
int save_errno = errno;
|
||||
|
||||
if (ctx->res)
|
||||
res_nclose(ctx->res);
|
||||
free(ctx->RHS);
|
||||
free(ctx->LHS);
|
||||
if (ctx->res && ctx->free_res)
|
||||
(*ctx->free_res)(ctx->res);
|
||||
free(ctx);
|
||||
__set_errno(save_errno);
|
||||
}
|
||||
@@ -232,10 +226,6 @@ hesiod_resolve(void *context, const char *name, const char *type) {
|
||||
|
||||
if (bindname == NULL)
|
||||
return (NULL);
|
||||
if (init(ctx) == -1) {
|
||||
free(bindname);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
retvec = get_txt_records(ctx, ctx->classes[0], bindname);
|
||||
|
||||
@@ -365,13 +355,13 @@ get_txt_records(struct hesiod_p *ctx, int class, const char *name) {
|
||||
/*
|
||||
* Construct the query and send it.
|
||||
*/
|
||||
n = res_nmkquery(ctx->res, QUERY, name, class, T_TXT, NULL, 0,
|
||||
n = res_mkquery(QUERY, name, class, T_TXT, NULL, 0,
|
||||
NULL, qbuf, MAX_HESRESP);
|
||||
if (n < 0) {
|
||||
__set_errno(EMSGSIZE);
|
||||
return (NULL);
|
||||
}
|
||||
n = res_nsend(ctx->res, qbuf, n, abuf, MAX_HESRESP);
|
||||
n = res_send(qbuf, n, abuf, MAX_HESRESP);
|
||||
if (n < 0) {
|
||||
__set_errno(ECONNREFUSED);
|
||||
return (NULL);
|
||||
@@ -421,7 +411,7 @@ get_txt_records(struct hesiod_p *ctx, int class, const char *name) {
|
||||
cp += INT16SZ + INT32SZ; /* skip the ttl, too */
|
||||
rr.dlen = ns_get16(cp);
|
||||
cp += INT16SZ;
|
||||
if (cp + rr.dlen > eom) {
|
||||
if (rr.dlen == 0 || cp + rr.dlen > eom) {
|
||||
__set_errno(EMSGSIZE);
|
||||
goto cleanup;
|
||||
}
|
||||
@@ -464,44 +454,3 @@ get_txt_records(struct hesiod_p *ctx, int class, const char *name) {
|
||||
free(list);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
struct __res_state *
|
||||
__hesiod_res_get(void *context) {
|
||||
struct hesiod_p *ctx = context;
|
||||
|
||||
if (!ctx->res) {
|
||||
struct __res_state *res;
|
||||
res = (struct __res_state *)calloc(1, sizeof *res);
|
||||
if (res == NULL)
|
||||
return (NULL);
|
||||
__hesiod_res_set(ctx, res, free);
|
||||
}
|
||||
|
||||
return (ctx->res);
|
||||
}
|
||||
|
||||
void
|
||||
__hesiod_res_set(void *context, struct __res_state *res,
|
||||
void (*free_res)(void *)) {
|
||||
struct hesiod_p *ctx = context;
|
||||
|
||||
if (ctx->res && ctx->free_res) {
|
||||
res_nclose(ctx->res);
|
||||
(*ctx->free_res)(ctx->res);
|
||||
}
|
||||
|
||||
ctx->res = res;
|
||||
ctx->free_res = free_res;
|
||||
}
|
||||
|
||||
static int
|
||||
init(struct hesiod_p *ctx) {
|
||||
|
||||
if (!ctx->res && !__hesiod_res_get(ctx))
|
||||
return (-1);
|
||||
|
||||
if (__res_maybe_init (ctx->res, 0) == -1)
|
||||
return (-1);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
+22
-12
@@ -1,3 +1,20 @@
|
||||
/* Copyright (C) 1997-2016 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1996,1999 by Internet Software Consortium.
|
||||
*
|
||||
@@ -19,22 +36,15 @@
|
||||
* This file is primarily maintained by <tytso@mit.edu> and <ghudson@mit.edu>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* $BINDId: hesiod.h,v 1.7 1999/01/08 19:22:45 vixie Exp $
|
||||
*/
|
||||
|
||||
#ifndef _HESIOD_H_INCLUDED
|
||||
#define _HESIOD_H_INCLUDED
|
||||
|
||||
int hesiod_init (void **context);
|
||||
void hesiod_end (void *context);
|
||||
int hesiod_init (void **context) attribute_hidden;
|
||||
void hesiod_end (void *context) attribute_hidden;
|
||||
char * hesiod_to_bind (void *context, const char *name,
|
||||
const char *type);
|
||||
const char *type) attribute_hidden;
|
||||
char ** hesiod_resolve (void *context, const char *name,
|
||||
const char *type);
|
||||
void hesiod_free_list (void *context, char **list);
|
||||
struct __res_state * __hesiod_res_get (void *context);
|
||||
void __hesiod_res_set (void *context, struct __res_state *,
|
||||
void (*)(void *));
|
||||
const char *type) attribute_hidden;
|
||||
void hesiod_free_list (void *context, char **list) attribute_hidden;
|
||||
|
||||
#endif /*_HESIOD_H_INCLUDED*/
|
||||
|
||||
+17
-9
@@ -1,3 +1,20 @@
|
||||
/* Copyright (C) 1997-2016 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1996,1999 by Internet Software Consortium.
|
||||
*
|
||||
@@ -19,10 +36,6 @@
|
||||
* This file is primarily maintained by <tytso@mit.edu> and <ghudson@mit.edu>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* $BINDId: hesiod_p.h,v 1.9 1999/01/08 19:24:39 vixie Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
* hesiod_p.h -- private definitions for the hesiod library
|
||||
*/
|
||||
@@ -36,11 +49,6 @@
|
||||
struct hesiod_p {
|
||||
char * LHS; /* normally ".ns" */
|
||||
char * RHS; /* AKA the default hesiod domain */
|
||||
struct __res_state * res; /* resolver context */
|
||||
void (*free_res)(void *);
|
||||
void (*res_set)(struct hesiod_p *, struct __res_state *,
|
||||
void (*)(void *));
|
||||
struct __res_state * (*res_get)(struct hesiod_p *);
|
||||
int classes[2]; /* The class search order. */
|
||||
};
|
||||
|
||||
|
||||
@@ -26,8 +26,6 @@
|
||||
#include <string.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
#include "nss_hesiod.h"
|
||||
|
||||
/* Get the declaration of the parser function. */
|
||||
#define ENTNAME grent
|
||||
#define STRUCTURE group
|
||||
@@ -58,8 +56,7 @@ lookup (const char *name, const char *type, struct group *grp,
|
||||
size_t len;
|
||||
int olderr = errno;
|
||||
|
||||
context = _nss_hesiod_init ();
|
||||
if (context == NULL)
|
||||
if (hesiod_init (&context) < 0)
|
||||
return NSS_STATUS_UNAVAIL;
|
||||
|
||||
list = hesiod_resolve (context, name, type);
|
||||
@@ -179,8 +176,7 @@ _nss_hesiod_initgroups_dyn (const char *user, gid_t group, long int *start,
|
||||
gid_t *groups = *groupsp;
|
||||
int save_errno;
|
||||
|
||||
context = _nss_hesiod_init ();
|
||||
if (context == NULL)
|
||||
if (hesiod_init (&context) < 0)
|
||||
return NSS_STATUS_UNAVAIL;
|
||||
|
||||
list = hesiod_resolve (context, user, "grplist");
|
||||
|
||||
@@ -25,8 +25,6 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "nss_hesiod.h"
|
||||
|
||||
/* Declare a parser for Hesiod protocol entries. Although the format
|
||||
of the entries is identical to those in /etc/protocols, here is no
|
||||
predefined parser for us to use. */
|
||||
@@ -68,8 +66,7 @@ lookup (const char *name, const char *type, struct protoent *proto,
|
||||
int found;
|
||||
int olderr = errno;
|
||||
|
||||
context = _nss_hesiod_init ();
|
||||
if (context == NULL)
|
||||
if (hesiod_init (&context) < 0)
|
||||
return NSS_STATUS_UNAVAIL;
|
||||
|
||||
list = hesiod_resolve (context, name, type);
|
||||
|
||||
@@ -24,8 +24,6 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "nss_hesiod.h"
|
||||
|
||||
/* Get the declaration of the parser function. */
|
||||
#define ENTNAME pwent
|
||||
#define STRUCTURE passwd
|
||||
@@ -56,8 +54,7 @@ lookup (const char *name, const char *type, struct passwd *pwd,
|
||||
size_t len;
|
||||
int olderr = errno;
|
||||
|
||||
context = _nss_hesiod_init ();
|
||||
if (context == NULL)
|
||||
if (hesiod_init (&context) < 0)
|
||||
return NSS_STATUS_UNAVAIL;
|
||||
|
||||
list = hesiod_resolve (context, name, type);
|
||||
|
||||
@@ -25,8 +25,6 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "nss_hesiod.h"
|
||||
|
||||
/* Hesiod uses a format for service entries that differs from the
|
||||
traditional format. We therefore declare our own parser. */
|
||||
|
||||
@@ -69,8 +67,7 @@ lookup (const char *name, const char *type, const char *protocol,
|
||||
int found;
|
||||
int olderr = errno;
|
||||
|
||||
context = _nss_hesiod_init ();
|
||||
if (context == NULL)
|
||||
if (hesiod_init (&context) < 0)
|
||||
return NSS_STATUS_UNAVAIL;
|
||||
|
||||
list = hesiod_resolve (context, name, type);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#ifndef _PRINTF_H
|
||||
|
||||
#include <stdio-common/printf.h>
|
||||
#include <xlocale.h>
|
||||
|
||||
/* Now define the internal interfaces. */
|
||||
extern int __printf_fphex (FILE *, const struct printf_info *,
|
||||
@@ -8,5 +9,8 @@ extern int __printf_fphex (FILE *, const struct printf_info *,
|
||||
extern int __printf_fp (FILE *, const struct printf_info *,
|
||||
const void *const *);
|
||||
libc_hidden_proto (__printf_fp)
|
||||
extern int __printf_fp_l (FILE *, locale_t, const struct printf_info *,
|
||||
const void *const *);
|
||||
libc_hidden_proto (__printf_fp_l)
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
#include <misc/sys/auxv.h>
|
||||
+3
-1
@@ -50,7 +50,7 @@ aux := check_pf check_native ifreq
|
||||
|
||||
tests := htontest test_ifindex tst-ntoa tst-ether_aton tst-network \
|
||||
tst-gethnm test-ifaddrs bug-if1 test-inet6_opt tst-ether_line \
|
||||
tst-getni1 tst-getni2 tst-inet6_rth tst-checks
|
||||
tst-getni1 tst-getni2 tst-inet6_rth tst-checks tst-sockaddr
|
||||
|
||||
include ../Rules
|
||||
|
||||
@@ -84,6 +84,8 @@ CFLAGS-either_hton.c = -fexceptions
|
||||
CFLAGS-getnetgrent.c = -fexceptions
|
||||
CFLAGS-getnetgrent_r.c = -fexceptions
|
||||
|
||||
CFLAGS-tst-sockaddr.c = -fno-strict-aliasing
|
||||
|
||||
endif
|
||||
|
||||
ifeq ($(build-static-nss),yes)
|
||||
|
||||
+346
-252
@@ -1,3 +1,21 @@
|
||||
/* Convert socket address to string using Name Service Switch modules.
|
||||
Copyright (C) 1997-2016 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
/* The Inner Net License, Version 2.00
|
||||
|
||||
The author(s) grant permission for redistribution and use in source and
|
||||
@@ -169,20 +187,322 @@ nrl_domainname (void)
|
||||
return domain;
|
||||
};
|
||||
|
||||
/* Copy a string to a destination buffer with length checking. Return
|
||||
EAI_OVERFLOW if the buffer is not large enough, and 0 on
|
||||
success. */
|
||||
static int
|
||||
checked_copy (char *dest, size_t destlen, const char *source)
|
||||
{
|
||||
size_t source_length = strlen (source);
|
||||
if (source_length + 1 > destlen)
|
||||
return EAI_OVERFLOW;
|
||||
memcpy (dest, source, source_length + 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Helper function for CHECKED_SNPRINTF below. */
|
||||
static int
|
||||
check_sprintf_result (int result, size_t destlen)
|
||||
{
|
||||
if (result < 0)
|
||||
return EAI_SYSTEM;
|
||||
if ((size_t) result >= destlen)
|
||||
/* If ret == destlen, there was no room for the terminating NUL
|
||||
character. */
|
||||
return EAI_OVERFLOW;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Format a string in the destination buffer. Return 0 on success,
|
||||
EAI_OVERFLOW in case the buffer is too small, or EAI_SYSTEM on any
|
||||
other error. */
|
||||
#define CHECKED_SNPRINTF(dest, destlen, format, ...) \
|
||||
check_sprintf_result \
|
||||
(__snprintf (dest, destlen, format, __VA_ARGS__), destlen)
|
||||
|
||||
/* Convert host name, AF_INET/AF_INET6 case, name only. */
|
||||
static int
|
||||
gni_host_inet_name (struct scratch_buffer *tmpbuf,
|
||||
const struct sockaddr *sa, socklen_t addrlen,
|
||||
char *host, socklen_t hostlen, int flags)
|
||||
{
|
||||
int herrno;
|
||||
struct hostent th;
|
||||
struct hostent *h = NULL;
|
||||
if (sa->sa_family == AF_INET6)
|
||||
{
|
||||
const struct sockaddr_in6 *sin6p = (const struct sockaddr_in6 *) sa;
|
||||
while (__gethostbyaddr_r (&sin6p->sin6_addr, sizeof(struct in6_addr),
|
||||
AF_INET6, &th, tmpbuf->data, tmpbuf->length,
|
||||
&h, &herrno))
|
||||
if (herrno == NETDB_INTERNAL && errno == ERANGE)
|
||||
{
|
||||
if (!scratch_buffer_grow (tmpbuf))
|
||||
{
|
||||
__set_h_errno (herrno);
|
||||
return EAI_MEMORY;
|
||||
}
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
const struct sockaddr_in *sinp = (const struct sockaddr_in *) sa;
|
||||
while (__gethostbyaddr_r (&sinp->sin_addr, sizeof(struct in_addr),
|
||||
AF_INET, &th, tmpbuf->data, tmpbuf->length,
|
||||
&h, &herrno))
|
||||
if (herrno == NETDB_INTERNAL && errno == ERANGE)
|
||||
{
|
||||
if (!scratch_buffer_grow (tmpbuf))
|
||||
{
|
||||
__set_h_errno (herrno);
|
||||
return EAI_MEMORY;
|
||||
}
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
if (h == NULL)
|
||||
{
|
||||
if (herrno == NETDB_INTERNAL)
|
||||
{
|
||||
__set_h_errno (herrno);
|
||||
return EAI_SYSTEM;
|
||||
}
|
||||
if (herrno == TRY_AGAIN)
|
||||
{
|
||||
__set_h_errno (herrno);
|
||||
return EAI_AGAIN;
|
||||
}
|
||||
}
|
||||
|
||||
if (h)
|
||||
{
|
||||
char *c;
|
||||
if ((flags & NI_NOFQDN)
|
||||
&& (c = nrl_domainname ())
|
||||
&& (c = strstr (h->h_name, c))
|
||||
&& (c != h->h_name) && (*(--c) == '.'))
|
||||
/* Terminate the string after the prefix. */
|
||||
*c = '\0';
|
||||
|
||||
#ifdef HAVE_LIBIDN
|
||||
/* If requested, convert from the IDN format. */
|
||||
if (flags & NI_IDN)
|
||||
{
|
||||
int idn_flags = 0;
|
||||
if (flags & NI_IDN_ALLOW_UNASSIGNED)
|
||||
idn_flags |= IDNA_ALLOW_UNASSIGNED;
|
||||
if (flags & NI_IDN_USE_STD3_ASCII_RULES)
|
||||
idn_flags |= IDNA_USE_STD3_ASCII_RULES;
|
||||
|
||||
char *out;
|
||||
int rc = __idna_to_unicode_lzlz (h->h_name, &out,
|
||||
idn_flags);
|
||||
if (rc != IDNA_SUCCESS)
|
||||
{
|
||||
if (rc == IDNA_MALLOC_ERROR)
|
||||
return EAI_MEMORY;
|
||||
if (rc == IDNA_DLOPEN_ERROR)
|
||||
return EAI_SYSTEM;
|
||||
return EAI_IDN_ENCODE;
|
||||
}
|
||||
|
||||
if (out != h->h_name)
|
||||
{
|
||||
h->h_name = strdupa (out);
|
||||
free (out);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
size_t len = strlen (h->h_name) + 1;
|
||||
if (len > hostlen)
|
||||
return EAI_OVERFLOW;
|
||||
|
||||
memcpy (host, h->h_name, len);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return EAI_NONAME;
|
||||
}
|
||||
|
||||
/* Convert host name, AF_INET/AF_INET6 case, numeric conversion. */
|
||||
static int
|
||||
gni_host_inet_numeric (struct scratch_buffer *tmpbuf,
|
||||
const struct sockaddr *sa, socklen_t addrlen,
|
||||
char *host, socklen_t hostlen, int flags)
|
||||
{
|
||||
if (sa->sa_family == AF_INET6)
|
||||
{
|
||||
const struct sockaddr_in6 *sin6p = (const struct sockaddr_in6 *) sa;
|
||||
if (inet_ntop (AF_INET6, &sin6p->sin6_addr, host, hostlen) == NULL)
|
||||
return EAI_OVERFLOW;
|
||||
|
||||
uint32_t scopeid = sin6p->sin6_scope_id;
|
||||
if (scopeid != 0)
|
||||
{
|
||||
size_t used_hostlen = __strnlen (host, hostlen);
|
||||
/* Location of the scope string in the host buffer. */
|
||||
char *scope_start = host + used_hostlen;
|
||||
size_t scope_length = hostlen - used_hostlen;
|
||||
|
||||
if (IN6_IS_ADDR_LINKLOCAL (&sin6p->sin6_addr)
|
||||
|| IN6_IS_ADDR_MC_LINKLOCAL (&sin6p->sin6_addr))
|
||||
{
|
||||
char scopebuf[IFNAMSIZ];
|
||||
if (if_indextoname (scopeid, scopebuf) != NULL)
|
||||
return CHECKED_SNPRINTF
|
||||
(scope_start, scope_length,
|
||||
"%c%s", SCOPE_DELIMITER, scopebuf);
|
||||
}
|
||||
return CHECKED_SNPRINTF
|
||||
(scope_start, scope_length, "%c%u", SCOPE_DELIMITER, scopeid);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const struct sockaddr_in *sinp = (const struct sockaddr_in *) sa;
|
||||
if (inet_ntop (AF_INET, &sinp->sin_addr, host, hostlen) == NULL)
|
||||
return EAI_OVERFLOW;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Convert AF_INET or AF_INET6 socket address, host part. */
|
||||
static int
|
||||
gni_host_inet (struct scratch_buffer *tmpbuf,
|
||||
const struct sockaddr *sa, socklen_t addrlen,
|
||||
char *host, socklen_t hostlen, int flags)
|
||||
{
|
||||
if (!(flags & NI_NUMERICHOST))
|
||||
{
|
||||
int result = gni_host_inet_name
|
||||
(tmpbuf, sa, addrlen, host, hostlen, flags);
|
||||
if (result != EAI_NONAME)
|
||||
return result;
|
||||
}
|
||||
|
||||
if (flags & NI_NAMEREQD)
|
||||
return EAI_NONAME;
|
||||
else
|
||||
return gni_host_inet_numeric
|
||||
(tmpbuf, sa, addrlen, host, hostlen, flags);
|
||||
}
|
||||
|
||||
/* Convert AF_LOCAL socket address, host part. */
|
||||
static int
|
||||
gni_host_local (struct scratch_buffer *tmpbuf,
|
||||
const struct sockaddr *sa, socklen_t addrlen,
|
||||
char *host, socklen_t hostlen, int flags)
|
||||
{
|
||||
if (!(flags & NI_NUMERICHOST))
|
||||
{
|
||||
struct utsname utsname;
|
||||
if (uname (&utsname) == 0)
|
||||
return checked_copy (host, hostlen, utsname.nodename);
|
||||
}
|
||||
|
||||
if (flags & NI_NAMEREQD)
|
||||
return EAI_NONAME;
|
||||
|
||||
return checked_copy (host, hostlen, "localhost");
|
||||
}
|
||||
|
||||
/* Convert the host part of an AF_LOCAK socket address. */
|
||||
static int
|
||||
gni_host (struct scratch_buffer *tmpbuf,
|
||||
const struct sockaddr *sa, socklen_t addrlen,
|
||||
char *host, socklen_t hostlen, int flags)
|
||||
{
|
||||
switch (sa->sa_family)
|
||||
{
|
||||
case AF_INET:
|
||||
case AF_INET6:
|
||||
return gni_host_inet (tmpbuf, sa, addrlen, host, hostlen, flags);
|
||||
|
||||
case AF_LOCAL:
|
||||
return gni_host_local (tmpbuf, sa, addrlen, host, hostlen, flags);
|
||||
|
||||
default:
|
||||
return EAI_FAMILY;
|
||||
}
|
||||
}
|
||||
|
||||
/* Convert service to string, AF_INET and AF_INET6 variant. */
|
||||
static int
|
||||
gni_serv_inet (struct scratch_buffer *tmpbuf,
|
||||
const struct sockaddr *sa, socklen_t addrlen,
|
||||
char *serv, socklen_t servlen, int flags)
|
||||
{
|
||||
_Static_assert
|
||||
(offsetof (struct sockaddr_in, sin_port)
|
||||
== offsetof (struct sockaddr_in6, sin6_port)
|
||||
&& sizeof (((struct sockaddr_in) {}).sin_port) == sizeof (in_port_t)
|
||||
&& sizeof (((struct sockaddr_in6) {}).sin6_port) == sizeof (in_port_t),
|
||||
"AF_INET and AF_INET6 port consistency");
|
||||
const struct sockaddr_in *sinp = (const struct sockaddr_in *) sa;
|
||||
if (!(flags & NI_NUMERICSERV))
|
||||
{
|
||||
struct servent *s, ts;
|
||||
int e;
|
||||
while ((e = __getservbyport_r (sinp->sin_port,
|
||||
((flags & NI_DGRAM)
|
||||
? "udp" : "tcp"), &ts,
|
||||
tmpbuf->data, tmpbuf->length, &s)))
|
||||
{
|
||||
if (e == ERANGE)
|
||||
{
|
||||
if (!scratch_buffer_grow (tmpbuf))
|
||||
return EAI_MEMORY;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
if (s)
|
||||
return checked_copy (serv, servlen, s->s_name);
|
||||
/* Fall through to numeric conversion. */
|
||||
}
|
||||
return CHECKED_SNPRINTF (serv, servlen, "%d", ntohs (sinp->sin_port));
|
||||
}
|
||||
|
||||
/* Convert service to string, AF_LOCAL variant. */
|
||||
static int
|
||||
gni_serv_local (struct scratch_buffer *tmpbuf,
|
||||
const struct sockaddr *sa, socklen_t addrlen,
|
||||
char *serv, socklen_t servlen, int flags)
|
||||
{
|
||||
return checked_copy
|
||||
(serv, servlen, ((const struct sockaddr_un *) sa)->sun_path);
|
||||
}
|
||||
|
||||
/* Convert service to string, dispatching to the implementations
|
||||
above. */
|
||||
static int
|
||||
gni_serv (struct scratch_buffer *tmpbuf,
|
||||
const struct sockaddr *sa, socklen_t addrlen,
|
||||
char *serv, socklen_t servlen, int flags)
|
||||
{
|
||||
switch (sa->sa_family)
|
||||
{
|
||||
case AF_INET:
|
||||
case AF_INET6:
|
||||
return gni_serv_inet (tmpbuf, sa, addrlen, serv, servlen, flags);
|
||||
case AF_LOCAL:
|
||||
return gni_serv_local (tmpbuf, sa, addrlen, serv, servlen, flags);
|
||||
default:
|
||||
return EAI_FAMILY;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
getnameinfo (const struct sockaddr *sa, socklen_t addrlen, char *host,
|
||||
socklen_t hostlen, char *serv, socklen_t servlen,
|
||||
int flags)
|
||||
{
|
||||
int serrno = errno;
|
||||
int herrno;
|
||||
struct hostent th;
|
||||
int ok = 0;
|
||||
struct scratch_buffer tmpbuf;
|
||||
|
||||
scratch_buffer_init (&tmpbuf);
|
||||
|
||||
if (flags & ~(NI_NUMERICHOST|NI_NUMERICSERV|NI_NOFQDN|NI_NAMEREQD|NI_DGRAM
|
||||
#ifdef HAVE_LIBIDN
|
||||
|NI_IDN|NI_IDN_ALLOW_UNASSIGNED|NI_IDN_USE_STD3_ASCII_RULES
|
||||
@@ -214,256 +534,30 @@ getnameinfo (const struct sockaddr *sa, socklen_t addrlen, char *host,
|
||||
return EAI_FAMILY;
|
||||
}
|
||||
|
||||
struct scratch_buffer tmpbuf;
|
||||
scratch_buffer_init (&tmpbuf);
|
||||
|
||||
if (host != NULL && hostlen > 0)
|
||||
switch (sa->sa_family)
|
||||
{
|
||||
case AF_INET:
|
||||
case AF_INET6:
|
||||
if (!(flags & NI_NUMERICHOST))
|
||||
{
|
||||
struct hostent *h = NULL;
|
||||
if (sa->sa_family == AF_INET6)
|
||||
{
|
||||
while (__gethostbyaddr_r ((const void *) &(((const struct sockaddr_in6 *) sa)->sin6_addr),
|
||||
sizeof(struct in6_addr),
|
||||
AF_INET6, &th,
|
||||
tmpbuf.data, tmpbuf.length,
|
||||
&h, &herrno))
|
||||
if (herrno == NETDB_INTERNAL && errno == ERANGE)
|
||||
{
|
||||
if (!scratch_buffer_grow (&tmpbuf))
|
||||
{
|
||||
__set_h_errno (herrno);
|
||||
return EAI_MEMORY;
|
||||
}
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
while (__gethostbyaddr_r ((const void *) &(((const struct sockaddr_in *)sa)->sin_addr),
|
||||
sizeof(struct in_addr),
|
||||
AF_INET, &th,
|
||||
tmpbuf.data, tmpbuf.length,
|
||||
&h, &herrno))
|
||||
if (herrno == NETDB_INTERNAL && errno == ERANGE)
|
||||
{
|
||||
if (!scratch_buffer_grow (&tmpbuf))
|
||||
{
|
||||
__set_h_errno (herrno);
|
||||
return EAI_MEMORY;
|
||||
}
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
if (h == NULL)
|
||||
{
|
||||
if (herrno == NETDB_INTERNAL)
|
||||
{
|
||||
__set_h_errno (herrno);
|
||||
return EAI_SYSTEM;
|
||||
}
|
||||
if (herrno == TRY_AGAIN)
|
||||
{
|
||||
__set_h_errno (herrno);
|
||||
return EAI_AGAIN;
|
||||
}
|
||||
}
|
||||
|
||||
if (h)
|
||||
{
|
||||
char *c;
|
||||
if ((flags & NI_NOFQDN)
|
||||
&& (c = nrl_domainname ())
|
||||
&& (c = strstr (h->h_name, c))
|
||||
&& (c != h->h_name) && (*(--c) == '.'))
|
||||
/* Terminate the string after the prefix. */
|
||||
*c = '\0';
|
||||
|
||||
#ifdef HAVE_LIBIDN
|
||||
/* If requested, convert from the IDN format. */
|
||||
if (flags & NI_IDN)
|
||||
{
|
||||
int idn_flags = 0;
|
||||
if (flags & NI_IDN_ALLOW_UNASSIGNED)
|
||||
idn_flags |= IDNA_ALLOW_UNASSIGNED;
|
||||
if (flags & NI_IDN_USE_STD3_ASCII_RULES)
|
||||
idn_flags |= IDNA_USE_STD3_ASCII_RULES;
|
||||
|
||||
char *out;
|
||||
int rc = __idna_to_unicode_lzlz (h->h_name, &out,
|
||||
idn_flags);
|
||||
if (rc != IDNA_SUCCESS)
|
||||
{
|
||||
if (rc == IDNA_MALLOC_ERROR)
|
||||
return EAI_MEMORY;
|
||||
if (rc == IDNA_DLOPEN_ERROR)
|
||||
return EAI_SYSTEM;
|
||||
return EAI_IDN_ENCODE;
|
||||
}
|
||||
|
||||
if (out != h->h_name)
|
||||
{
|
||||
h->h_name = strdupa (out);
|
||||
free (out);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
size_t len = strlen (h->h_name) + 1;
|
||||
if (len > hostlen)
|
||||
return EAI_OVERFLOW;
|
||||
|
||||
memcpy (host, h->h_name, len);
|
||||
|
||||
ok = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ok)
|
||||
{
|
||||
if (flags & NI_NAMEREQD)
|
||||
{
|
||||
__set_errno (serrno);
|
||||
return EAI_NONAME;
|
||||
}
|
||||
else
|
||||
{
|
||||
const char *c;
|
||||
if (sa->sa_family == AF_INET6)
|
||||
{
|
||||
const struct sockaddr_in6 *sin6p;
|
||||
uint32_t scopeid;
|
||||
|
||||
sin6p = (const struct sockaddr_in6 *) sa;
|
||||
|
||||
c = inet_ntop (AF_INET6,
|
||||
(const void *) &sin6p->sin6_addr, host, hostlen);
|
||||
scopeid = sin6p->sin6_scope_id;
|
||||
if (scopeid != 0)
|
||||
{
|
||||
/* Buffer is >= IFNAMSIZ+1. */
|
||||
char scopebuf[IFNAMSIZ + 1];
|
||||
char *scopeptr;
|
||||
int ni_numericscope = 0;
|
||||
size_t real_hostlen = __strnlen (host, hostlen);
|
||||
size_t scopelen = 0;
|
||||
|
||||
scopebuf[0] = SCOPE_DELIMITER;
|
||||
scopebuf[1] = '\0';
|
||||
scopeptr = &scopebuf[1];
|
||||
|
||||
if (IN6_IS_ADDR_LINKLOCAL (&sin6p->sin6_addr)
|
||||
|| IN6_IS_ADDR_MC_LINKLOCAL (&sin6p->sin6_addr))
|
||||
{
|
||||
if (if_indextoname (scopeid, scopeptr) == NULL)
|
||||
++ni_numericscope;
|
||||
else
|
||||
scopelen = strlen (scopebuf);
|
||||
}
|
||||
else
|
||||
++ni_numericscope;
|
||||
|
||||
if (ni_numericscope)
|
||||
scopelen = 1 + __snprintf (scopeptr,
|
||||
(scopebuf
|
||||
+ sizeof scopebuf
|
||||
- scopeptr),
|
||||
"%u", scopeid);
|
||||
|
||||
if (real_hostlen + scopelen + 1 > hostlen)
|
||||
/* Signal the buffer is too small. This is
|
||||
what inet_ntop does. */
|
||||
c = NULL;
|
||||
else
|
||||
memcpy (host + real_hostlen, scopebuf, scopelen + 1);
|
||||
}
|
||||
}
|
||||
else
|
||||
c = inet_ntop (AF_INET,
|
||||
(const void *) &(((const struct sockaddr_in *) sa)->sin_addr),
|
||||
host, hostlen);
|
||||
if (c == NULL)
|
||||
return EAI_OVERFLOW;
|
||||
}
|
||||
ok = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case AF_LOCAL:
|
||||
if (!(flags & NI_NUMERICHOST))
|
||||
{
|
||||
struct utsname utsname;
|
||||
|
||||
if (!uname (&utsname))
|
||||
{
|
||||
strncpy (host, utsname.nodename, hostlen);
|
||||
break;
|
||||
};
|
||||
};
|
||||
|
||||
if (flags & NI_NAMEREQD)
|
||||
{
|
||||
__set_errno (serrno);
|
||||
return EAI_NONAME;
|
||||
}
|
||||
|
||||
strncpy (host, "localhost", hostlen);
|
||||
break;
|
||||
|
||||
default:
|
||||
return EAI_FAMILY;
|
||||
{
|
||||
int result = gni_host (&tmpbuf, sa, addrlen, host, hostlen, flags);
|
||||
if (result != 0)
|
||||
{
|
||||
scratch_buffer_free (&tmpbuf);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
if (serv && (servlen > 0))
|
||||
switch (sa->sa_family)
|
||||
{
|
||||
case AF_INET:
|
||||
case AF_INET6:
|
||||
if (!(flags & NI_NUMERICSERV))
|
||||
{
|
||||
struct servent *s, ts;
|
||||
int e;
|
||||
while ((e = __getservbyport_r (((const struct sockaddr_in *) sa)->sin_port,
|
||||
((flags & NI_DGRAM)
|
||||
? "udp" : "tcp"), &ts,
|
||||
tmpbuf.data, tmpbuf.length, &s)))
|
||||
{
|
||||
if (e == ERANGE)
|
||||
{
|
||||
if (!scratch_buffer_grow (&tmpbuf))
|
||||
return EAI_MEMORY;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
if (s)
|
||||
{
|
||||
strncpy (serv, s->s_name, servlen);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (__snprintf (serv, servlen, "%d",
|
||||
ntohs (((const struct sockaddr_in *) sa)->sin_port))
|
||||
+ 1 > servlen)
|
||||
return EAI_OVERFLOW;
|
||||
|
||||
break;
|
||||
|
||||
case AF_LOCAL:
|
||||
strncpy (serv, ((const struct sockaddr_un *) sa)->sun_path, servlen);
|
||||
break;
|
||||
{
|
||||
int result = gni_serv (&tmpbuf, sa, addrlen, serv, servlen, flags);
|
||||
if (result != 0)
|
||||
{
|
||||
scratch_buffer_free (&tmpbuf);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
if (host && (hostlen > 0))
|
||||
host[hostlen-1] = 0;
|
||||
if (serv && (servlen > 0))
|
||||
serv[servlen-1] = 0;
|
||||
errno = serrno;
|
||||
scratch_buffer_free (&tmpbuf);
|
||||
return 0;
|
||||
}
|
||||
libc_hidden_def (getnameinfo)
|
||||
|
||||
@@ -0,0 +1,125 @@
|
||||
/* Tests for socket address type definitions.
|
||||
Copyright (C) 2016 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public License as
|
||||
published by the Free Software Foundation; either version 2.1 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; see the file COPYING.LIB. If
|
||||
not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
|
||||
/* This is a copy of the previous definition of struct
|
||||
sockaddr_storage. It is not equal to the old value of _SS_SIZE
|
||||
(128) on all architectures. We must stay compatible with the old
|
||||
definition. */
|
||||
|
||||
#define OLD_REFERENCE_SIZE 128
|
||||
#define OLD_PADSIZE (OLD_REFERENCE_SIZE - (2 * sizeof (__ss_aligntype)))
|
||||
struct sockaddr_storage_old
|
||||
{
|
||||
__SOCKADDR_COMMON (old_);
|
||||
__ss_aligntype old_align;
|
||||
char old_padding[OLD_PADSIZE];
|
||||
};
|
||||
|
||||
static bool errors;
|
||||
|
||||
static void
|
||||
check (bool ok, const char *message)
|
||||
{
|
||||
if (!ok)
|
||||
{
|
||||
printf ("error: failed check: %s\n", message);
|
||||
errors = true;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
check (OLD_REFERENCE_SIZE >= _SS_SIZE,
|
||||
"old target size is not smaller than actual size");
|
||||
check (sizeof (struct sockaddr_storage_old)
|
||||
== sizeof (struct sockaddr_storage),
|
||||
"old and new sizes match");
|
||||
check (__alignof (struct sockaddr_storage_old)
|
||||
== __alignof (struct sockaddr_storage),
|
||||
"old and new alignment matches");
|
||||
check (offsetof (struct sockaddr_storage_old, old_family)
|
||||
== offsetof (struct sockaddr_storage, ss_family),
|
||||
"old and new family offsets match");
|
||||
check (sizeof (struct sockaddr_storage) == _SS_SIZE,
|
||||
"struct sockaddr_storage size");
|
||||
|
||||
/* Check for lack of holes in the struct definition. */
|
||||
check (offsetof (struct sockaddr_storage, __ss_padding)
|
||||
== __SOCKADDR_COMMON_SIZE,
|
||||
"implicit padding before explicit padding");
|
||||
check (offsetof (struct sockaddr_storage, __ss_align)
|
||||
== __SOCKADDR_COMMON_SIZE
|
||||
+ sizeof (((struct sockaddr_storage) {}).__ss_padding),
|
||||
"implicit padding before explicit padding");
|
||||
|
||||
/* Check for POSIX compatibility requirements between struct
|
||||
sockaddr_storage and struct sockaddr_un. */
|
||||
check (sizeof (struct sockaddr_storage) >= sizeof (struct sockaddr_un),
|
||||
"sockaddr_storage is at least as large as sockaddr_un");
|
||||
check (__alignof (struct sockaddr_storage)
|
||||
>= __alignof (struct sockaddr_un),
|
||||
"sockaddr_storage is at least as aligned as sockaddr_un");
|
||||
check (offsetof (struct sockaddr_storage, ss_family)
|
||||
== offsetof (struct sockaddr_un, sun_family),
|
||||
"family offsets match");
|
||||
|
||||
/* Check that the compiler preserves bit patterns in aggregate
|
||||
copies. Based on <https://gcc.gnu.org/PR71120>. */
|
||||
check (sizeof (struct sockaddr_storage) >= sizeof (struct sockaddr_in),
|
||||
"sockaddr_storage is at least as large as sockaddr_in");
|
||||
{
|
||||
struct sockaddr_storage addr;
|
||||
memset (&addr, 0, sizeof (addr));
|
||||
{
|
||||
struct sockaddr_in *sinp = (struct sockaddr_in *)&addr;
|
||||
sinp->sin_family = AF_INET;
|
||||
sinp->sin_addr.s_addr = htonl (INADDR_LOOPBACK);
|
||||
sinp->sin_port = htons (80);
|
||||
}
|
||||
struct sockaddr_storage copy;
|
||||
copy = addr;
|
||||
|
||||
struct sockaddr_storage *p = malloc (sizeof (*p));
|
||||
if (p == NULL)
|
||||
{
|
||||
printf ("error: malloc: %m\n");
|
||||
return 1;
|
||||
}
|
||||
*p = copy;
|
||||
const struct sockaddr_in *sinp = (const struct sockaddr_in *)p;
|
||||
check (sinp->sin_family == AF_INET, "sin_family");
|
||||
check (sinp->sin_addr.s_addr == htonl (INADDR_LOOPBACK), "sin_addr");
|
||||
check (sinp->sin_port == htons (80), "sin_port");
|
||||
free (p);
|
||||
}
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
#define TEST_FUNCTION do_test ()
|
||||
#include "../test-skeleton.c"
|
||||
@@ -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
|
||||
|
||||
+17
-15
@@ -50,16 +50,14 @@ fmemopen_read (void *cookie, char *b, size_t s)
|
||||
|
||||
if (c->pos + s > c->maxpos)
|
||||
{
|
||||
if ((size_t) c->pos == c->maxpos)
|
||||
return 0;
|
||||
s = c->size - c->pos;
|
||||
s = c->maxpos - c->pos;
|
||||
if ((size_t) c->pos > c->maxpos)
|
||||
s = 0;
|
||||
}
|
||||
|
||||
memcpy (b, &(c->buffer[c->pos]), s);
|
||||
|
||||
c->pos += s;
|
||||
if ((size_t) c->pos > c->maxpos)
|
||||
c->maxpos = c->pos;
|
||||
|
||||
return s;
|
||||
}
|
||||
@@ -70,28 +68,29 @@ fmemopen_write (void *cookie, const char *b, size_t s)
|
||||
{
|
||||
fmemopen_cookie_t *c = (fmemopen_cookie_t *) cookie;;
|
||||
_IO_off64_t pos = c->append ? c->maxpos : c->pos;
|
||||
int addnullc;
|
||||
int addnullc = (s == 0 || b[s - 1] != '\0');
|
||||
|
||||
addnullc = (s == 0 || b[s - 1] != '\0');
|
||||
|
||||
if (pos + s + addnullc > c->size)
|
||||
if (pos + s > c->size)
|
||||
{
|
||||
if ((size_t) (c->pos + addnullc) >= c->size)
|
||||
{
|
||||
__set_errno (ENOSPC);
|
||||
return 0;
|
||||
}
|
||||
s = c->size - pos - addnullc;
|
||||
s = c->size - pos;
|
||||
}
|
||||
|
||||
memcpy (&(c->buffer[pos]), b, s);
|
||||
|
||||
pos += s;
|
||||
if ((size_t) pos > c->maxpos)
|
||||
c->pos = pos + s;
|
||||
if ((size_t) c->pos > c->maxpos)
|
||||
{
|
||||
c->maxpos = pos;
|
||||
if (addnullc)
|
||||
c->maxpos = c->pos;
|
||||
if (c->maxpos < c->size && addnullc)
|
||||
c->buffer[c->maxpos] = '\0';
|
||||
/* A null byte is written in a stream open for update iff it fits. */
|
||||
else if (c->append == 0 && addnullc != 0)
|
||||
c->buffer[c->size-1] = '\0';
|
||||
}
|
||||
|
||||
return s;
|
||||
@@ -123,7 +122,10 @@ fmemopen_seek (void *cookie, _IO_off64_t *p, int w)
|
||||
}
|
||||
|
||||
if (np < 0 || (size_t) np > c->size)
|
||||
return -1;
|
||||
{
|
||||
__set_errno (EINVAL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
*p = c->pos = np;
|
||||
|
||||
|
||||
+35
-14
@@ -43,25 +43,29 @@ static _IO_ssize_t
|
||||
_IO_cookie_read (_IO_FILE *fp, void *buf, _IO_ssize_t size)
|
||||
{
|
||||
struct _IO_cookie_file *cfile = (struct _IO_cookie_file *) fp;
|
||||
cookie_read_function_t *read_cb = cfile->__io_functions.read;
|
||||
PTR_DEMANGLE (read_cb);
|
||||
|
||||
if (cfile->__io_functions.read == NULL)
|
||||
if (read_cb == NULL)
|
||||
return -1;
|
||||
|
||||
return cfile->__io_functions.read (cfile->__cookie, buf, size);
|
||||
return read_cb (cfile->__cookie, buf, size);
|
||||
}
|
||||
|
||||
static _IO_ssize_t
|
||||
_IO_cookie_write (_IO_FILE *fp, const void *buf, _IO_ssize_t size)
|
||||
{
|
||||
struct _IO_cookie_file *cfile = (struct _IO_cookie_file *) fp;
|
||||
cookie_write_function_t *write_cb = cfile->__io_functions.write;
|
||||
PTR_DEMANGLE (write_cb);
|
||||
|
||||
if (cfile->__io_functions.write == NULL)
|
||||
if (write_cb == NULL)
|
||||
{
|
||||
fp->_flags |= _IO_ERR_SEEN;
|
||||
return 0;
|
||||
}
|
||||
|
||||
_IO_ssize_t n = cfile->__io_functions.write (cfile->__cookie, buf, size);
|
||||
_IO_ssize_t n = write_cb (cfile->__cookie, buf, size);
|
||||
if (n < size)
|
||||
fp->_flags |= _IO_ERR_SEEN;
|
||||
|
||||
@@ -72,9 +76,11 @@ static _IO_off64_t
|
||||
_IO_cookie_seek (_IO_FILE *fp, _IO_off64_t offset, int dir)
|
||||
{
|
||||
struct _IO_cookie_file *cfile = (struct _IO_cookie_file *) fp;
|
||||
cookie_seek_function_t *seek_cb = cfile->__io_functions.seek;
|
||||
PTR_DEMANGLE (seek_cb);
|
||||
|
||||
return ((cfile->__io_functions.seek == NULL
|
||||
|| (cfile->__io_functions.seek (cfile->__cookie, &offset, dir)
|
||||
return ((seek_cb == NULL
|
||||
|| (seek_cb (cfile->__cookie, &offset, dir)
|
||||
== -1)
|
||||
|| offset == (_IO_off64_t) -1)
|
||||
? _IO_pos_BAD : offset);
|
||||
@@ -84,11 +90,13 @@ static int
|
||||
_IO_cookie_close (_IO_FILE *fp)
|
||||
{
|
||||
struct _IO_cookie_file *cfile = (struct _IO_cookie_file *) fp;
|
||||
cookie_close_function_t *close_cb = cfile->__io_functions.close;
|
||||
PTR_DEMANGLE (close_cb);
|
||||
|
||||
if (cfile->__io_functions.close == NULL)
|
||||
if (close_cb == NULL)
|
||||
return 0;
|
||||
|
||||
return cfile->__io_functions.close (cfile->__cookie);
|
||||
return close_cb (cfile->__cookie);
|
||||
}
|
||||
|
||||
|
||||
@@ -126,6 +134,19 @@ static const struct _IO_jump_t _IO_cookie_jumps = {
|
||||
};
|
||||
|
||||
|
||||
/* Copy the callbacks from SOURCE to *TARGET, with pointer
|
||||
mangling. */
|
||||
static void
|
||||
set_callbacks (_IO_cookie_io_functions_t *target,
|
||||
_IO_cookie_io_functions_t source)
|
||||
{
|
||||
PTR_MANGLE (source.read);
|
||||
PTR_MANGLE (source.write);
|
||||
PTR_MANGLE (source.seek);
|
||||
PTR_MANGLE (source.close);
|
||||
*target = source;
|
||||
}
|
||||
|
||||
void
|
||||
_IO_cookie_init (struct _IO_cookie_file *cfile, int read_write,
|
||||
void *cookie, _IO_cookie_io_functions_t io_functions)
|
||||
@@ -134,7 +155,7 @@ _IO_cookie_init (struct _IO_cookie_file *cfile, int read_write,
|
||||
_IO_JUMPS (&cfile->__fp) = &_IO_cookie_jumps;
|
||||
|
||||
cfile->__cookie = cookie;
|
||||
cfile->__io_functions = io_functions;
|
||||
set_callbacks (&cfile->__io_functions, io_functions);
|
||||
|
||||
_IO_file_init (&cfile->__fp);
|
||||
|
||||
@@ -205,14 +226,14 @@ attribute_compat_text_section
|
||||
_IO_old_cookie_seek (_IO_FILE *fp, _IO_off64_t offset, int dir)
|
||||
{
|
||||
struct _IO_cookie_file *cfile = (struct _IO_cookie_file *) fp;
|
||||
int (*seek) (_IO_FILE *, _IO_off_t, int);
|
||||
int ret;
|
||||
int (*seek_cb) (_IO_FILE *, _IO_off_t, int)
|
||||
= (int (*) (_IO_FILE *, _IO_off_t, int)) cfile->__io_functions.seek;;
|
||||
PTR_DEMANGLE (seek_cb);
|
||||
|
||||
seek = (int (*)(_IO_FILE *, _IO_off_t, int)) cfile->__io_functions.seek;
|
||||
if (seek == NULL)
|
||||
if (seek_cb == NULL)
|
||||
return _IO_pos_BAD;
|
||||
|
||||
ret = seek (cfile->__cookie, offset, dir);
|
||||
int ret = seek_cb (cfile->__cookie, offset, dir);
|
||||
|
||||
return (ret == -1) ? _IO_pos_BAD : ret;
|
||||
}
|
||||
|
||||
@@ -299,6 +299,27 @@ extern __thread struct __locale_data *const *_nl_current_##category \
|
||||
|
||||
#endif
|
||||
|
||||
/* Extract CATEGORY locale's string for ITEM. */
|
||||
static inline const char *
|
||||
_nl_lookup (locale_t l, int category, int item)
|
||||
{
|
||||
return l->__locales[category]->values[_NL_ITEM_INDEX (item)].string;
|
||||
}
|
||||
|
||||
/* Extract CATEGORY locale's wide string for ITEM. */
|
||||
static inline const wchar_t *
|
||||
_nl_lookup_wstr (locale_t l, int category, int item)
|
||||
{
|
||||
return (wchar_t *) l->__locales[category]
|
||||
->values[_NL_ITEM_INDEX (item)].wstr;
|
||||
}
|
||||
|
||||
/* Extract the CATEGORY locale's word for ITEM. */
|
||||
static inline uint32_t
|
||||
_nl_lookup_word (locale_t l, int category, int item)
|
||||
{
|
||||
return l->__locales[category]->values[_NL_ITEM_INDEX (item)].word;
|
||||
}
|
||||
|
||||
/* Default search path if no LOCPATH environment variable. */
|
||||
extern const char _nl_default_locale_path[] attribute_hidden;
|
||||
|
||||
@@ -1,3 +1,24 @@
|
||||
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-02-19 Florian Weimer <fweimer@redhat.com>
|
||||
|
||||
[BZ #19581]
|
||||
* locales/sr_ME (date_fmt): Remove newline.
|
||||
* locales/sr_RS (date_fmt): Likewise.
|
||||
* locales/sr_RS@latin (date_fmt): Likewise.
|
||||
|
||||
2016-02-08 Mike Frysinger <vapier@gentoo.org>
|
||||
|
||||
* locales/an_ES: Convert to UTF-8 encodings.
|
||||
|
||||
@@ -144,8 +144,8 @@ copy "en_DK"
|
||||
END LC_CTYPE
|
||||
|
||||
LC_MESSAGES
|
||||
yesexpr "<U005E><U005B><U0064><U0044><U0079><U0059><U005D><U002A><U002E>"
|
||||
noexpr "<U005E><U005B><U006E><U004E><U005D><U002A><U002E>"
|
||||
yesexpr "<U005E><U005B><U0064><U0044><U0079><U0059><U005D>"
|
||||
noexpr "<U005E><U005B><U006E><U004E><U005D>"
|
||||
END LC_MESSAGES
|
||||
|
||||
LC_MONETARY
|
||||
|
||||
@@ -1035,9 +1035,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>"
|
||||
@@ -1096,8 +1096,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>
|
||||
@@ -1119,6 +1119,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>
|
||||
#
|
||||
@@ -4545,6 +4551,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>
|
||||
#
|
||||
@@ -7245,6 +7257,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
|
||||
@@ -7273,6 +7286,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
|
||||
@@ -7283,6 +7297,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
|
||||
@@ -7298,20 +7313,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
|
||||
|
||||
@@ -119,7 +119,7 @@ am_pm "";""
|
||||
t_fmt_ampm "<U0025><U0054>"
|
||||
date_fmt "<U0025><U0061><U002c><U0020><U0025><U0065><U002E><U0020>/
|
||||
<U0025><U0062><U0020><U0025><U0059><U002E><U0020><U0020><U0025><U0048>/
|
||||
<U003A><U0025><U004D><U003A><U0025><U0053><U0020><U0025><U005A><U000A>"
|
||||
<U003A><U0025><U004D><U003A><U0025><U0053><U0020><U0025><U005A>"
|
||||
week 7;19971130;4
|
||||
first_weekday 2
|
||||
first_workday 2
|
||||
|
||||
@@ -300,7 +300,7 @@ am_pm "";""
|
||||
t_fmt_ampm "<U0025><U0054>"
|
||||
date_fmt "<U0025><U0061><U002C><U0020><U0025><U0065><U002E><U0020>/
|
||||
<U0025><U0062><U0020><U0025><U0059><U002E><U0020><U0020><U0025><U0048>/
|
||||
<U003A><U0025><U004D><U003A><U0025><U0053><U0020><U0025><U005A><U000A>"
|
||||
<U003A><U0025><U004D><U003A><U0025><U0053><U0020><U0025><U005A>"
|
||||
week 7;19971130;4
|
||||
first_weekday 2
|
||||
first_workday 2
|
||||
|
||||
@@ -120,7 +120,7 @@ am_pm "";""
|
||||
t_fmt_ampm "<U0025><U0054>"
|
||||
date_fmt "<U0025><U0061><U002c><U0020><U0025><U0065><U002E><U0020>/
|
||||
<U0025><U0062><U0020><U0025><U0059><U002E><U0020><U0020><U0025><U0048>/
|
||||
<U003A><U0025><U004D><U003A><U0025><U0053><U0020><U0025><U005A><U000A>"
|
||||
<U003A><U0025><U004D><U003A><U0025><U0053><U0020><U0025><U005A>"
|
||||
week 7;19971130;4
|
||||
first_weekday 2
|
||||
first_workday 2
|
||||
|
||||
+6
-7
@@ -29,7 +29,8 @@ tests := mallocbug tst-malloc tst-valloc tst-calloc tst-obstack \
|
||||
tst-malloc-usable tst-realloc tst-posix_memalign \
|
||||
tst-pvalloc tst-memalign tst-mallopt tst-scratch_buffer \
|
||||
tst-malloc-backtrace tst-malloc-thread-exit \
|
||||
tst-malloc-thread-fail
|
||||
tst-malloc-thread-fail tst-malloc-fork-deadlock \
|
||||
tst-mallocfork2
|
||||
test-srcs = tst-mtrace
|
||||
|
||||
routines = malloc morecore mcheck mtrace obstack \
|
||||
@@ -46,12 +47,10 @@ extra-libs-others = $(extra-libs)
|
||||
libmemusage-routines = memusage
|
||||
libmemusage-inhibit-o = $(filter-out .os,$(object-suffixes))
|
||||
|
||||
$(objpfx)tst-malloc-backtrace: $(common-objpfx)nptl/libpthread.so \
|
||||
$(common-objpfx)nptl/libpthread_nonshared.a
|
||||
$(objpfx)tst-malloc-thread-exit: $(common-objpfx)nptl/libpthread.so \
|
||||
$(common-objpfx)nptl/libpthread_nonshared.a
|
||||
$(objpfx)tst-malloc-thread-fail: $(common-objpfx)nptl/libpthread.so \
|
||||
$(common-objpfx)nptl/libpthread_nonshared.a
|
||||
$(objpfx)tst-malloc-backtrace: $(shared-thread-library)
|
||||
$(objpfx)tst-malloc-thread-exit: $(shared-thread-library)
|
||||
$(objpfx)tst-malloc-thread-fail: $(shared-thread-library)
|
||||
$(objpfx)tst-malloc-fork-deadlock: $(shared-thread-library)
|
||||
|
||||
# These should be removed by `make clean'.
|
||||
extra-objs = mcheck-init.o libmcheck.a
|
||||
|
||||
+65
-169
@@ -130,149 +130,43 @@ int __malloc_initialized = -1;
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef NO_THREADS
|
||||
|
||||
/* atfork support. */
|
||||
|
||||
static void *(*save_malloc_hook)(size_t __size, const void *);
|
||||
static void (*save_free_hook) (void *__ptr, const void *);
|
||||
static void *save_arena;
|
||||
/* The following three functions are called around fork from a
|
||||
multi-threaded process. We do not use the general fork handler
|
||||
mechanism to make sure that our handlers are the last ones being
|
||||
called, so that other fork handlers can use the malloc
|
||||
subsystem. */
|
||||
|
||||
# ifdef ATFORK_MEM
|
||||
ATFORK_MEM;
|
||||
# endif
|
||||
|
||||
/* Magic value for the thread-specific arena pointer when
|
||||
malloc_atfork() is in use. */
|
||||
|
||||
# define ATFORK_ARENA_PTR ((void *) -1)
|
||||
|
||||
/* The following hooks are used while the `atfork' handling mechanism
|
||||
is active. */
|
||||
|
||||
static void *
|
||||
malloc_atfork (size_t sz, const void *caller)
|
||||
void
|
||||
internal_function
|
||||
__malloc_fork_lock_parent (void)
|
||||
{
|
||||
void *victim;
|
||||
|
||||
if (thread_arena == ATFORK_ARENA_PTR)
|
||||
{
|
||||
/* We are the only thread that may allocate at all. */
|
||||
if (save_malloc_hook != malloc_check)
|
||||
{
|
||||
return _int_malloc (&main_arena, sz);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (top_check () < 0)
|
||||
return 0;
|
||||
|
||||
victim = _int_malloc (&main_arena, sz + 1);
|
||||
return mem2mem_check (victim, sz);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Suspend the thread until the `atfork' handlers have completed.
|
||||
By that time, the hooks will have been reset as well, so that
|
||||
mALLOc() can be used again. */
|
||||
(void) mutex_lock (&list_lock);
|
||||
(void) mutex_unlock (&list_lock);
|
||||
return __libc_malloc (sz);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
free_atfork (void *mem, const void *caller)
|
||||
{
|
||||
mstate ar_ptr;
|
||||
mchunkptr p; /* chunk corresponding to mem */
|
||||
|
||||
if (mem == 0) /* free(0) has no effect */
|
||||
return;
|
||||
|
||||
p = mem2chunk (mem); /* do not bother to replicate free_check here */
|
||||
|
||||
if (chunk_is_mmapped (p)) /* release mmapped memory. */
|
||||
{
|
||||
munmap_chunk (p);
|
||||
return;
|
||||
}
|
||||
|
||||
ar_ptr = arena_for_chunk (p);
|
||||
_int_free (ar_ptr, p, thread_arena == ATFORK_ARENA_PTR);
|
||||
}
|
||||
|
||||
|
||||
/* Counter for number of times the list is locked by the same thread. */
|
||||
static unsigned int atfork_recursive_cntr;
|
||||
|
||||
/* The following two functions are registered via thread_atfork() to
|
||||
make sure that the mutexes remain in a consistent state in the
|
||||
fork()ed version of a thread. Also adapt the malloc and free hooks
|
||||
temporarily, because the `atfork' handler mechanism may use
|
||||
malloc/free internally (e.g. in LinuxThreads). */
|
||||
|
||||
static void
|
||||
ptmalloc_lock_all (void)
|
||||
{
|
||||
mstate ar_ptr;
|
||||
|
||||
if (__malloc_initialized < 1)
|
||||
return;
|
||||
|
||||
/* We do not acquire free_list_lock here because we completely
|
||||
reconstruct free_list in ptmalloc_unlock_all2. */
|
||||
reconstruct free_list in __malloc_fork_unlock_child. */
|
||||
|
||||
if (mutex_trylock (&list_lock))
|
||||
{
|
||||
if (thread_arena == ATFORK_ARENA_PTR)
|
||||
/* This is the same thread which already locks the global list.
|
||||
Just bump the counter. */
|
||||
goto out;
|
||||
(void) mutex_lock (&list_lock);
|
||||
|
||||
/* This thread has to wait its turn. */
|
||||
(void) mutex_lock (&list_lock);
|
||||
}
|
||||
for (ar_ptr = &main_arena;; )
|
||||
for (mstate ar_ptr = &main_arena;; )
|
||||
{
|
||||
(void) mutex_lock (&ar_ptr->mutex);
|
||||
ar_ptr = ar_ptr->next;
|
||||
if (ar_ptr == &main_arena)
|
||||
break;
|
||||
}
|
||||
save_malloc_hook = __malloc_hook;
|
||||
save_free_hook = __free_hook;
|
||||
__malloc_hook = malloc_atfork;
|
||||
__free_hook = free_atfork;
|
||||
/* Only the current thread may perform malloc/free calls now.
|
||||
save_arena will be reattached to the current thread, in
|
||||
ptmalloc_lock_all, so save_arena->attached_threads is not
|
||||
updated. */
|
||||
save_arena = thread_arena;
|
||||
thread_arena = ATFORK_ARENA_PTR;
|
||||
out:
|
||||
++atfork_recursive_cntr;
|
||||
}
|
||||
|
||||
static void
|
||||
ptmalloc_unlock_all (void)
|
||||
void
|
||||
internal_function
|
||||
__malloc_fork_unlock_parent (void)
|
||||
{
|
||||
mstate ar_ptr;
|
||||
|
||||
if (__malloc_initialized < 1)
|
||||
return;
|
||||
|
||||
if (--atfork_recursive_cntr != 0)
|
||||
return;
|
||||
|
||||
/* Replace ATFORK_ARENA_PTR with save_arena.
|
||||
save_arena->attached_threads was not changed in ptmalloc_lock_all
|
||||
and is still correct. */
|
||||
thread_arena = save_arena;
|
||||
__malloc_hook = save_malloc_hook;
|
||||
__free_hook = save_free_hook;
|
||||
for (ar_ptr = &main_arena;; )
|
||||
for (mstate ar_ptr = &main_arena;; )
|
||||
{
|
||||
(void) mutex_unlock (&ar_ptr->mutex);
|
||||
ar_ptr = ar_ptr->next;
|
||||
@@ -282,35 +176,23 @@ ptmalloc_unlock_all (void)
|
||||
(void) mutex_unlock (&list_lock);
|
||||
}
|
||||
|
||||
# ifdef __linux__
|
||||
|
||||
/* In NPTL, unlocking a mutex in the child process after a
|
||||
fork() is currently unsafe, whereas re-initializing it is safe and
|
||||
does not leak resources. Therefore, a special atfork handler is
|
||||
installed for the child. */
|
||||
|
||||
static void
|
||||
ptmalloc_unlock_all2 (void)
|
||||
void
|
||||
internal_function
|
||||
__malloc_fork_unlock_child (void)
|
||||
{
|
||||
mstate ar_ptr;
|
||||
|
||||
if (__malloc_initialized < 1)
|
||||
return;
|
||||
|
||||
thread_arena = save_arena;
|
||||
__malloc_hook = save_malloc_hook;
|
||||
__free_hook = save_free_hook;
|
||||
|
||||
/* Push all arenas to the free list, except save_arena, which is
|
||||
/* Push all arenas to the free list, except thread_arena, which is
|
||||
attached to the current thread. */
|
||||
mutex_init (&free_list_lock);
|
||||
if (save_arena != NULL)
|
||||
((mstate) save_arena)->attached_threads = 1;
|
||||
if (thread_arena != NULL)
|
||||
thread_arena->attached_threads = 1;
|
||||
free_list = NULL;
|
||||
for (ar_ptr = &main_arena;; )
|
||||
for (mstate ar_ptr = &main_arena;; )
|
||||
{
|
||||
mutex_init (&ar_ptr->mutex);
|
||||
if (ar_ptr != save_arena)
|
||||
if (ar_ptr != thread_arena)
|
||||
{
|
||||
/* This arena is no longer attached to any thread. */
|
||||
ar_ptr->attached_threads = 0;
|
||||
@@ -323,15 +205,8 @@ ptmalloc_unlock_all2 (void)
|
||||
}
|
||||
|
||||
mutex_init (&list_lock);
|
||||
atfork_recursive_cntr = 0;
|
||||
}
|
||||
|
||||
# else
|
||||
|
||||
# define ptmalloc_unlock_all2 ptmalloc_unlock_all
|
||||
# endif
|
||||
#endif /* !NO_THREADS */
|
||||
|
||||
/* Initialization routine. */
|
||||
#include <string.h>
|
||||
extern char **_environ;
|
||||
@@ -400,7 +275,6 @@ ptmalloc_init (void)
|
||||
#endif
|
||||
|
||||
thread_arena = &main_arena;
|
||||
thread_atfork (ptmalloc_lock_all, ptmalloc_unlock_all, ptmalloc_unlock_all2);
|
||||
const char *s = NULL;
|
||||
if (__glibc_likely (_environ != NULL))
|
||||
{
|
||||
@@ -475,14 +349,6 @@ ptmalloc_init (void)
|
||||
__malloc_initialized = 1;
|
||||
}
|
||||
|
||||
/* There are platforms (e.g. Hurd) with a link-time hook mechanism. */
|
||||
#ifdef thread_atfork_static
|
||||
thread_atfork_static (ptmalloc_lock_all, ptmalloc_unlock_all, \
|
||||
ptmalloc_unlock_all2)
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* Managing heaps and arenas (for concurrent threads) */
|
||||
|
||||
#if MALLOC_DEBUG > 1
|
||||
@@ -831,7 +697,8 @@ _int_new_arena (size_t size)
|
||||
limit is reached). At this point, some arena has to be attached
|
||||
to two threads. We could acquire the arena lock before list_lock
|
||||
to make it less likely that reused_arena picks this new arena,
|
||||
but this could result in a deadlock with ptmalloc_lock_all. */
|
||||
but this could result in a deadlock with
|
||||
__malloc_fork_lock_parent. */
|
||||
|
||||
(void) mutex_lock (&a->mutex);
|
||||
|
||||
@@ -839,8 +706,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)
|
||||
{
|
||||
@@ -855,7 +721,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);
|
||||
}
|
||||
@@ -872,6 +739,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. */
|
||||
@@ -908,27 +795,36 @@ reused_arena (mstate avoid_arena)
|
||||
{
|
||||
result = result->next;
|
||||
if (result == begin)
|
||||
break;
|
||||
/* We looped around the arena list. We could not find any
|
||||
arena that was either not corrupted or not the one we
|
||||
wanted to avoid. */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* We could not find any arena that was either not corrupted or not the one
|
||||
we wanted to avoid. */
|
||||
if (result == begin || result == avoid_arena)
|
||||
return NULL;
|
||||
|
||||
/* No arena available without contention. Wait for the next in line. */
|
||||
LIBC_PROBE (memory_arena_reuse_wait, 3, &result->mutex, result, avoid_arena);
|
||||
(void) mutex_lock (&result->mutex);
|
||||
|
||||
out:
|
||||
/* Attach the arena to the current thread. 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);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
/* Internal declarations for malloc, for use within libc.
|
||||
Copyright (C) 2016 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public License as
|
||||
published by the Free Software Foundation; either version 2.1 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; see the file COPYING.LIB. If
|
||||
not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef _MALLOC_PRIVATE_H
|
||||
#define _MALLOC_PRIVATE_H
|
||||
|
||||
/* Called in the parent process before a fork. */
|
||||
void __malloc_fork_lock_parent (void) internal_function attribute_hidden;
|
||||
|
||||
/* Called in the parent process after a fork. */
|
||||
void __malloc_fork_unlock_parent (void) internal_function attribute_hidden;
|
||||
|
||||
/* Called in the child process after a fork. */
|
||||
void __malloc_fork_unlock_child (void) internal_function attribute_hidden;
|
||||
|
||||
|
||||
#endif /* _MALLOC_PRIVATE_H */
|
||||
+1
-4
@@ -244,6 +244,7 @@
|
||||
/* For ALIGN_UP et. al. */
|
||||
#include <libc-internal.h>
|
||||
|
||||
#include <malloc/malloc-internal.h>
|
||||
|
||||
/*
|
||||
Debugging:
|
||||
@@ -1074,10 +1075,6 @@ static void* realloc_check(void* oldmem, size_t bytes,
|
||||
const void *caller);
|
||||
static void* memalign_check(size_t alignment, size_t bytes,
|
||||
const void *caller);
|
||||
#ifndef NO_THREADS
|
||||
static void* malloc_atfork(size_t sz, const void *caller);
|
||||
static void free_atfork(void* mem, const void *caller);
|
||||
#endif
|
||||
|
||||
/* ------------------ MMAP support ------------------ */
|
||||
|
||||
|
||||
@@ -0,0 +1,220 @@
|
||||
/* Test concurrent fork, getline, and fflush (NULL).
|
||||
Copyright (C) 2016 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public License as
|
||||
published by the Free Software Foundation; either version 2.1 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; see the file COPYING.LIB. If
|
||||
not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <pthread.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <malloc.h>
|
||||
#include <time.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
|
||||
static int do_test (void);
|
||||
#define TEST_FUNCTION do_test ()
|
||||
#include "../test-skeleton.c"
|
||||
|
||||
enum {
|
||||
/* Number of threads which call fork. */
|
||||
fork_thread_count = 4,
|
||||
/* Number of threads which call getline (and, indirectly,
|
||||
malloc). */
|
||||
read_thread_count = 8,
|
||||
};
|
||||
|
||||
static bool termination_requested;
|
||||
|
||||
static void *
|
||||
fork_thread_function (void *closure)
|
||||
{
|
||||
while (!__atomic_load_n (&termination_requested, __ATOMIC_RELAXED))
|
||||
{
|
||||
pid_t pid = fork ();
|
||||
if (pid < 0)
|
||||
{
|
||||
printf ("error: fork: %m\n");
|
||||
abort ();
|
||||
}
|
||||
else if (pid == 0)
|
||||
_exit (17);
|
||||
|
||||
int status;
|
||||
if (waitpid (pid, &status, 0) < 0)
|
||||
{
|
||||
printf ("error: waitpid: %m\n");
|
||||
abort ();
|
||||
}
|
||||
if (!WIFEXITED (status) || WEXITSTATUS (status) != 17)
|
||||
{
|
||||
printf ("error: waitpid returned invalid status: %d\n", status);
|
||||
abort ();
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static char *file_to_read;
|
||||
|
||||
static void *
|
||||
read_thread_function (void *closure)
|
||||
{
|
||||
FILE *f = fopen (file_to_read, "r");
|
||||
if (f == NULL)
|
||||
{
|
||||
printf ("error: fopen (%s): %m\n", file_to_read);
|
||||
abort ();
|
||||
}
|
||||
|
||||
while (!__atomic_load_n (&termination_requested, __ATOMIC_RELAXED))
|
||||
{
|
||||
rewind (f);
|
||||
char *line = NULL;
|
||||
size_t line_allocated = 0;
|
||||
ssize_t ret = getline (&line, &line_allocated, f);
|
||||
if (ret < 0)
|
||||
{
|
||||
printf ("error: getline: %m\n");
|
||||
abort ();
|
||||
}
|
||||
free (line);
|
||||
}
|
||||
fclose (f);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void *
|
||||
flushall_thread_function (void *closure)
|
||||
{
|
||||
while (!__atomic_load_n (&termination_requested, __ATOMIC_RELAXED))
|
||||
if (fflush (NULL) != 0)
|
||||
{
|
||||
printf ("error: fflush (NULL): %m\n");
|
||||
abort ();
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
create_threads (pthread_t *threads, size_t count, void *(*func) (void *))
|
||||
{
|
||||
for (size_t i = 0; i < count; ++i)
|
||||
{
|
||||
int ret = pthread_create (threads + i, NULL, func, NULL);
|
||||
if (ret != 0)
|
||||
{
|
||||
errno = ret;
|
||||
printf ("error: pthread_create: %m\n");
|
||||
abort ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
join_threads (pthread_t *threads, size_t count)
|
||||
{
|
||||
for (size_t i = 0; i < count; ++i)
|
||||
{
|
||||
int ret = pthread_join (threads[i], NULL);
|
||||
if (ret != 0)
|
||||
{
|
||||
errno = ret;
|
||||
printf ("error: pthread_join: %m\n");
|
||||
abort ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Create a file which consists of a single long line, and assigns
|
||||
file_to_read. The hope is that this triggers an allocation in
|
||||
getline which needs a lock. */
|
||||
static void
|
||||
create_file_with_large_line (void)
|
||||
{
|
||||
int fd = create_temp_file ("bug19431-large-line", &file_to_read);
|
||||
if (fd < 0)
|
||||
{
|
||||
printf ("error: create_temp_file: %m\n");
|
||||
abort ();
|
||||
}
|
||||
FILE *f = fdopen (fd, "w+");
|
||||
if (f == NULL)
|
||||
{
|
||||
printf ("error: fdopen: %m\n");
|
||||
abort ();
|
||||
}
|
||||
for (int i = 0; i < 50000; ++i)
|
||||
fputc ('x', f);
|
||||
fputc ('\n', f);
|
||||
if (ferror (f))
|
||||
{
|
||||
printf ("error: fputc: %m\n");
|
||||
abort ();
|
||||
}
|
||||
if (fclose (f) != 0)
|
||||
{
|
||||
printf ("error: fclose: %m\n");
|
||||
abort ();
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
/* Make sure that we do not exceed the arena limit with the number
|
||||
of threads we configured. */
|
||||
if (mallopt (M_ARENA_MAX, 400) == 0)
|
||||
{
|
||||
printf ("error: mallopt (M_ARENA_MAX) failed\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Leave some room for shutting down all threads gracefully. */
|
||||
int timeout = 3;
|
||||
if (timeout > TIMEOUT)
|
||||
timeout = TIMEOUT - 1;
|
||||
|
||||
create_file_with_large_line ();
|
||||
|
||||
pthread_t fork_threads[fork_thread_count];
|
||||
create_threads (fork_threads, fork_thread_count, fork_thread_function);
|
||||
pthread_t read_threads[read_thread_count];
|
||||
create_threads (read_threads, read_thread_count, read_thread_function);
|
||||
pthread_t flushall_threads[1];
|
||||
create_threads (flushall_threads, 1, flushall_thread_function);
|
||||
|
||||
struct timespec ts = {timeout, 0};
|
||||
if (nanosleep (&ts, NULL))
|
||||
{
|
||||
printf ("error: error: nanosleep: %m\n");
|
||||
abort ();
|
||||
}
|
||||
|
||||
__atomic_store_n (&termination_requested, true, __ATOMIC_RELAXED);
|
||||
|
||||
join_threads (flushall_threads, 1);
|
||||
join_threads (read_threads, read_thread_count);
|
||||
join_threads (fork_threads, fork_thread_count);
|
||||
|
||||
free (file_to_read);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,220 @@
|
||||
/* Test case for async-signal-safe fork (with respect to malloc).
|
||||
Copyright (C) 2016 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public License as
|
||||
published by the Free Software Foundation; either version 2.1 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; see the file COPYING.LIB. If
|
||||
not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
/* This test will fail if the process is multi-threaded because we
|
||||
only have an async-signal-safe fork in the single-threaded case
|
||||
(where we skip acquiring the malloc heap locks).
|
||||
|
||||
This test only checks async-signal-safety with regards to malloc;
|
||||
other, more rarely-used glibc subsystems could have locks which
|
||||
still make fork unsafe, even in single-threaded processes. */
|
||||
|
||||
#include <errno.h>
|
||||
#include <sched.h>
|
||||
#include <signal.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/wait.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/* How many malloc objects to keep arond. */
|
||||
enum { malloc_objects = 1009 };
|
||||
|
||||
/* The maximum size of an object. */
|
||||
enum { malloc_maximum_size = 70000 };
|
||||
|
||||
/* How many signals need to be delivered before the test exits. */
|
||||
enum { signal_count = 1000 };
|
||||
|
||||
|
||||
/* Process ID of the subprocess which sends SIGUSR1 signals. */
|
||||
static pid_t sigusr1_sender_pid;
|
||||
|
||||
/* Set to 1 if SIGUSR1 is received. Used to detect a signal during
|
||||
malloc/free. */
|
||||
static volatile sig_atomic_t sigusr1_received;
|
||||
|
||||
/* Periodically set to 1, to indicate that the process is making
|
||||
progress. Checked by liveness_signal_handler. */
|
||||
static volatile sig_atomic_t progress_indicator = 1;
|
||||
|
||||
/* Write the message to standard output. Usable from signal
|
||||
handlers. */
|
||||
static void
|
||||
write_message (const char *str)
|
||||
{
|
||||
write (STDOUT_FILENO, str, strlen (str));
|
||||
}
|
||||
|
||||
static void
|
||||
sigusr1_handler (int signo)
|
||||
{
|
||||
/* Let the main program make progress, by temporarily suspending
|
||||
signals from the subprocess. */
|
||||
if (sigusr1_received)
|
||||
return;
|
||||
/* sigusr1_sender_pid might not be initialized in the parent when
|
||||
the first SIGUSR1 signal arrives. */
|
||||
if (sigusr1_sender_pid > 0 && kill (sigusr1_sender_pid, SIGSTOP) != 0)
|
||||
{
|
||||
write_message ("error: kill (SIGSTOP)\n");
|
||||
abort ();
|
||||
}
|
||||
sigusr1_received = 1;
|
||||
|
||||
/* Perform a fork with a trivial subprocess. */
|
||||
pid_t pid = fork ();
|
||||
if (pid == -1)
|
||||
{
|
||||
write_message ("error: fork\n");
|
||||
abort ();
|
||||
}
|
||||
if (pid == 0)
|
||||
_exit (0);
|
||||
int status;
|
||||
int ret = TEMP_FAILURE_RETRY (waitpid (pid, &status, 0));
|
||||
if (ret < 0)
|
||||
{
|
||||
write_message ("error: waitpid\n");
|
||||
abort ();
|
||||
}
|
||||
if (status != 0)
|
||||
{
|
||||
write_message ("error: unexpected exit status from subprocess\n");
|
||||
abort ();
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
liveness_signal_handler (int signo)
|
||||
{
|
||||
if (progress_indicator)
|
||||
progress_indicator = 0;
|
||||
else
|
||||
write_message ("warning: process seems to be stuck\n");
|
||||
}
|
||||
|
||||
static void
|
||||
__attribute__ ((noreturn))
|
||||
signal_sender (int signo, bool sleep)
|
||||
{
|
||||
pid_t target = getppid ();
|
||||
while (true)
|
||||
{
|
||||
if (kill (target, signo) != 0)
|
||||
{
|
||||
dprintf (STDOUT_FILENO, "error: kill: %m\n");
|
||||
abort ();
|
||||
}
|
||||
if (sleep)
|
||||
usleep (1 * 1000 * 1000);
|
||||
else
|
||||
/* Reduce the rate at which we send signals. */
|
||||
sched_yield ();
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
struct sigaction action =
|
||||
{
|
||||
.sa_handler = sigusr1_handler,
|
||||
};
|
||||
sigemptyset (&action.sa_mask);
|
||||
|
||||
if (sigaction (SIGUSR1, &action, NULL) != 0)
|
||||
{
|
||||
printf ("error: sigaction: %m");
|
||||
return 1;
|
||||
}
|
||||
|
||||
action.sa_handler = liveness_signal_handler;
|
||||
if (sigaction (SIGUSR2, &action, NULL) != 0)
|
||||
{
|
||||
printf ("error: sigaction: %m");
|
||||
return 1;
|
||||
}
|
||||
|
||||
pid_t sigusr2_sender_pid = fork ();
|
||||
if (sigusr2_sender_pid == 0)
|
||||
signal_sender (SIGUSR2, true);
|
||||
sigusr1_sender_pid = fork ();
|
||||
if (sigusr1_sender_pid == 0)
|
||||
signal_sender (SIGUSR1, false);
|
||||
|
||||
void *objects[malloc_objects] = {};
|
||||
unsigned signals = 0;
|
||||
unsigned seed = 1;
|
||||
time_t last_report = 0;
|
||||
while (signals < signal_count)
|
||||
{
|
||||
progress_indicator = 1;
|
||||
int slot = rand_r (&seed) % malloc_objects;
|
||||
size_t size = rand_r (&seed) % malloc_maximum_size;
|
||||
if (kill (sigusr1_sender_pid, SIGCONT) != 0)
|
||||
{
|
||||
printf ("error: kill (SIGCONT): %m\n");
|
||||
signal (SIGUSR1, SIG_IGN);
|
||||
kill (sigusr1_sender_pid, SIGKILL);
|
||||
kill (sigusr2_sender_pid, SIGKILL);
|
||||
return 1;
|
||||
}
|
||||
sigusr1_received = false;
|
||||
free (objects[slot]);
|
||||
objects[slot] = malloc (size);
|
||||
if (sigusr1_received)
|
||||
{
|
||||
++signals;
|
||||
time_t current = time (0);
|
||||
if (current != last_report)
|
||||
{
|
||||
printf ("info: SIGUSR1 signal count: %u\n", signals);
|
||||
last_report = current;
|
||||
}
|
||||
}
|
||||
if (objects[slot] == NULL)
|
||||
{
|
||||
printf ("error: malloc: %m\n");
|
||||
signal (SIGUSR1, SIG_IGN);
|
||||
kill (sigusr1_sender_pid, SIGKILL);
|
||||
kill (sigusr2_sender_pid, SIGKILL);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Clean up allocations. */
|
||||
for (int slot = 0; slot < malloc_objects; ++slot)
|
||||
free (objects[slot]);
|
||||
|
||||
/* Terminate the signal-sending subprocess. The SIGUSR1 handler
|
||||
should no longer run because it uses sigusr1_sender_pid. */
|
||||
signal (SIGUSR1, SIG_IGN);
|
||||
kill (sigusr1_sender_pid, SIGKILL);
|
||||
kill (sigusr2_sender_pid, SIGKILL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define TIMEOUT 20
|
||||
|
||||
#define TEST_FUNCTION do_test ()
|
||||
#include "../test-skeleton.c"
|
||||
@@ -0,0 +1,42 @@
|
||||
/* Example for creating a struct dirent object for use with glob.
|
||||
Copyright (C) 2016 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
struct dirent *
|
||||
mkdirent (const char *name)
|
||||
{
|
||||
size_t dirent_size = offsetof (struct dirent, d_name) + 1;
|
||||
size_t name_length = strlen (name);
|
||||
size_t total_size = dirent_size + name_length;
|
||||
if (total_size < dirent_size)
|
||||
{
|
||||
errno = ENOMEM;
|
||||
return NULL;
|
||||
}
|
||||
struct dirent *result = malloc (total_size);
|
||||
if (result == NULL)
|
||||
return NULL;
|
||||
result->d_type = DT_UNKNOWN;
|
||||
result->d_ino = 1; /* Do not skip this entry. */
|
||||
memcpy (result->d_name, name, name_length + 1);
|
||||
return result;
|
||||
}
|
||||
@@ -1051,14 +1051,6 @@ systems that do not support @w{ISO C11}.
|
||||
@c _dl_addr_inside_object ok
|
||||
@c determine_info ok
|
||||
@c __rtld_lock_unlock_recursive (dl_load_lock) @aculock
|
||||
@c thread_atfork @asulock @aculock @acsfd @acsmem
|
||||
@c __register_atfork @asulock @aculock @acsfd @acsmem
|
||||
@c lll_lock (__fork_lock) @asulock @aculock
|
||||
@c fork_handler_alloc @asulock @aculock @acsfd @acsmem
|
||||
@c calloc dup @asulock @aculock @acsfd @acsmem
|
||||
@c __linkin_atfork ok
|
||||
@c catomic_compare_and_exchange_bool_acq ok
|
||||
@c lll_unlock (__fork_lock) @aculock
|
||||
@c *_environ @mtsenv
|
||||
@c next_env_entry ok
|
||||
@c strcspn dup ok
|
||||
|
||||
+38
-1
@@ -237,7 +237,44 @@ function used to read the contents of a directory. It is used if the
|
||||
@code{GLOB_ALTDIRFUNC} bit is set in the flag parameter. The type of
|
||||
this field is @w{@code{struct dirent *(*) (void *)}}.
|
||||
|
||||
This is a GNU extension.
|
||||
An implementation of @code{gl_readdir} needs to initialize the following
|
||||
members of the @code{struct dirent} object:
|
||||
|
||||
@table @code
|
||||
@item d_type
|
||||
This member should be set to the file type of the entry if it is known.
|
||||
Otherwise, the value @code{DT_UNKNOWN} can be used. The @code{glob}
|
||||
function may use the specified file type to avoid callbacks in cases
|
||||
where the file type indicates that the data is not required.
|
||||
|
||||
@item d_ino
|
||||
This member needs to be non-zero, otherwise @code{glob} may skip the
|
||||
current entry and call the @code{gl_readdir} callback function again to
|
||||
retrieve another entry.
|
||||
|
||||
@item d_name
|
||||
This member must be set to the name of the entry. It must be
|
||||
null-terminated.
|
||||
@end table
|
||||
|
||||
The example below shows how to allocate a @code{struct dirent} object
|
||||
containing a given name.
|
||||
|
||||
@smallexample
|
||||
@include mkdirent.c.texi
|
||||
@end smallexample
|
||||
|
||||
The @code{glob} function reads the @code{struct dirent} members listed
|
||||
above and makes a copy of the file name in the @code{d_name} member
|
||||
immediately after the @code{gl_readdir} callback function returns.
|
||||
Future invocations of any of the callback functions may dealloacte or
|
||||
reuse the buffer. It is the responsibility of the caller of the
|
||||
@code{glob} function to allocate and deallocate the buffer, around the
|
||||
call to @code{glob} or using the callback functions. For example, an
|
||||
application could allocate the buffer in the @code{gl_readdir} callback
|
||||
function, and deallocate it in the @code{gl_closedir} callback function.
|
||||
|
||||
The @code{gl_readdir} member is a GNU extension.
|
||||
|
||||
@item gl_opendir
|
||||
The address of an alternative implementation of the @code{opendir}
|
||||
|
||||
+2
-1
@@ -100,7 +100,8 @@ $(inst_libdir)/libm.so: $(common-objpfx)format.lds \
|
||||
cat $<; \
|
||||
echo 'GROUP ( $(slibdir)/libm.so$(libm.so-version) ' \
|
||||
'AS_NEEDED ( $(libdir)/libmvec_nonshared.a $(slibdir)/libmvec.so$(libmvec.so-version) ) )' \
|
||||
) > $@
|
||||
) > $@.new
|
||||
mv -f $@.new $@
|
||||
endif
|
||||
|
||||
# Rules for the test suite.
|
||||
|
||||
@@ -1144,6 +1144,7 @@ cos 0x4.7857dp+68
|
||||
cos -0x1.02e34cp+0
|
||||
cos 0xf.f0274p+4
|
||||
cos 0x3.042d88p+0
|
||||
cos 0x1.8475e5afd4481p+0
|
||||
|
||||
cosh 0
|
||||
cosh -0
|
||||
@@ -3780,6 +3781,7 @@ sin min
|
||||
sin -min
|
||||
sin min_subnorm
|
||||
sin -min_subnorm
|
||||
sin 0x1.8475e5afd4481p+0
|
||||
|
||||
sincos 0
|
||||
sincos -0
|
||||
@@ -3814,6 +3816,7 @@ sincos min
|
||||
sincos -min
|
||||
sincos min_subnorm
|
||||
sincos -min_subnorm
|
||||
sincos 0x1.8475e5afd4481p+0
|
||||
|
||||
sinh 0
|
||||
sinh -0
|
||||
|
||||
@@ -103416,6 +103416,75 @@ cos 0x3.042d88p+0
|
||||
= cos tonearest ldbl-128ibm 0x3.042d88p+0L : -0xf.dfe6f2169e24f276e8027d91bcp-4L : inexact-ok
|
||||
= cos towardzero ldbl-128ibm 0x3.042d88p+0L : -0xf.dfe6f2169e24f276e8027d91b8p-4L : inexact-ok
|
||||
= cos upward ldbl-128ibm 0x3.042d88p+0L : -0xf.dfe6f2169e24f276e8027d91b8p-4L : inexact-ok
|
||||
cos 0x1.8475e5afd4481p+0
|
||||
= cos downward flt-32 0x1.8475e6p+0f : 0xd.a8263p-8f : inexact-ok
|
||||
= cos tonearest flt-32 0x1.8475e6p+0f : 0xd.a8263p-8f : inexact-ok
|
||||
= cos towardzero flt-32 0x1.8475e6p+0f : 0xd.a8263p-8f : inexact-ok
|
||||
= cos upward flt-32 0x1.8475e6p+0f : 0xd.a8264p-8f : inexact-ok
|
||||
= cos downward dbl-64 0x1.8475e6p+0 : 0xd.a8263394be6dp-8 : inexact-ok
|
||||
= cos tonearest dbl-64 0x1.8475e6p+0 : 0xd.a8263394be6dp-8 : inexact-ok
|
||||
= cos towardzero dbl-64 0x1.8475e6p+0 : 0xd.a8263394be6dp-8 : inexact-ok
|
||||
= cos upward dbl-64 0x1.8475e6p+0 : 0xd.a8263394be6d8p-8 : inexact-ok
|
||||
= cos downward ldbl-96-intel 0x1.8475e6p+0L : 0xd.a8263394be6d0e5p-8L : inexact-ok
|
||||
= cos tonearest ldbl-96-intel 0x1.8475e6p+0L : 0xd.a8263394be6d0e6p-8L : inexact-ok
|
||||
= cos towardzero ldbl-96-intel 0x1.8475e6p+0L : 0xd.a8263394be6d0e5p-8L : inexact-ok
|
||||
= cos upward ldbl-96-intel 0x1.8475e6p+0L : 0xd.a8263394be6d0e6p-8L : inexact-ok
|
||||
= cos downward ldbl-96-m68k 0x1.8475e6p+0L : 0xd.a8263394be6d0e5p-8L : inexact-ok
|
||||
= cos tonearest ldbl-96-m68k 0x1.8475e6p+0L : 0xd.a8263394be6d0e6p-8L : inexact-ok
|
||||
= cos towardzero ldbl-96-m68k 0x1.8475e6p+0L : 0xd.a8263394be6d0e5p-8L : inexact-ok
|
||||
= cos upward ldbl-96-m68k 0x1.8475e6p+0L : 0xd.a8263394be6d0e6p-8L : inexact-ok
|
||||
= cos downward ldbl-128 0x1.8475e6p+0L : 0xd.a8263394be6d0e58c1c35a8a3bap-8L : inexact-ok
|
||||
= cos tonearest ldbl-128 0x1.8475e6p+0L : 0xd.a8263394be6d0e58c1c35a8a3bap-8L : inexact-ok
|
||||
= cos towardzero ldbl-128 0x1.8475e6p+0L : 0xd.a8263394be6d0e58c1c35a8a3bap-8L : inexact-ok
|
||||
= cos upward ldbl-128 0x1.8475e6p+0L : 0xd.a8263394be6d0e58c1c35a8a3ba8p-8L : inexact-ok
|
||||
= cos downward ldbl-128ibm 0x1.8475e6p+0L : 0xd.a8263394be6d0e58c1c35a8a38p-8L : inexact-ok
|
||||
= cos tonearest ldbl-128ibm 0x1.8475e6p+0L : 0xd.a8263394be6d0e58c1c35a8a3cp-8L : inexact-ok
|
||||
= cos towardzero ldbl-128ibm 0x1.8475e6p+0L : 0xd.a8263394be6d0e58c1c35a8a38p-8L : inexact-ok
|
||||
= cos upward ldbl-128ibm 0x1.8475e6p+0L : 0xd.a8263394be6d0e58c1c35a8a3cp-8L : inexact-ok
|
||||
= cos downward flt-32 0x1.8475e4p+0f : 0xd.a8283p-8f : inexact-ok
|
||||
= cos tonearest flt-32 0x1.8475e4p+0f : 0xd.a8283p-8f : inexact-ok
|
||||
= cos towardzero flt-32 0x1.8475e4p+0f : 0xd.a8283p-8f : inexact-ok
|
||||
= cos upward flt-32 0x1.8475e4p+0f : 0xd.a8284p-8f : inexact-ok
|
||||
= cos downward dbl-64 0x1.8475e4p+0 : 0xd.a82832da19f98p-8 : inexact-ok
|
||||
= cos tonearest dbl-64 0x1.8475e4p+0 : 0xd.a82832da19f98p-8 : inexact-ok
|
||||
= cos towardzero dbl-64 0x1.8475e4p+0 : 0xd.a82832da19f98p-8 : inexact-ok
|
||||
= cos upward dbl-64 0x1.8475e4p+0 : 0xd.a82832da19fap-8 : inexact-ok
|
||||
= cos downward ldbl-96-intel 0x1.8475e4p+0L : 0xd.a82832da19f9891p-8L : inexact-ok
|
||||
= cos tonearest ldbl-96-intel 0x1.8475e4p+0L : 0xd.a82832da19f9892p-8L : inexact-ok
|
||||
= cos towardzero ldbl-96-intel 0x1.8475e4p+0L : 0xd.a82832da19f9891p-8L : inexact-ok
|
||||
= cos upward ldbl-96-intel 0x1.8475e4p+0L : 0xd.a82832da19f9892p-8L : inexact-ok
|
||||
= cos downward ldbl-96-m68k 0x1.8475e4p+0L : 0xd.a82832da19f9891p-8L : inexact-ok
|
||||
= cos tonearest ldbl-96-m68k 0x1.8475e4p+0L : 0xd.a82832da19f9892p-8L : inexact-ok
|
||||
= cos towardzero ldbl-96-m68k 0x1.8475e4p+0L : 0xd.a82832da19f9891p-8L : inexact-ok
|
||||
= cos upward ldbl-96-m68k 0x1.8475e4p+0L : 0xd.a82832da19f9892p-8L : inexact-ok
|
||||
= cos downward ldbl-128 0x1.8475e4p+0L : 0xd.a82832da19f9891d9762fa659ff8p-8L : inexact-ok
|
||||
= cos tonearest ldbl-128 0x1.8475e4p+0L : 0xd.a82832da19f9891d9762fa659ff8p-8L : inexact-ok
|
||||
= cos towardzero ldbl-128 0x1.8475e4p+0L : 0xd.a82832da19f9891d9762fa659ff8p-8L : inexact-ok
|
||||
= cos upward ldbl-128 0x1.8475e4p+0L : 0xd.a82832da19f9891d9762fa65ap-8L : inexact-ok
|
||||
= cos downward ldbl-128ibm 0x1.8475e4p+0L : 0xd.a82832da19f9891d9762fa659cp-8L : inexact-ok
|
||||
= cos tonearest ldbl-128ibm 0x1.8475e4p+0L : 0xd.a82832da19f9891d9762fa65ap-8L : inexact-ok
|
||||
= cos towardzero ldbl-128ibm 0x1.8475e4p+0L : 0xd.a82832da19f9891d9762fa659cp-8L : inexact-ok
|
||||
= cos upward ldbl-128ibm 0x1.8475e4p+0L : 0xd.a82832da19f9891d9762fa65ap-8L : inexact-ok
|
||||
= cos downward dbl-64 0x1.8475e5afd4481p+0 : 0xd.a82683a33cbe8p-8 : inexact-ok
|
||||
= cos tonearest dbl-64 0x1.8475e5afd4481p+0 : 0xd.a82683a33cbe8p-8 : inexact-ok
|
||||
= cos towardzero dbl-64 0x1.8475e5afd4481p+0 : 0xd.a82683a33cbe8p-8 : inexact-ok
|
||||
= cos upward dbl-64 0x1.8475e5afd4481p+0 : 0xd.a82683a33cbfp-8 : inexact-ok
|
||||
= cos downward ldbl-96-intel 0x1.8475e5afd4481p+0L : 0xd.a82683a33cbebffp-8L : inexact-ok
|
||||
= cos tonearest ldbl-96-intel 0x1.8475e5afd4481p+0L : 0xd.a82683a33cbecp-8L : inexact-ok
|
||||
= cos towardzero ldbl-96-intel 0x1.8475e5afd4481p+0L : 0xd.a82683a33cbebffp-8L : inexact-ok
|
||||
= cos upward ldbl-96-intel 0x1.8475e5afd4481p+0L : 0xd.a82683a33cbecp-8L : inexact-ok
|
||||
= cos downward ldbl-96-m68k 0x1.8475e5afd4481p+0L : 0xd.a82683a33cbebffp-8L : inexact-ok
|
||||
= cos tonearest ldbl-96-m68k 0x1.8475e5afd4481p+0L : 0xd.a82683a33cbecp-8L : inexact-ok
|
||||
= cos towardzero ldbl-96-m68k 0x1.8475e5afd4481p+0L : 0xd.a82683a33cbebffp-8L : inexact-ok
|
||||
= cos upward ldbl-96-m68k 0x1.8475e5afd4481p+0L : 0xd.a82683a33cbecp-8L : inexact-ok
|
||||
= cos downward ldbl-128 0x1.8475e5afd4481p+0L : 0xd.a82683a33cbebfffffffa2966878p-8L : inexact-ok
|
||||
= cos tonearest ldbl-128 0x1.8475e5afd4481p+0L : 0xd.a82683a33cbebfffffffa2966878p-8L : inexact-ok
|
||||
= cos towardzero ldbl-128 0x1.8475e5afd4481p+0L : 0xd.a82683a33cbebfffffffa2966878p-8L : inexact-ok
|
||||
= cos upward ldbl-128 0x1.8475e5afd4481p+0L : 0xd.a82683a33cbebfffffffa296688p-8L : inexact-ok
|
||||
= cos downward ldbl-128ibm 0x1.8475e5afd4481p+0L : 0xd.a82683a33cbebfffffffa29668p-8L : inexact-ok
|
||||
= cos tonearest ldbl-128ibm 0x1.8475e5afd4481p+0L : 0xd.a82683a33cbebfffffffa29668p-8L : inexact-ok
|
||||
= cos towardzero ldbl-128ibm 0x1.8475e5afd4481p+0L : 0xd.a82683a33cbebfffffffa29668p-8L : inexact-ok
|
||||
= cos upward ldbl-128ibm 0x1.8475e5afd4481p+0L : 0xd.a82683a33cbebfffffffa2966cp-8L : inexact-ok
|
||||
cosh 0
|
||||
= cosh downward flt-32 0x0p+0f : 0x1p+0f : inexact-ok
|
||||
= cosh tonearest flt-32 0x0p+0f : 0x1p+0f : inexact-ok
|
||||
@@ -262073,6 +262142,75 @@ sin -min_subnorm
|
||||
= sin tonearest ldbl-128 -0x4p-16496L : -0x4p-16496L : inexact-ok underflow errno-erange-ok
|
||||
= sin towardzero ldbl-128 -0x4p-16496L : -0x0p+0L : inexact-ok underflow errno-erange-ok
|
||||
= sin upward ldbl-128 -0x4p-16496L : -0x0p+0L : inexact-ok underflow errno-erange-ok
|
||||
sin 0x1.8475e5afd4481p+0
|
||||
= sin downward flt-32 0x1.8475e6p+0f : 0xf.fa2adp-4f : inexact-ok
|
||||
= sin tonearest flt-32 0x1.8475e6p+0f : 0xf.fa2aep-4f : inexact-ok
|
||||
= sin towardzero flt-32 0x1.8475e6p+0f : 0xf.fa2adp-4f : inexact-ok
|
||||
= sin upward flt-32 0x1.8475e6p+0f : 0xf.fa2aep-4f : inexact-ok
|
||||
= sin downward dbl-64 0x1.8475e6p+0 : 0xf.fa2add3e58948p-4 : inexact-ok
|
||||
= sin tonearest dbl-64 0x1.8475e6p+0 : 0xf.fa2add3e58948p-4 : inexact-ok
|
||||
= sin towardzero dbl-64 0x1.8475e6p+0 : 0xf.fa2add3e58948p-4 : inexact-ok
|
||||
= sin upward dbl-64 0x1.8475e6p+0 : 0xf.fa2add3e5895p-4 : inexact-ok
|
||||
= sin downward ldbl-96-intel 0x1.8475e6p+0L : 0xf.fa2add3e58948d1p-4L : inexact-ok
|
||||
= sin tonearest ldbl-96-intel 0x1.8475e6p+0L : 0xf.fa2add3e58948d1p-4L : inexact-ok
|
||||
= sin towardzero ldbl-96-intel 0x1.8475e6p+0L : 0xf.fa2add3e58948d1p-4L : inexact-ok
|
||||
= sin upward ldbl-96-intel 0x1.8475e6p+0L : 0xf.fa2add3e58948d2p-4L : inexact-ok
|
||||
= sin downward ldbl-96-m68k 0x1.8475e6p+0L : 0xf.fa2add3e58948d1p-4L : inexact-ok
|
||||
= sin tonearest ldbl-96-m68k 0x1.8475e6p+0L : 0xf.fa2add3e58948d1p-4L : inexact-ok
|
||||
= sin towardzero ldbl-96-m68k 0x1.8475e6p+0L : 0xf.fa2add3e58948d1p-4L : inexact-ok
|
||||
= sin upward ldbl-96-m68k 0x1.8475e6p+0L : 0xf.fa2add3e58948d2p-4L : inexact-ok
|
||||
= sin downward ldbl-128 0x1.8475e6p+0L : 0xf.fa2add3e58948d10238cc27b5618p-4L : inexact-ok
|
||||
= sin tonearest ldbl-128 0x1.8475e6p+0L : 0xf.fa2add3e58948d10238cc27b562p-4L : inexact-ok
|
||||
= sin towardzero ldbl-128 0x1.8475e6p+0L : 0xf.fa2add3e58948d10238cc27b5618p-4L : inexact-ok
|
||||
= sin upward ldbl-128 0x1.8475e6p+0L : 0xf.fa2add3e58948d10238cc27b562p-4L : inexact-ok
|
||||
= sin downward ldbl-128ibm 0x1.8475e6p+0L : 0xf.fa2add3e58948d10238cc27b54p-4L : inexact-ok
|
||||
= sin tonearest ldbl-128ibm 0x1.8475e6p+0L : 0xf.fa2add3e58948d10238cc27b58p-4L : inexact-ok
|
||||
= sin towardzero ldbl-128ibm 0x1.8475e6p+0L : 0xf.fa2add3e58948d10238cc27b54p-4L : inexact-ok
|
||||
= sin upward ldbl-128ibm 0x1.8475e6p+0L : 0xf.fa2add3e58948d10238cc27b58p-4L : inexact-ok
|
||||
= sin downward flt-32 0x1.8475e4p+0f : 0xf.fa2adp-4f : inexact-ok
|
||||
= sin tonearest flt-32 0x1.8475e4p+0f : 0xf.fa2aep-4f : inexact-ok
|
||||
= sin towardzero flt-32 0x1.8475e4p+0f : 0xf.fa2adp-4f : inexact-ok
|
||||
= sin upward flt-32 0x1.8475e4p+0f : 0xf.fa2aep-4f : inexact-ok
|
||||
= sin downward dbl-64 0x1.8475e4p+0 : 0xf.fa2adb8953aep-4 : inexact-ok
|
||||
= sin tonearest dbl-64 0x1.8475e4p+0 : 0xf.fa2adb8953aep-4 : inexact-ok
|
||||
= sin towardzero dbl-64 0x1.8475e4p+0 : 0xf.fa2adb8953aep-4 : inexact-ok
|
||||
= sin upward dbl-64 0x1.8475e4p+0 : 0xf.fa2adb8953ae8p-4 : inexact-ok
|
||||
= sin downward ldbl-96-intel 0x1.8475e4p+0L : 0xf.fa2adb8953ae262p-4L : inexact-ok
|
||||
= sin tonearest ldbl-96-intel 0x1.8475e4p+0L : 0xf.fa2adb8953ae262p-4L : inexact-ok
|
||||
= sin towardzero ldbl-96-intel 0x1.8475e4p+0L : 0xf.fa2adb8953ae262p-4L : inexact-ok
|
||||
= sin upward ldbl-96-intel 0x1.8475e4p+0L : 0xf.fa2adb8953ae263p-4L : inexact-ok
|
||||
= sin downward ldbl-96-m68k 0x1.8475e4p+0L : 0xf.fa2adb8953ae262p-4L : inexact-ok
|
||||
= sin tonearest ldbl-96-m68k 0x1.8475e4p+0L : 0xf.fa2adb8953ae262p-4L : inexact-ok
|
||||
= sin towardzero ldbl-96-m68k 0x1.8475e4p+0L : 0xf.fa2adb8953ae262p-4L : inexact-ok
|
||||
= sin upward ldbl-96-m68k 0x1.8475e4p+0L : 0xf.fa2adb8953ae263p-4L : inexact-ok
|
||||
= sin downward ldbl-128 0x1.8475e4p+0L : 0xf.fa2adb8953ae26229c919ec8f6b8p-4L : inexact-ok
|
||||
= sin tonearest ldbl-128 0x1.8475e4p+0L : 0xf.fa2adb8953ae26229c919ec8f6cp-4L : inexact-ok
|
||||
= sin towardzero ldbl-128 0x1.8475e4p+0L : 0xf.fa2adb8953ae26229c919ec8f6b8p-4L : inexact-ok
|
||||
= sin upward ldbl-128 0x1.8475e4p+0L : 0xf.fa2adb8953ae26229c919ec8f6cp-4L : inexact-ok
|
||||
= sin downward ldbl-128ibm 0x1.8475e4p+0L : 0xf.fa2adb8953ae26229c919ec8f4p-4L : inexact-ok
|
||||
= sin tonearest ldbl-128ibm 0x1.8475e4p+0L : 0xf.fa2adb8953ae26229c919ec8f8p-4L : inexact-ok
|
||||
= sin towardzero ldbl-128ibm 0x1.8475e4p+0L : 0xf.fa2adb8953ae26229c919ec8f4p-4L : inexact-ok
|
||||
= sin upward ldbl-128ibm 0x1.8475e4p+0L : 0xf.fa2adb8953ae26229c919ec8f8p-4L : inexact-ok
|
||||
= sin downward dbl-64 0x1.8475e5afd4481p+0 : 0xf.fa2adcf9ea838p-4 : inexact-ok
|
||||
= sin tonearest dbl-64 0x1.8475e5afd4481p+0 : 0xf.fa2adcf9ea84p-4 : inexact-ok
|
||||
= sin towardzero dbl-64 0x1.8475e5afd4481p+0 : 0xf.fa2adcf9ea838p-4 : inexact-ok
|
||||
= sin upward dbl-64 0x1.8475e5afd4481p+0 : 0xf.fa2adcf9ea84p-4 : inexact-ok
|
||||
= sin downward ldbl-96-intel 0x1.8475e5afd4481p+0L : 0xf.fa2adcf9ea83dbdp-4L : inexact-ok
|
||||
= sin tonearest ldbl-96-intel 0x1.8475e5afd4481p+0L : 0xf.fa2adcf9ea83dbep-4L : inexact-ok
|
||||
= sin towardzero ldbl-96-intel 0x1.8475e5afd4481p+0L : 0xf.fa2adcf9ea83dbdp-4L : inexact-ok
|
||||
= sin upward ldbl-96-intel 0x1.8475e5afd4481p+0L : 0xf.fa2adcf9ea83dbep-4L : inexact-ok
|
||||
= sin downward ldbl-96-m68k 0x1.8475e5afd4481p+0L : 0xf.fa2adcf9ea83dbdp-4L : inexact-ok
|
||||
= sin tonearest ldbl-96-m68k 0x1.8475e5afd4481p+0L : 0xf.fa2adcf9ea83dbep-4L : inexact-ok
|
||||
= sin towardzero ldbl-96-m68k 0x1.8475e5afd4481p+0L : 0xf.fa2adcf9ea83dbdp-4L : inexact-ok
|
||||
= sin upward ldbl-96-m68k 0x1.8475e5afd4481p+0L : 0xf.fa2adcf9ea83dbep-4L : inexact-ok
|
||||
= sin downward ldbl-128 0x1.8475e5afd4481p+0L : 0xf.fa2adcf9ea83dbdd053ee455ea68p-4L : inexact-ok
|
||||
= sin tonearest ldbl-128 0x1.8475e5afd4481p+0L : 0xf.fa2adcf9ea83dbdd053ee455ea7p-4L : inexact-ok
|
||||
= sin towardzero ldbl-128 0x1.8475e5afd4481p+0L : 0xf.fa2adcf9ea83dbdd053ee455ea68p-4L : inexact-ok
|
||||
= sin upward ldbl-128 0x1.8475e5afd4481p+0L : 0xf.fa2adcf9ea83dbdd053ee455ea7p-4L : inexact-ok
|
||||
= sin downward ldbl-128ibm 0x1.8475e5afd4481p+0L : 0xf.fa2adcf9ea83dbdd053ee455e8p-4L : inexact-ok
|
||||
= sin tonearest ldbl-128ibm 0x1.8475e5afd4481p+0L : 0xf.fa2adcf9ea83dbdd053ee455ecp-4L : inexact-ok
|
||||
= sin towardzero ldbl-128ibm 0x1.8475e5afd4481p+0L : 0xf.fa2adcf9ea83dbdd053ee455e8p-4L : inexact-ok
|
||||
= sin upward ldbl-128ibm 0x1.8475e5afd4481p+0L : 0xf.fa2adcf9ea83dbdd053ee455ecp-4L : inexact-ok
|
||||
sincos 0
|
||||
= sincos downward flt-32 0x0p+0f : 0x0p+0f 0x1p+0f : inexact-ok
|
||||
= sincos tonearest flt-32 0x0p+0f : 0x0p+0f 0x1p+0f : inexact-ok
|
||||
@@ -264170,6 +264308,75 @@ sincos -min_subnorm
|
||||
= sincos tonearest ldbl-128 -0x4p-16496L : -0x4p-16496L 0x1p+0L : inexact-ok underflow errno-erange-ok
|
||||
= sincos towardzero ldbl-128 -0x4p-16496L : -0x0p+0L 0xf.fffffffffffffffffffffffffff8p-4L : inexact-ok underflow errno-erange-ok
|
||||
= sincos upward ldbl-128 -0x4p-16496L : -0x0p+0L 0x1p+0L : inexact-ok underflow errno-erange-ok
|
||||
sincos 0x1.8475e5afd4481p+0
|
||||
= sincos downward flt-32 0x1.8475e6p+0f : 0xf.fa2adp-4f 0xd.a8263p-8f : inexact-ok
|
||||
= sincos tonearest flt-32 0x1.8475e6p+0f : 0xf.fa2aep-4f 0xd.a8263p-8f : inexact-ok
|
||||
= sincos towardzero flt-32 0x1.8475e6p+0f : 0xf.fa2adp-4f 0xd.a8263p-8f : inexact-ok
|
||||
= sincos upward flt-32 0x1.8475e6p+0f : 0xf.fa2aep-4f 0xd.a8264p-8f : inexact-ok
|
||||
= sincos downward dbl-64 0x1.8475e6p+0 : 0xf.fa2add3e58948p-4 0xd.a8263394be6dp-8 : inexact-ok
|
||||
= sincos tonearest dbl-64 0x1.8475e6p+0 : 0xf.fa2add3e58948p-4 0xd.a8263394be6dp-8 : inexact-ok
|
||||
= sincos towardzero dbl-64 0x1.8475e6p+0 : 0xf.fa2add3e58948p-4 0xd.a8263394be6dp-8 : inexact-ok
|
||||
= sincos upward dbl-64 0x1.8475e6p+0 : 0xf.fa2add3e5895p-4 0xd.a8263394be6d8p-8 : inexact-ok
|
||||
= sincos downward ldbl-96-intel 0x1.8475e6p+0L : 0xf.fa2add3e58948d1p-4L 0xd.a8263394be6d0e5p-8L : inexact-ok
|
||||
= sincos tonearest ldbl-96-intel 0x1.8475e6p+0L : 0xf.fa2add3e58948d1p-4L 0xd.a8263394be6d0e6p-8L : inexact-ok
|
||||
= sincos towardzero ldbl-96-intel 0x1.8475e6p+0L : 0xf.fa2add3e58948d1p-4L 0xd.a8263394be6d0e5p-8L : inexact-ok
|
||||
= sincos upward ldbl-96-intel 0x1.8475e6p+0L : 0xf.fa2add3e58948d2p-4L 0xd.a8263394be6d0e6p-8L : inexact-ok
|
||||
= sincos downward ldbl-96-m68k 0x1.8475e6p+0L : 0xf.fa2add3e58948d1p-4L 0xd.a8263394be6d0e5p-8L : inexact-ok
|
||||
= sincos tonearest ldbl-96-m68k 0x1.8475e6p+0L : 0xf.fa2add3e58948d1p-4L 0xd.a8263394be6d0e6p-8L : inexact-ok
|
||||
= sincos towardzero ldbl-96-m68k 0x1.8475e6p+0L : 0xf.fa2add3e58948d1p-4L 0xd.a8263394be6d0e5p-8L : inexact-ok
|
||||
= sincos upward ldbl-96-m68k 0x1.8475e6p+0L : 0xf.fa2add3e58948d2p-4L 0xd.a8263394be6d0e6p-8L : inexact-ok
|
||||
= sincos downward ldbl-128 0x1.8475e6p+0L : 0xf.fa2add3e58948d10238cc27b5618p-4L 0xd.a8263394be6d0e58c1c35a8a3bap-8L : inexact-ok
|
||||
= sincos tonearest ldbl-128 0x1.8475e6p+0L : 0xf.fa2add3e58948d10238cc27b562p-4L 0xd.a8263394be6d0e58c1c35a8a3bap-8L : inexact-ok
|
||||
= sincos towardzero ldbl-128 0x1.8475e6p+0L : 0xf.fa2add3e58948d10238cc27b5618p-4L 0xd.a8263394be6d0e58c1c35a8a3bap-8L : inexact-ok
|
||||
= sincos upward ldbl-128 0x1.8475e6p+0L : 0xf.fa2add3e58948d10238cc27b562p-4L 0xd.a8263394be6d0e58c1c35a8a3ba8p-8L : inexact-ok
|
||||
= sincos downward ldbl-128ibm 0x1.8475e6p+0L : 0xf.fa2add3e58948d10238cc27b54p-4L 0xd.a8263394be6d0e58c1c35a8a38p-8L : inexact-ok
|
||||
= sincos tonearest ldbl-128ibm 0x1.8475e6p+0L : 0xf.fa2add3e58948d10238cc27b58p-4L 0xd.a8263394be6d0e58c1c35a8a3cp-8L : inexact-ok
|
||||
= sincos towardzero ldbl-128ibm 0x1.8475e6p+0L : 0xf.fa2add3e58948d10238cc27b54p-4L 0xd.a8263394be6d0e58c1c35a8a38p-8L : inexact-ok
|
||||
= sincos upward ldbl-128ibm 0x1.8475e6p+0L : 0xf.fa2add3e58948d10238cc27b58p-4L 0xd.a8263394be6d0e58c1c35a8a3cp-8L : inexact-ok
|
||||
= sincos downward flt-32 0x1.8475e4p+0f : 0xf.fa2adp-4f 0xd.a8283p-8f : inexact-ok
|
||||
= sincos tonearest flt-32 0x1.8475e4p+0f : 0xf.fa2aep-4f 0xd.a8283p-8f : inexact-ok
|
||||
= sincos towardzero flt-32 0x1.8475e4p+0f : 0xf.fa2adp-4f 0xd.a8283p-8f : inexact-ok
|
||||
= sincos upward flt-32 0x1.8475e4p+0f : 0xf.fa2aep-4f 0xd.a8284p-8f : inexact-ok
|
||||
= sincos downward dbl-64 0x1.8475e4p+0 : 0xf.fa2adb8953aep-4 0xd.a82832da19f98p-8 : inexact-ok
|
||||
= sincos tonearest dbl-64 0x1.8475e4p+0 : 0xf.fa2adb8953aep-4 0xd.a82832da19f98p-8 : inexact-ok
|
||||
= sincos towardzero dbl-64 0x1.8475e4p+0 : 0xf.fa2adb8953aep-4 0xd.a82832da19f98p-8 : inexact-ok
|
||||
= sincos upward dbl-64 0x1.8475e4p+0 : 0xf.fa2adb8953ae8p-4 0xd.a82832da19fap-8 : inexact-ok
|
||||
= sincos downward ldbl-96-intel 0x1.8475e4p+0L : 0xf.fa2adb8953ae262p-4L 0xd.a82832da19f9891p-8L : inexact-ok
|
||||
= sincos tonearest ldbl-96-intel 0x1.8475e4p+0L : 0xf.fa2adb8953ae262p-4L 0xd.a82832da19f9892p-8L : inexact-ok
|
||||
= sincos towardzero ldbl-96-intel 0x1.8475e4p+0L : 0xf.fa2adb8953ae262p-4L 0xd.a82832da19f9891p-8L : inexact-ok
|
||||
= sincos upward ldbl-96-intel 0x1.8475e4p+0L : 0xf.fa2adb8953ae263p-4L 0xd.a82832da19f9892p-8L : inexact-ok
|
||||
= sincos downward ldbl-96-m68k 0x1.8475e4p+0L : 0xf.fa2adb8953ae262p-4L 0xd.a82832da19f9891p-8L : inexact-ok
|
||||
= sincos tonearest ldbl-96-m68k 0x1.8475e4p+0L : 0xf.fa2adb8953ae262p-4L 0xd.a82832da19f9892p-8L : inexact-ok
|
||||
= sincos towardzero ldbl-96-m68k 0x1.8475e4p+0L : 0xf.fa2adb8953ae262p-4L 0xd.a82832da19f9891p-8L : inexact-ok
|
||||
= sincos upward ldbl-96-m68k 0x1.8475e4p+0L : 0xf.fa2adb8953ae263p-4L 0xd.a82832da19f9892p-8L : inexact-ok
|
||||
= sincos downward ldbl-128 0x1.8475e4p+0L : 0xf.fa2adb8953ae26229c919ec8f6b8p-4L 0xd.a82832da19f9891d9762fa659ff8p-8L : inexact-ok
|
||||
= sincos tonearest ldbl-128 0x1.8475e4p+0L : 0xf.fa2adb8953ae26229c919ec8f6cp-4L 0xd.a82832da19f9891d9762fa659ff8p-8L : inexact-ok
|
||||
= sincos towardzero ldbl-128 0x1.8475e4p+0L : 0xf.fa2adb8953ae26229c919ec8f6b8p-4L 0xd.a82832da19f9891d9762fa659ff8p-8L : inexact-ok
|
||||
= sincos upward ldbl-128 0x1.8475e4p+0L : 0xf.fa2adb8953ae26229c919ec8f6cp-4L 0xd.a82832da19f9891d9762fa65ap-8L : inexact-ok
|
||||
= sincos downward ldbl-128ibm 0x1.8475e4p+0L : 0xf.fa2adb8953ae26229c919ec8f4p-4L 0xd.a82832da19f9891d9762fa659cp-8L : inexact-ok
|
||||
= sincos tonearest ldbl-128ibm 0x1.8475e4p+0L : 0xf.fa2adb8953ae26229c919ec8f8p-4L 0xd.a82832da19f9891d9762fa65ap-8L : inexact-ok
|
||||
= sincos towardzero ldbl-128ibm 0x1.8475e4p+0L : 0xf.fa2adb8953ae26229c919ec8f4p-4L 0xd.a82832da19f9891d9762fa659cp-8L : inexact-ok
|
||||
= sincos upward ldbl-128ibm 0x1.8475e4p+0L : 0xf.fa2adb8953ae26229c919ec8f8p-4L 0xd.a82832da19f9891d9762fa65ap-8L : inexact-ok
|
||||
= sincos downward dbl-64 0x1.8475e5afd4481p+0 : 0xf.fa2adcf9ea838p-4 0xd.a82683a33cbe8p-8 : inexact-ok
|
||||
= sincos tonearest dbl-64 0x1.8475e5afd4481p+0 : 0xf.fa2adcf9ea84p-4 0xd.a82683a33cbe8p-8 : inexact-ok
|
||||
= sincos towardzero dbl-64 0x1.8475e5afd4481p+0 : 0xf.fa2adcf9ea838p-4 0xd.a82683a33cbe8p-8 : inexact-ok
|
||||
= sincos upward dbl-64 0x1.8475e5afd4481p+0 : 0xf.fa2adcf9ea84p-4 0xd.a82683a33cbfp-8 : inexact-ok
|
||||
= sincos downward ldbl-96-intel 0x1.8475e5afd4481p+0L : 0xf.fa2adcf9ea83dbdp-4L 0xd.a82683a33cbebffp-8L : inexact-ok
|
||||
= sincos tonearest ldbl-96-intel 0x1.8475e5afd4481p+0L : 0xf.fa2adcf9ea83dbep-4L 0xd.a82683a33cbecp-8L : inexact-ok
|
||||
= sincos towardzero ldbl-96-intel 0x1.8475e5afd4481p+0L : 0xf.fa2adcf9ea83dbdp-4L 0xd.a82683a33cbebffp-8L : inexact-ok
|
||||
= sincos upward ldbl-96-intel 0x1.8475e5afd4481p+0L : 0xf.fa2adcf9ea83dbep-4L 0xd.a82683a33cbecp-8L : inexact-ok
|
||||
= sincos downward ldbl-96-m68k 0x1.8475e5afd4481p+0L : 0xf.fa2adcf9ea83dbdp-4L 0xd.a82683a33cbebffp-8L : inexact-ok
|
||||
= sincos tonearest ldbl-96-m68k 0x1.8475e5afd4481p+0L : 0xf.fa2adcf9ea83dbep-4L 0xd.a82683a33cbecp-8L : inexact-ok
|
||||
= sincos towardzero ldbl-96-m68k 0x1.8475e5afd4481p+0L : 0xf.fa2adcf9ea83dbdp-4L 0xd.a82683a33cbebffp-8L : inexact-ok
|
||||
= sincos upward ldbl-96-m68k 0x1.8475e5afd4481p+0L : 0xf.fa2adcf9ea83dbep-4L 0xd.a82683a33cbecp-8L : inexact-ok
|
||||
= sincos downward ldbl-128 0x1.8475e5afd4481p+0L : 0xf.fa2adcf9ea83dbdd053ee455ea68p-4L 0xd.a82683a33cbebfffffffa2966878p-8L : inexact-ok
|
||||
= sincos tonearest ldbl-128 0x1.8475e5afd4481p+0L : 0xf.fa2adcf9ea83dbdd053ee455ea7p-4L 0xd.a82683a33cbebfffffffa2966878p-8L : inexact-ok
|
||||
= sincos towardzero ldbl-128 0x1.8475e5afd4481p+0L : 0xf.fa2adcf9ea83dbdd053ee455ea68p-4L 0xd.a82683a33cbebfffffffa2966878p-8L : inexact-ok
|
||||
= sincos upward ldbl-128 0x1.8475e5afd4481p+0L : 0xf.fa2adcf9ea83dbdd053ee455ea7p-4L 0xd.a82683a33cbebfffffffa296688p-8L : inexact-ok
|
||||
= sincos downward ldbl-128ibm 0x1.8475e5afd4481p+0L : 0xf.fa2adcf9ea83dbdd053ee455e8p-4L 0xd.a82683a33cbebfffffffa29668p-8L : inexact-ok
|
||||
= sincos tonearest ldbl-128ibm 0x1.8475e5afd4481p+0L : 0xf.fa2adcf9ea83dbdd053ee455ecp-4L 0xd.a82683a33cbebfffffffa29668p-8L : inexact-ok
|
||||
= sincos towardzero ldbl-128ibm 0x1.8475e5afd4481p+0L : 0xf.fa2adcf9ea83dbdd053ee455e8p-4L 0xd.a82683a33cbebfffffffa29668p-8L : inexact-ok
|
||||
= sincos upward ldbl-128ibm 0x1.8475e5afd4481p+0L : 0xf.fa2adcf9ea83dbdd053ee455ecp-4L 0xd.a82683a33cbebfffffffa2966cp-8L : inexact-ok
|
||||
sinh 0
|
||||
= sinh downward flt-32 0x0p+0f : 0x0p+0f : inexact-ok
|
||||
= sinh tonearest flt-32 0x0p+0f : 0x0p+0f : inexact-ok
|
||||
|
||||
@@ -30,12 +30,17 @@ do_test (void)
|
||||
header fix this test will not compile. */
|
||||
if (isinff (1.0f)
|
||||
|| !isinff (INFINITY)
|
||||
#ifndef NO_LONG_DOUBLE
|
||||
|| isinfl (1.0L)
|
||||
|| !isinfl (INFINITY)
|
||||
#endif
|
||||
|| isnanf (2.0f)
|
||||
|| !isnanf (NAN)
|
||||
#ifndef NO_LONG_DOUBLE
|
||||
|| isnanl (2.0L)
|
||||
|| !isnanl (NAN))
|
||||
|| !isnanl (NAN)
|
||||
#endif
|
||||
)
|
||||
{
|
||||
printf ("FAIL: Failed to call is* functions.\n");
|
||||
exit (1);
|
||||
|
||||
+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);
|
||||
|
||||
|
||||
|
||||
+11
-9
@@ -680,16 +680,18 @@ nis_server_cache_add (const_nis_name name, int search_parent,
|
||||
/* Choose which entry should be evicted from the cache. */
|
||||
loc = &nis_server_cache[0];
|
||||
if (*loc != NULL)
|
||||
for (i = 1; i < 16; ++i)
|
||||
if (nis_server_cache[i] == NULL)
|
||||
{
|
||||
{
|
||||
for (i = 1; i < 16; ++i)
|
||||
if (nis_server_cache[i] == NULL)
|
||||
{
|
||||
loc = &nis_server_cache[i];
|
||||
break;
|
||||
}
|
||||
else if ((*loc)->uses > nis_server_cache[i]->uses
|
||||
|| ((*loc)->uses == nis_server_cache[i]->uses
|
||||
&& (*loc)->expires > nis_server_cache[i]->expires))
|
||||
loc = &nis_server_cache[i];
|
||||
break;
|
||||
}
|
||||
else if ((*loc)->uses > nis_server_cache[i]->uses
|
||||
|| ((*loc)->uses == nis_server_cache[i]->uses
|
||||
&& (*loc)->expires > nis_server_cache[i]->expires))
|
||||
loc = &nis_server_cache[i];
|
||||
}
|
||||
old = *loc;
|
||||
*loc = new;
|
||||
|
||||
|
||||
@@ -266,7 +266,7 @@ _nss_nis_initgroups_dyn (const char *user, gid_t group, long int *start,
|
||||
|
||||
tmpbuf = __alloca (buflen);
|
||||
|
||||
do
|
||||
while (1)
|
||||
{
|
||||
while ((status =
|
||||
internal_getgrent_r (&grpbuf, tmpbuf, buflen, errnop,
|
||||
@@ -275,8 +275,11 @@ _nss_nis_initgroups_dyn (const char *user, gid_t group, long int *start,
|
||||
tmpbuf = extend_alloca (tmpbuf, buflen, 2 * buflen);
|
||||
|
||||
if (status != NSS_STATUS_SUCCESS)
|
||||
goto done;
|
||||
|
||||
{
|
||||
if (status == NSS_STATUS_NOTFOUND)
|
||||
status = NSS_STATUS_SUCCESS;
|
||||
goto done;
|
||||
}
|
||||
|
||||
g = &grpbuf;
|
||||
if (g->gr_gid != group)
|
||||
@@ -304,7 +307,11 @@ _nss_nis_initgroups_dyn (const char *user, gid_t group, long int *start,
|
||||
|
||||
newgroups = realloc (groups, newsize * sizeof (*groups));
|
||||
if (newgroups == NULL)
|
||||
goto done;
|
||||
{
|
||||
status = NSS_STATUS_TRYAGAIN;
|
||||
*errnop = errno;
|
||||
goto done;
|
||||
}
|
||||
*groupsp = groups = newgroups;
|
||||
*size = newsize;
|
||||
}
|
||||
@@ -316,7 +323,6 @@ _nss_nis_initgroups_dyn (const char *user, gid_t group, long int *start,
|
||||
}
|
||||
}
|
||||
}
|
||||
while (status == NSS_STATUS_SUCCESS);
|
||||
|
||||
done:
|
||||
while (intern.start != NULL)
|
||||
|
||||
+10
-33
@@ -25,48 +25,25 @@
|
||||
the historical ABI requires it. For static linking, there is no need to
|
||||
provide anything here--the libc version will be linked in. For shared
|
||||
library ABI compatibility, there must be __fork and fork symbols in
|
||||
libpthread.so; so we define them using IFUNC to redirect to the libc
|
||||
function. */
|
||||
libpthread.so.
|
||||
|
||||
With an IFUNC resolver, it would be possible to avoid the
|
||||
indirection, but the IFUNC resolver might run before the
|
||||
__libc_fork symbol has been relocated, in which case the IFUNC
|
||||
resolver would not be able to provide the correct address. */
|
||||
|
||||
#if SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_22)
|
||||
|
||||
# if HAVE_IFUNC
|
||||
|
||||
static __typeof (fork) *
|
||||
__attribute__ ((used))
|
||||
fork_resolve (void)
|
||||
{
|
||||
return &__libc_fork;
|
||||
}
|
||||
|
||||
# ifdef HAVE_ASM_SET_DIRECTIVE
|
||||
# define DEFINE_FORK(name) \
|
||||
asm (".set " #name ", fork_resolve\n" \
|
||||
".globl " #name "\n" \
|
||||
".type " #name ", %gnu_indirect_function");
|
||||
# else
|
||||
# define DEFINE_FORK(name) \
|
||||
asm (#name " = fork_resolve\n" \
|
||||
".globl " #name "\n" \
|
||||
".type " #name ", %gnu_indirect_function");
|
||||
# endif
|
||||
|
||||
# else /* !HAVE_IFUNC */
|
||||
|
||||
static pid_t __attribute__ ((used))
|
||||
fork_compat (void)
|
||||
{
|
||||
return __libc_fork ();
|
||||
}
|
||||
|
||||
# define DEFINE_FORK(name) strong_alias (fork_compat, name)
|
||||
strong_alias (fork_compat, fork_alias)
|
||||
compat_symbol (libpthread, fork_alias, fork, GLIBC_2_0);
|
||||
|
||||
# endif /* HAVE_IFUNC */
|
||||
|
||||
DEFINE_FORK (fork_ifunc)
|
||||
compat_symbol (libpthread, fork_ifunc, fork, GLIBC_2_0);
|
||||
|
||||
DEFINE_FORK (__fork_ifunc)
|
||||
compat_symbol (libpthread, __fork_ifunc, __fork, GLIBC_2_0);
|
||||
strong_alias (fork_compat, __fork_alias)
|
||||
compat_symbol (libpthread, __fork_alias, __fork, GLIBC_2_0);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -333,6 +333,22 @@ do_test (void)
|
||||
|
||||
puts ("early cancellation succeeded");
|
||||
|
||||
if (ap == &a2)
|
||||
{
|
||||
/* The aio_read(&a) was not canceled because the read request was
|
||||
already in progress. In the meanwhile aio_write(ap) wrote something
|
||||
to the pipe and the read request either has already been finished or
|
||||
is able to read the requested byte.
|
||||
Wait for the read request before returning from this function because
|
||||
the return value and error code from the read syscall will be written
|
||||
to the struct aiocb a, which lies on the stack of this function.
|
||||
Otherwise the stack from subsequent function calls - e.g. _dl_fini -
|
||||
will be corrupted, which can lead to undefined behaviour like a
|
||||
segmentation fault. */
|
||||
const struct aiocb *l[1] = { &a };
|
||||
TEMP_FAILURE_RETRY (aio_suspend(l, 1, NULL));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
+9
-3
@@ -77,7 +77,7 @@ CONCAT(_nss_db_set,ENTNAME) (int stayopen)
|
||||
keep_db |= stayopen;
|
||||
|
||||
/* Reset the sequential index. */
|
||||
entidx = (const char *) state.header + state.header->valstroffset;
|
||||
entidx = NULL;
|
||||
}
|
||||
|
||||
__libc_lock_unlock (lock);
|
||||
@@ -253,8 +253,14 @@ CONCAT(_nss_db_get,ENTNAME_r) (struct STRUCTURE *result, char *buffer,
|
||||
H_ERRNO_SET (NETDB_INTERNAL);
|
||||
goto out;
|
||||
}
|
||||
entidx = NULL;
|
||||
}
|
||||
|
||||
/* Start from the beginning if freshly initialized or reset
|
||||
requested by set*ent. */
|
||||
if (entidx == NULL)
|
||||
entidx = (const char *) state.header + state.header->valstroffset;
|
||||
|
||||
status = NSS_STATUS_UNAVAIL;
|
||||
if (state.header != MAP_FAILED)
|
||||
{
|
||||
@@ -288,8 +294,8 @@ CONCAT(_nss_db_get,ENTNAME_r) (struct STRUCTURE *result, char *buffer,
|
||||
}
|
||||
if (err < 0)
|
||||
{
|
||||
H_ERRNO_SET (HOST_NOT_FOUND);
|
||||
status = NSS_STATUS_NOTFOUND;
|
||||
H_ERRNO_SET (NETDB_INTERNAL);
|
||||
status = NSS_STATUS_TRYAGAIN;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
+468
-452
File diff suppressed because it is too large
Load Diff
+357
-298
File diff suppressed because it is too large
Load Diff
+1122
-1025
File diff suppressed because it is too large
Load Diff
+367
-296
File diff suppressed because it is too large
Load Diff
+14
-2
@@ -40,6 +40,17 @@
|
||||
# define PRINTF(fmt, args...)
|
||||
#endif
|
||||
|
||||
#define LONG_NAME \
|
||||
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
|
||||
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
|
||||
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
|
||||
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
|
||||
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
|
||||
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
|
||||
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
|
||||
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
|
||||
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
|
||||
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
||||
|
||||
static struct
|
||||
{
|
||||
@@ -58,6 +69,7 @@ static struct
|
||||
{ ".", 3, DT_DIR, 0755 },
|
||||
{ "..", 3, DT_DIR, 0755 },
|
||||
{ "a", 3, DT_REG, 0644 },
|
||||
{ LONG_NAME, 3, DT_REG, 0644 },
|
||||
{ "unreadable", 2, DT_DIR, 0111 },
|
||||
{ ".", 3, DT_DIR, 0111 },
|
||||
{ "..", 3, DT_DIR, 0755 },
|
||||
@@ -75,7 +87,7 @@ typedef struct
|
||||
int level;
|
||||
int idx;
|
||||
struct dirent d;
|
||||
char room_for_dirent[NAME_MAX];
|
||||
char room_for_dirent[sizeof (LONG_NAME)];
|
||||
} my_DIR;
|
||||
|
||||
|
||||
@@ -193,7 +205,7 @@ my_readdir (void *gdir)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dir->d.d_ino = dir->idx;
|
||||
dir->d.d_ino = 1; /* glob should not skip this entry. */
|
||||
|
||||
#ifdef _DIRENT_HAVE_D_TYPE
|
||||
dir->d.d_type = filesystem[dir->idx].type;
|
||||
|
||||
+125
-118
@@ -24,7 +24,9 @@
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/* Outcomment the following line for production quality code. */
|
||||
/* #define NDEBUG 1 */
|
||||
@@ -57,10 +59,8 @@
|
||||
|
||||
#if defined HAVE_DIRENT_H || defined __GNU_LIBRARY__
|
||||
# include <dirent.h>
|
||||
# define NAMLEN(dirent) strlen((dirent)->d_name)
|
||||
#else
|
||||
# define dirent direct
|
||||
# define NAMLEN(dirent) (dirent)->d_namlen
|
||||
# ifdef HAVE_SYS_NDIR_H
|
||||
# include <sys/ndir.h>
|
||||
# endif
|
||||
@@ -75,82 +75,8 @@
|
||||
# endif /* HAVE_VMSDIR_H */
|
||||
#endif
|
||||
|
||||
|
||||
/* In GNU systems, <dirent.h> defines this macro for us. */
|
||||
#ifdef _D_NAMLEN
|
||||
# undef NAMLEN
|
||||
# define NAMLEN(d) _D_NAMLEN(d)
|
||||
#endif
|
||||
|
||||
/* When used in the GNU libc the symbol _DIRENT_HAVE_D_TYPE is available
|
||||
if the `d_type' member for `struct dirent' is available.
|
||||
HAVE_STRUCT_DIRENT_D_TYPE plays the same role in GNULIB. */
|
||||
#if defined _DIRENT_HAVE_D_TYPE || defined HAVE_STRUCT_DIRENT_D_TYPE
|
||||
/* True if the directory entry D must be of type T. */
|
||||
# define DIRENT_MUST_BE(d, t) ((d)->d_type == (t))
|
||||
|
||||
/* True if the directory entry D might be a symbolic link. */
|
||||
# define DIRENT_MIGHT_BE_SYMLINK(d) \
|
||||
((d)->d_type == DT_UNKNOWN || (d)->d_type == DT_LNK)
|
||||
|
||||
/* True if the directory entry D might be a directory. */
|
||||
# define DIRENT_MIGHT_BE_DIR(d) \
|
||||
((d)->d_type == DT_DIR || DIRENT_MIGHT_BE_SYMLINK (d))
|
||||
|
||||
#else /* !HAVE_D_TYPE */
|
||||
# define DIRENT_MUST_BE(d, t) false
|
||||
# define DIRENT_MIGHT_BE_SYMLINK(d) true
|
||||
# define DIRENT_MIGHT_BE_DIR(d) true
|
||||
#endif /* HAVE_D_TYPE */
|
||||
|
||||
/* If the system has the `struct dirent64' type we use it internally. */
|
||||
#if defined _LIBC && !defined COMPILE_GLOB64
|
||||
# if defined HAVE_DIRENT_H || defined __GNU_LIBRARY__
|
||||
# define CONVERT_D_NAMLEN(d64, d32)
|
||||
# else
|
||||
# define CONVERT_D_NAMLEN(d64, d32) \
|
||||
(d64)->d_namlen = (d32)->d_namlen;
|
||||
# endif
|
||||
|
||||
# if (defined POSIX || defined WINDOWS32) && !defined __GNU_LIBRARY__
|
||||
# define CONVERT_D_INO(d64, d32)
|
||||
# else
|
||||
# define CONVERT_D_INO(d64, d32) \
|
||||
(d64)->d_ino = (d32)->d_ino;
|
||||
# endif
|
||||
|
||||
# ifdef _DIRENT_HAVE_D_TYPE
|
||||
# define CONVERT_D_TYPE(d64, d32) \
|
||||
(d64)->d_type = (d32)->d_type;
|
||||
# else
|
||||
# define CONVERT_D_TYPE(d64, d32)
|
||||
# endif
|
||||
|
||||
# define CONVERT_DIRENT_DIRENT64(d64, d32) \
|
||||
memcpy ((d64)->d_name, (d32)->d_name, NAMLEN (d32) + 1); \
|
||||
CONVERT_D_NAMLEN (d64, d32) \
|
||||
CONVERT_D_INO (d64, d32) \
|
||||
CONVERT_D_TYPE (d64, d32)
|
||||
#endif
|
||||
|
||||
|
||||
#if (defined POSIX || defined WINDOWS32) && !defined __GNU_LIBRARY__
|
||||
/* Posix does not require that the d_ino field be present, and some
|
||||
systems do not provide it. */
|
||||
# define REAL_DIR_ENTRY(dp) 1
|
||||
#else
|
||||
# define REAL_DIR_ENTRY(dp) (dp->d_ino != 0)
|
||||
#endif /* POSIX */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/* NAME_MAX is usually defined in <dirent.h> or <limits.h>. */
|
||||
#include <limits.h>
|
||||
#ifndef NAME_MAX
|
||||
# define NAME_MAX (sizeof (((struct dirent *) 0)->d_name))
|
||||
#endif
|
||||
|
||||
#include <alloca.h>
|
||||
|
||||
#ifdef _LIBC
|
||||
@@ -195,8 +121,111 @@
|
||||
|
||||
static const char *next_brace_sub (const char *begin, int flags) __THROWNL;
|
||||
|
||||
/* A representation of a directory entry which does not depend on the
|
||||
layout of struct dirent, or the size of ino_t. */
|
||||
struct readdir_result
|
||||
{
|
||||
const char *name;
|
||||
# if defined _DIRENT_HAVE_D_TYPE || defined HAVE_STRUCT_DIRENT_D_TYPE
|
||||
uint8_t type;
|
||||
# endif
|
||||
bool skip_entry;
|
||||
};
|
||||
|
||||
# if defined _DIRENT_HAVE_D_TYPE || defined HAVE_STRUCT_DIRENT_D_TYPE
|
||||
/* Initializer based on the d_type member of struct dirent. */
|
||||
# define D_TYPE_TO_RESULT(source) (source)->d_type,
|
||||
|
||||
/* True if the directory entry D might be a symbolic link. */
|
||||
static bool
|
||||
readdir_result_might_be_symlink (struct readdir_result d)
|
||||
{
|
||||
return d.type == DT_UNKNOWN || d.type == DT_LNK;
|
||||
}
|
||||
|
||||
/* True if the directory entry D might be a directory. */
|
||||
static bool
|
||||
readdir_result_might_be_dir (struct readdir_result d)
|
||||
{
|
||||
return d.type == DT_DIR || readdir_result_might_be_symlink (d);
|
||||
}
|
||||
# else /* defined _DIRENT_HAVE_D_TYPE || defined HAVE_STRUCT_DIRENT_D_TYPE */
|
||||
# define D_TYPE_TO_RESULT(source)
|
||||
|
||||
/* If we do not have type information, symbolic links and directories
|
||||
are always a possibility. */
|
||||
|
||||
static bool
|
||||
readdir_result_might_be_symlink (struct readdir_result d)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
readdir_result_might_be_dir (struct readdir_result d)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
# endif /* defined _DIRENT_HAVE_D_TYPE || defined HAVE_STRUCT_DIRENT_D_TYPE */
|
||||
|
||||
# if (defined POSIX || defined WINDOWS32) && !defined __GNU_LIBRARY__
|
||||
/* Initializer for skip_entry. POSIX does not require that the d_ino
|
||||
field be present, and some systems do not provide it. */
|
||||
# define D_INO_TO_RESULT(source) false,
|
||||
# else
|
||||
# define D_INO_TO_RESULT(source) (source)->d_ino == 0,
|
||||
# endif
|
||||
|
||||
/* Construct an initializer for a struct readdir_result object from a
|
||||
struct dirent *. No copy of the name is made. */
|
||||
#define READDIR_RESULT_INITIALIZER(source) \
|
||||
{ \
|
||||
source->d_name, \
|
||||
D_TYPE_TO_RESULT (source) \
|
||||
D_INO_TO_RESULT (source) \
|
||||
}
|
||||
|
||||
#endif /* !defined _LIBC || !defined GLOB_ONLY_P */
|
||||
|
||||
/* Call gl_readdir on STREAM. This macro can be overridden to reduce
|
||||
type safety if an old interface version needs to be supported. */
|
||||
#ifndef GL_READDIR
|
||||
# define GL_READDIR(pglob, stream) ((pglob)->gl_readdir (stream))
|
||||
#endif
|
||||
|
||||
/* Extract name and type from directory entry. No copy of the name is
|
||||
made. If SOURCE is NULL, result name is NULL. Keep in sync with
|
||||
convert_dirent64 below. */
|
||||
static struct readdir_result
|
||||
convert_dirent (const struct dirent *source)
|
||||
{
|
||||
if (source == NULL)
|
||||
{
|
||||
struct readdir_result result = { NULL, };
|
||||
return result;
|
||||
}
|
||||
struct readdir_result result = READDIR_RESULT_INITIALIZER (source);
|
||||
return result;
|
||||
}
|
||||
|
||||
#ifndef COMPILE_GLOB64
|
||||
/* Like convert_dirent, but works on struct dirent64 instead. Keep in
|
||||
sync with convert_dirent above. */
|
||||
static struct readdir_result
|
||||
convert_dirent64 (const struct dirent64 *source)
|
||||
{
|
||||
if (source == NULL)
|
||||
{
|
||||
struct readdir_result result = { NULL, };
|
||||
return result;
|
||||
}
|
||||
struct readdir_result result = READDIR_RESULT_INITIALIZER (source);
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef attribute_hidden
|
||||
# define attribute_hidden
|
||||
#endif
|
||||
@@ -1553,56 +1582,36 @@ glob_in_dir (const char *pattern, const char *directory, int flags,
|
||||
|
||||
while (1)
|
||||
{
|
||||
const char *name;
|
||||
size_t len;
|
||||
#if defined _LIBC && !defined COMPILE_GLOB64
|
||||
struct dirent64 *d;
|
||||
union
|
||||
{
|
||||
struct dirent64 d64;
|
||||
char room [offsetof (struct dirent64, d_name[0])
|
||||
+ NAME_MAX + 1];
|
||||
}
|
||||
d64buf;
|
||||
|
||||
if (__glibc_unlikely (flags & GLOB_ALTDIRFUNC))
|
||||
{
|
||||
struct dirent *d32 = (*pglob->gl_readdir) (stream);
|
||||
if (d32 != NULL)
|
||||
{
|
||||
CONVERT_DIRENT_DIRENT64 (&d64buf.d64, d32);
|
||||
d = &d64buf.d64;
|
||||
}
|
||||
else
|
||||
d = NULL;
|
||||
}
|
||||
else
|
||||
d = __readdir64 (stream);
|
||||
struct readdir_result d;
|
||||
{
|
||||
if (__builtin_expect (flags & GLOB_ALTDIRFUNC, 0))
|
||||
d = convert_dirent (GL_READDIR (pglob, stream));
|
||||
else
|
||||
{
|
||||
#ifdef COMPILE_GLOB64
|
||||
d = convert_dirent (__readdir (stream));
|
||||
#else
|
||||
struct dirent *d = (__builtin_expect (flags & GLOB_ALTDIRFUNC, 0)
|
||||
? ((struct dirent *)
|
||||
(*pglob->gl_readdir) (stream))
|
||||
: __readdir (stream));
|
||||
d = convert_dirent64 (__readdir64 (stream));
|
||||
#endif
|
||||
if (d == NULL)
|
||||
}
|
||||
}
|
||||
if (d.name == NULL)
|
||||
break;
|
||||
if (! REAL_DIR_ENTRY (d))
|
||||
if (d.skip_entry)
|
||||
continue;
|
||||
|
||||
/* If we shall match only directories use the information
|
||||
provided by the dirent call if possible. */
|
||||
if ((flags & GLOB_ONLYDIR) && !DIRENT_MIGHT_BE_DIR (d))
|
||||
if ((flags & GLOB_ONLYDIR) && !readdir_result_might_be_dir (d))
|
||||
continue;
|
||||
|
||||
name = d->d_name;
|
||||
|
||||
if (fnmatch (pattern, name, fnm_flags) == 0)
|
||||
if (fnmatch (pattern, d.name, fnm_flags) == 0)
|
||||
{
|
||||
/* If the file we found is a symlink we have to
|
||||
make sure the target file exists. */
|
||||
if (!DIRENT_MIGHT_BE_SYMLINK (d)
|
||||
|| link_exists_p (dfd, directory, dirlen, name, pglob,
|
||||
flags))
|
||||
if (!readdir_result_might_be_symlink (d)
|
||||
|| link_exists_p (dfd, directory, dirlen, d.name,
|
||||
pglob, flags))
|
||||
{
|
||||
if (cur == names->count)
|
||||
{
|
||||
@@ -1622,12 +1631,10 @@ glob_in_dir (const char *pattern, const char *directory, int flags,
|
||||
names = newnames;
|
||||
cur = 0;
|
||||
}
|
||||
len = NAMLEN (d);
|
||||
names->name[cur] = (char *) malloc (len + 1);
|
||||
names->name[cur] = strdup (d.name);
|
||||
if (names->name[cur] == NULL)
|
||||
goto memory_error;
|
||||
*((char *) mempcpy (names->name[cur++], name, len))
|
||||
= '\0';
|
||||
++cur;
|
||||
++nfound;
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -211,7 +211,7 @@ my_readdir (void *gdir)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dir->d.d_ino = dir->idx;
|
||||
dir->d.d_ino = 1; /* glob should not skip this entry. */
|
||||
|
||||
#ifdef _DIRENT_HAVE_D_TYPE
|
||||
dir->d.d_type = filesystem[dir->idx].type;
|
||||
|
||||
@@ -70,7 +70,6 @@ static char sccsid[] = "@(#)gethostnamadr.c 8.1 (Berkeley) 6/4/93";
|
||||
#include <resolv.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <syslog.h>
|
||||
|
||||
#define RESOLVSORT
|
||||
|
||||
@@ -100,9 +99,6 @@ static char sccsid[] = "@(#)gethostnamadr.c 8.1 (Berkeley) 6/4/93";
|
||||
#define MAXALIASES 35
|
||||
#define MAXADDRS 35
|
||||
|
||||
static const char AskedForGot[] =
|
||||
"gethostby*.getanswer: asked for \"%s\", got \"%s\"";
|
||||
|
||||
static char *h_addr_ptrs[MAXADDRS + 1];
|
||||
|
||||
static struct hostent host;
|
||||
@@ -335,20 +331,12 @@ getanswer (const querybuf *answer, int anslen, const char *qname, int qtype)
|
||||
* uses many different types in responses that do not
|
||||
* match QTYPE.
|
||||
*/
|
||||
if ((_res.options & RES_USE_DNSSEC) == 0) {
|
||||
syslog(LOG_NOTICE|LOG_AUTH,
|
||||
"gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"",
|
||||
qname, p_class(C_IN), p_type(qtype),
|
||||
p_type(type));
|
||||
}
|
||||
cp += n;
|
||||
continue; /* XXX - had_error++ ? */
|
||||
}
|
||||
switch (type) {
|
||||
case T_PTR:
|
||||
if (strcasecmp(tname, bp) != 0) {
|
||||
syslog(LOG_NOTICE|LOG_AUTH,
|
||||
AskedForGot, qname, bp);
|
||||
cp += n;
|
||||
continue; /* XXX - had_error++ ? */
|
||||
}
|
||||
@@ -397,8 +385,6 @@ getanswer (const querybuf *answer, int anslen, const char *qname, int qtype)
|
||||
case T_A:
|
||||
case T_AAAA:
|
||||
if (strcasecmp(host.h_name, bp) != 0) {
|
||||
syslog(LOG_NOTICE|LOG_AUTH,
|
||||
AskedForGot, host.h_name, bp);
|
||||
cp += n;
|
||||
continue; /* XXX - had_error++ ? */
|
||||
}
|
||||
@@ -740,9 +726,6 @@ gethostbyaddr (const void *addr, socklen_t len, int af)
|
||||
_res.options &= ~RES_DNSRCH;
|
||||
_res.options |= RES_DEFNAMES;
|
||||
if (!(rhp = gethostbyname(hname2))) {
|
||||
syslog(LOG_NOTICE|LOG_AUTH,
|
||||
"gethostbyaddr: No A record for %s (verifying [%s])",
|
||||
hname2, inet_ntoa(*((struct in_addr *)addr)));
|
||||
_res.options = old_options;
|
||||
__set_h_errno (HOST_NOT_FOUND);
|
||||
return (NULL);
|
||||
@@ -752,9 +735,6 @@ gethostbyaddr (const void *addr, socklen_t len, int af)
|
||||
if (!memcmp(*haddr, addr, INADDRSZ))
|
||||
break;
|
||||
if (!*haddr) {
|
||||
syslog(LOG_NOTICE|LOG_AUTH,
|
||||
"gethostbyaddr: A record of %s != PTR record [%s]",
|
||||
hname2, inet_ntoa(*((struct in_addr *)addr)));
|
||||
__set_h_errno (HOST_NOT_FOUND);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
@@ -103,6 +103,11 @@ _nss_dns_getcanonname_r (const char *name, char *buffer, size_t buflen,
|
||||
|
||||
ptr += s;
|
||||
|
||||
/* Check that there are enough bytes for the RR
|
||||
metadata. */
|
||||
if (endptr - ptr < 10)
|
||||
goto unavail;
|
||||
|
||||
/* Check whether type and class match. */
|
||||
uint_fast16_t type;
|
||||
NS_GET16 (type, ptr);
|
||||
@@ -137,13 +142,25 @@ _nss_dns_getcanonname_r (const char *name, char *buffer, size_t buflen,
|
||||
if (__ns_get16 (ptr) != ns_c_in)
|
||||
goto unavail;
|
||||
|
||||
/* Also skip over the TTL. */
|
||||
/* Also skip over class and TTL. */
|
||||
ptr += sizeof (uint16_t) + sizeof (uint32_t);
|
||||
|
||||
/* Skip over the data length and data. */
|
||||
ptr += sizeof (uint16_t) + __ns_get16 (ptr);
|
||||
/* Skip over RDATA length and RDATA itself. */
|
||||
uint16_t rdatalen = __ns_get16 (ptr);
|
||||
ptr += sizeof (uint16_t);
|
||||
/* Not enough room for RDATA. */
|
||||
if (endptr - ptr < rdatalen)
|
||||
goto unavail;
|
||||
ptr += rdatalen;
|
||||
}
|
||||
}
|
||||
|
||||
/* Restore original buffer before retry. */
|
||||
if (ansp.ptr != buf)
|
||||
{
|
||||
free (ansp.ptr);
|
||||
ansp.ptr = buf;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
|
||||
+54
-42
@@ -78,7 +78,6 @@
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <sys/syslog.h>
|
||||
|
||||
#include "nsswitch.h"
|
||||
|
||||
@@ -99,10 +98,6 @@
|
||||
#endif
|
||||
#define MAXHOSTNAMELEN 256
|
||||
|
||||
static const char AskedForGot[] = "\
|
||||
gethostby*.getanswer: asked for \"%s\", got \"%s\"";
|
||||
|
||||
|
||||
/* We need this time later. */
|
||||
typedef union querybuf
|
||||
{
|
||||
@@ -139,6 +134,22 @@ extern enum nss_status _nss_dns_gethostbyname3_r (const char *name, int af,
|
||||
char **canonp);
|
||||
hidden_proto (_nss_dns_gethostbyname3_r)
|
||||
|
||||
/* Return the expected RDATA length for an address record type (A or
|
||||
AAAA). */
|
||||
static int
|
||||
rrtype_to_rdata_length (int type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case T_A:
|
||||
return INADDRSZ;
|
||||
case T_AAAA:
|
||||
return IN6ADDRSZ;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
enum nss_status
|
||||
_nss_dns_gethostbyname3_r (const char *name, int af, struct hostent *result,
|
||||
char *buffer, size_t buflen, int *errnop,
|
||||
@@ -751,6 +762,14 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype,
|
||||
cp += INT32SZ; /* TTL */
|
||||
n = __ns_get16 (cp);
|
||||
cp += INT16SZ; /* len */
|
||||
|
||||
if (end_of_message - cp < n)
|
||||
{
|
||||
/* RDATA extends beyond the end of the packet. */
|
||||
++had_error;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (__glibc_unlikely (class != C_IN))
|
||||
{
|
||||
/* XXX - debug? syslog? */
|
||||
@@ -830,14 +849,6 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype,
|
||||
have_to_map = 1;
|
||||
else if (__glibc_unlikely (type != qtype))
|
||||
{
|
||||
/* Log a low priority message if we get an unexpected record, but
|
||||
skip it if we are using DNSSEC since it uses many different types
|
||||
in responses that do not match QTYPE. */
|
||||
if ((_res.options & RES_USE_DNSSEC) == 0)
|
||||
syslog (LOG_NOTICE | LOG_AUTH,
|
||||
"gethostby*.getanswer: asked for \"%s %s %s\", "
|
||||
"got type \"%s\"",
|
||||
qname, p_class (C_IN), p_type (qtype), p_type (type));
|
||||
cp += n;
|
||||
continue; /* XXX - had_error++ ? */
|
||||
}
|
||||
@@ -847,7 +858,6 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype,
|
||||
case T_PTR:
|
||||
if (__glibc_unlikely (strcasecmp (tname, bp) != 0))
|
||||
{
|
||||
syslog (LOG_NOTICE | LOG_AUTH, AskedForGot, qname, bp);
|
||||
cp += n;
|
||||
continue; /* XXX - had_error++ ? */
|
||||
}
|
||||
@@ -891,10 +901,18 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype,
|
||||
case T_AAAA:
|
||||
if (__builtin_expect (strcasecmp (result->h_name, bp), 0) != 0)
|
||||
{
|
||||
syslog (LOG_NOTICE | LOG_AUTH, AskedForGot, result->h_name, bp);
|
||||
cp += n;
|
||||
continue; /* XXX - had_error++ ? */
|
||||
}
|
||||
|
||||
/* Stop parsing at a record whose length is incorrect. */
|
||||
if (n != rrtype_to_rdata_length (type))
|
||||
{
|
||||
++had_error;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Skip records of the wrong type. */
|
||||
if (n != result->h_length)
|
||||
{
|
||||
cp += n;
|
||||
@@ -1077,6 +1095,13 @@ gaih_getanswer_slice (const querybuf *answer, int anslen, const char *qname,
|
||||
n = __ns_get16 (cp);
|
||||
cp += INT16SZ; /* len */
|
||||
|
||||
if (end_of_message - cp < n)
|
||||
{
|
||||
/* RDATA extends beyond the end of the packet. */
|
||||
++had_error;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (class != C_IN)
|
||||
{
|
||||
cp += n;
|
||||
@@ -1124,32 +1149,25 @@ gaih_getanswer_slice (const querybuf *answer, int anslen, const char *qname,
|
||||
}
|
||||
continue;
|
||||
}
|
||||
#if 1
|
||||
// We should not see any types other than those explicitly listed
|
||||
// below. Some types sent by server seem missing, though. Just
|
||||
// collect the data for now.
|
||||
if (__glibc_unlikely (type != T_A && type != T_AAAA))
|
||||
#else
|
||||
if (__builtin_expect (type == T_SIG, 0)
|
||||
|| __builtin_expect (type == T_KEY, 0)
|
||||
|| __builtin_expect (type == T_NXT, 0)
|
||||
|| __builtin_expect (type == T_PTR, 0)
|
||||
|| __builtin_expect (type == T_DNAME, 0))
|
||||
#endif
|
||||
{
|
||||
/* We don't support DNSSEC yet. For now, ignore the record
|
||||
and send a low priority message to syslog.
|
||||
|
||||
We also don't expect T_PTR or T_DNAME messages. */
|
||||
syslog (LOG_DEBUG | LOG_AUTH,
|
||||
"getaddrinfo*.gaih_getanswer: got type \"%s\"",
|
||||
p_type (type));
|
||||
/* Stop parsing if we encounter a record with incorrect RDATA
|
||||
length. */
|
||||
if (type == T_A || type == T_AAAA)
|
||||
{
|
||||
if (n != rrtype_to_rdata_length (type))
|
||||
{
|
||||
++had_error;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Skip unknown records. */
|
||||
cp += n;
|
||||
continue;
|
||||
}
|
||||
if (type != T_A && type != T_AAAA)
|
||||
abort ();
|
||||
|
||||
assert (type == T_A || type == T_AAAA);
|
||||
if (*pat == NULL)
|
||||
{
|
||||
uintptr_t pad = (-(uintptr_t) buffer
|
||||
@@ -1183,12 +1201,6 @@ gaih_getanswer_slice (const querybuf *answer, int anslen, const char *qname,
|
||||
}
|
||||
|
||||
(*pat)->family = type == T_A ? AF_INET : AF_INET6;
|
||||
if (__builtin_expect ((type == T_A && n != INADDRSZ)
|
||||
|| (type == T_AAAA && n != IN6ADDRSZ), 0))
|
||||
{
|
||||
++had_error;
|
||||
continue;
|
||||
}
|
||||
memcpy ((*pat)->addr, cp, n);
|
||||
cp += n;
|
||||
(*pat)->scopeid = 0;
|
||||
|
||||
@@ -118,17 +118,14 @@ _nss_dns_getnetbyname_r (const char *name, struct netent *result,
|
||||
} net_buffer;
|
||||
querybuf *orig_net_buffer;
|
||||
int anslen;
|
||||
char *qbuf;
|
||||
enum nss_status status;
|
||||
|
||||
if (__res_maybe_init (&_res, 0) == -1)
|
||||
return NSS_STATUS_UNAVAIL;
|
||||
|
||||
qbuf = strdupa (name);
|
||||
|
||||
net_buffer.buf = orig_net_buffer = (querybuf *) alloca (1024);
|
||||
|
||||
anslen = __libc_res_nsearch (&_res, qbuf, C_IN, T_PTR, net_buffer.buf->buf,
|
||||
anslen = __libc_res_nsearch (&_res, name, C_IN, T_PTR, net_buffer.buf->buf,
|
||||
1024, &net_buffer.ptr, NULL, NULL, NULL, NULL);
|
||||
if (anslen < 0)
|
||||
{
|
||||
@@ -348,10 +345,23 @@ getanswer_r (const querybuf *answer, int anslen, struct netent *result,
|
||||
if (n < 0 || res_dnok (bp) == 0)
|
||||
break;
|
||||
cp += n;
|
||||
|
||||
if (end_of_message - cp < 10)
|
||||
{
|
||||
__set_h_errno (NO_RECOVERY);
|
||||
return NSS_STATUS_UNAVAIL;
|
||||
}
|
||||
|
||||
GETSHORT (type, cp);
|
||||
GETSHORT (class, cp);
|
||||
cp += INT32SZ; /* TTL */
|
||||
GETSHORT (n, cp);
|
||||
uint16_t rdatalen;
|
||||
GETSHORT (rdatalen, cp);
|
||||
if (end_of_message - cp < rdatalen)
|
||||
{
|
||||
__set_h_errno (NO_RECOVERY);
|
||||
return NSS_STATUS_UNAVAIL;
|
||||
}
|
||||
|
||||
if (class == C_IN && type == T_PTR)
|
||||
{
|
||||
@@ -373,7 +383,7 @@ getanswer_r (const querybuf *answer, int anslen, struct netent *result,
|
||||
cp += n;
|
||||
return NSS_STATUS_UNAVAIL;
|
||||
}
|
||||
cp += n;
|
||||
cp += rdatalen;
|
||||
if (alias_pointer + 2 < &net_data->aliases[MAX_NR_ALIASES])
|
||||
{
|
||||
*alias_pointer++ = bp;
|
||||
@@ -384,6 +394,9 @@ getanswer_r (const querybuf *answer, int anslen, struct netent *result,
|
||||
++have_answer;
|
||||
}
|
||||
}
|
||||
else
|
||||
/* Skip over unknown record data. */
|
||||
cp += rdatalen;
|
||||
}
|
||||
|
||||
if (have_answer)
|
||||
|
||||
+1
-1
@@ -594,7 +594,7 @@ __res_iclose(res_state statp, bool free_addr) {
|
||||
statp->_vcsock = -1;
|
||||
statp->_flags &= ~(RES_F_VC | RES_F_CONN);
|
||||
}
|
||||
for (ns = 0; ns < statp->_u._ext.nscount; ns++)
|
||||
for (ns = 0; ns < statp->nscount; ns++)
|
||||
if (statp->_u._ext.nsaddrs[ns]) {
|
||||
if (statp->_u._ext.nssocks[ns] != -1) {
|
||||
close_not_cancel_no_status(statp->_u._ext.nssocks[ns]);
|
||||
|
||||
+58
-44
@@ -649,6 +649,18 @@ get_nsaddr (res_state statp, int n)
|
||||
return (struct sockaddr *) (void *) &statp->nsaddr_list[n];
|
||||
}
|
||||
|
||||
/* Close the resolver structure, assign zero to *RESPLEN2 if RESPLEN2
|
||||
is not NULL, and return zero. */
|
||||
static int
|
||||
__attribute__ ((warn_unused_result))
|
||||
close_and_return_error (res_state statp, int *resplen2)
|
||||
{
|
||||
__res_iclose(statp, false);
|
||||
if (resplen2 != NULL)
|
||||
*resplen2 = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* The send_vc function is responsible for sending a DNS query over TCP
|
||||
to the nameserver numbered NS from the res_state STATP i.e.
|
||||
EXT(statp).nssocks[ns]. The function supports sending both IPv4 and
|
||||
@@ -750,8 +762,6 @@ send_vc(res_state statp,
|
||||
u_short len2;
|
||||
u_char *cp;
|
||||
|
||||
if (resplen2 != NULL)
|
||||
*resplen2 = 0;
|
||||
connreset = 0;
|
||||
same_ns:
|
||||
truncating = 0;
|
||||
@@ -777,6 +787,8 @@ send_vc(res_state statp,
|
||||
if (statp->_vcsock < 0) {
|
||||
*terrno = errno;
|
||||
Perror(statp, stderr, "socket(vc)", errno);
|
||||
if (resplen2 != NULL)
|
||||
*resplen2 = 0;
|
||||
return (-1);
|
||||
}
|
||||
__set_errno (0);
|
||||
@@ -786,8 +798,7 @@ send_vc(res_state statp,
|
||||
: sizeof (struct sockaddr_in6)) < 0) {
|
||||
*terrno = errno;
|
||||
Aerror(statp, stderr, "connect/vc", errno, nsap);
|
||||
__res_iclose(statp, false);
|
||||
return (0);
|
||||
return close_and_return_error (statp, resplen2);
|
||||
}
|
||||
statp->_flags |= RES_F_VC;
|
||||
}
|
||||
@@ -810,8 +821,7 @@ send_vc(res_state statp,
|
||||
if (TEMP_FAILURE_RETRY (writev(statp->_vcsock, iov, niov)) != explen) {
|
||||
*terrno = errno;
|
||||
Perror(statp, stderr, "write failed", errno);
|
||||
__res_iclose(statp, false);
|
||||
return (0);
|
||||
return close_and_return_error (statp, resplen2);
|
||||
}
|
||||
/*
|
||||
* Receive length & response
|
||||
@@ -833,7 +843,6 @@ send_vc(res_state statp,
|
||||
if (n <= 0) {
|
||||
*terrno = errno;
|
||||
Perror(statp, stderr, "read failed", errno);
|
||||
__res_iclose(statp, false);
|
||||
/*
|
||||
* A long running process might get its TCP
|
||||
* connection reset if the remote server was
|
||||
@@ -843,11 +852,13 @@ send_vc(res_state statp,
|
||||
* instead of failing. We only allow one reset
|
||||
* per query to prevent looping.
|
||||
*/
|
||||
if (*terrno == ECONNRESET && !connreset) {
|
||||
connreset = 1;
|
||||
goto same_ns;
|
||||
}
|
||||
return (0);
|
||||
if (*terrno == ECONNRESET && !connreset)
|
||||
{
|
||||
__res_iclose (statp, false);
|
||||
connreset = 1;
|
||||
goto same_ns;
|
||||
}
|
||||
return close_and_return_error (statp, resplen2);
|
||||
}
|
||||
int rlen = ntohs (rlen16);
|
||||
|
||||
@@ -879,11 +890,11 @@ send_vc(res_state statp,
|
||||
/* Always allocate MAXPACKET, callers expect
|
||||
this specific size. */
|
||||
u_char *newp = malloc (MAXPACKET);
|
||||
if (newp == NULL) {
|
||||
*terrno = ENOMEM;
|
||||
__res_iclose(statp, false);
|
||||
return (0);
|
||||
}
|
||||
if (newp == NULL)
|
||||
{
|
||||
*terrno = ENOMEM;
|
||||
return close_and_return_error (statp, resplen2);
|
||||
}
|
||||
*thisanssizp = MAXPACKET;
|
||||
*thisansp = newp;
|
||||
if (thisansp == ansp2)
|
||||
@@ -910,8 +921,7 @@ send_vc(res_state statp,
|
||||
Dprint(statp->options & RES_DEBUG,
|
||||
(stdout, ";; undersized: %d\n", len));
|
||||
*terrno = EMSGSIZE;
|
||||
__res_iclose(statp, false);
|
||||
return (0);
|
||||
return close_and_return_error (statp, resplen2);
|
||||
}
|
||||
|
||||
cp = *thisansp;
|
||||
@@ -922,8 +932,7 @@ send_vc(res_state statp,
|
||||
if (__glibc_unlikely (n <= 0)) {
|
||||
*terrno = errno;
|
||||
Perror(statp, stderr, "read(vc)", errno);
|
||||
__res_iclose(statp, false);
|
||||
return (0);
|
||||
return close_and_return_error (statp, resplen2);
|
||||
}
|
||||
if (__glibc_unlikely (truncating)) {
|
||||
/*
|
||||
@@ -1114,7 +1123,11 @@ send_dg(res_state statp,
|
||||
retry_reopen:
|
||||
retval = reopen (statp, terrno, ns);
|
||||
if (retval <= 0)
|
||||
return retval;
|
||||
{
|
||||
if (resplen2 != NULL)
|
||||
*resplen2 = 0;
|
||||
return retval;
|
||||
}
|
||||
retry:
|
||||
evNowTime(&now);
|
||||
evConsTime(&timeout, seconds, 0);
|
||||
@@ -1127,8 +1140,6 @@ send_dg(res_state statp,
|
||||
int recvresp2 = buf2 == NULL;
|
||||
pfd[0].fd = EXT(statp).nssocks[ns];
|
||||
pfd[0].events = POLLOUT;
|
||||
if (resplen2 != NULL)
|
||||
*resplen2 = 0;
|
||||
wait:
|
||||
if (need_recompute) {
|
||||
recompute_resend:
|
||||
@@ -1136,9 +1147,7 @@ send_dg(res_state statp,
|
||||
if (evCmpTime(finish, now) <= 0) {
|
||||
poll_err_out:
|
||||
Perror(statp, stderr, "poll", errno);
|
||||
err_out:
|
||||
__res_iclose(statp, false);
|
||||
return (0);
|
||||
return close_and_return_error (statp, resplen2);
|
||||
}
|
||||
evSubTime(&timeout, &finish, &now);
|
||||
need_recompute = 0;
|
||||
@@ -1185,7 +1194,9 @@ send_dg(res_state statp,
|
||||
}
|
||||
|
||||
*gotsomewhere = 1;
|
||||
return (0);
|
||||
if (resplen2 != NULL)
|
||||
*resplen2 = 0;
|
||||
return 0;
|
||||
}
|
||||
if (n < 0) {
|
||||
if (errno == EINTR)
|
||||
@@ -1253,7 +1264,7 @@ send_dg(res_state statp,
|
||||
|
||||
fail_sendmmsg:
|
||||
Perror(statp, stderr, "sendmmsg", errno);
|
||||
goto err_out;
|
||||
return close_and_return_error (statp, resplen2);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -1271,7 +1282,7 @@ send_dg(res_state statp,
|
||||
if (errno == EINTR || errno == EAGAIN)
|
||||
goto recompute_resend;
|
||||
Perror(statp, stderr, "send", errno);
|
||||
goto err_out;
|
||||
return close_and_return_error (statp, resplen2);
|
||||
}
|
||||
just_one:
|
||||
if (nwritten != 0 || buf2 == NULL || single_request)
|
||||
@@ -1349,7 +1360,7 @@ send_dg(res_state statp,
|
||||
goto wait;
|
||||
}
|
||||
Perror(statp, stderr, "recvfrom", errno);
|
||||
goto err_out;
|
||||
return close_and_return_error (statp, resplen2);
|
||||
}
|
||||
*gotsomewhere = 1;
|
||||
if (__glibc_unlikely (*thisresplenp < HFIXEDSZ)) {
|
||||
@@ -1360,7 +1371,7 @@ send_dg(res_state statp,
|
||||
(stdout, ";; undersized: %d\n",
|
||||
*thisresplenp));
|
||||
*terrno = EMSGSIZE;
|
||||
goto err_out;
|
||||
return close_and_return_error (statp, resplen2);
|
||||
}
|
||||
if ((recvresp1 || hp->id != anhp->id)
|
||||
&& (recvresp2 || hp2->id != anhp->id)) {
|
||||
@@ -1409,7 +1420,7 @@ send_dg(res_state statp,
|
||||
? *thisanssizp : *thisresplenp);
|
||||
/* record the error */
|
||||
statp->_flags |= RES_F_EDNS0ERR;
|
||||
goto err_out;
|
||||
return close_and_return_error (statp, resplen2);
|
||||
}
|
||||
#endif
|
||||
if (!(statp->options & RES_INSECURE2)
|
||||
@@ -1461,10 +1472,10 @@ send_dg(res_state statp,
|
||||
goto wait;
|
||||
}
|
||||
|
||||
__res_iclose(statp, false);
|
||||
/* don't retry if called from dig */
|
||||
if (!statp->pfcode)
|
||||
return (0);
|
||||
return close_and_return_error (statp, resplen2);
|
||||
__res_iclose(statp, false);
|
||||
}
|
||||
if (anhp->rcode == NOERROR && anhp->ancount == 0
|
||||
&& anhp->aa == 0 && anhp->ra == 0 && anhp->arcount == 0) {
|
||||
@@ -1486,6 +1497,8 @@ send_dg(res_state statp,
|
||||
__res_iclose(statp, false);
|
||||
// XXX if we have received one reply we could
|
||||
// XXX use it and not repeat it over TCP...
|
||||
if (resplen2 != NULL)
|
||||
*resplen2 = 0;
|
||||
return (1);
|
||||
}
|
||||
/* Mark which reply we received. */
|
||||
@@ -1501,21 +1514,22 @@ send_dg(res_state statp,
|
||||
__res_iclose (statp, false);
|
||||
retval = reopen (statp, terrno, ns);
|
||||
if (retval <= 0)
|
||||
return retval;
|
||||
{
|
||||
if (resplen2 != NULL)
|
||||
*resplen2 = 0;
|
||||
return retval;
|
||||
}
|
||||
pfd[0].fd = EXT(statp).nssocks[ns];
|
||||
}
|
||||
}
|
||||
goto wait;
|
||||
}
|
||||
/*
|
||||
* All is well, or the error is fatal. Signal that the
|
||||
* next nameserver ought not be tried.
|
||||
*/
|
||||
/* All is well. We have received both responses (if
|
||||
two responses were requested). */
|
||||
return (resplen);
|
||||
} else if (pfd[0].revents & (POLLERR | POLLHUP | POLLNVAL)) {
|
||||
/* Something went wrong. We can stop trying. */
|
||||
goto err_out;
|
||||
}
|
||||
} else if (pfd[0].revents & (POLLERR | POLLHUP | POLLNVAL))
|
||||
/* Something went wrong. We can stop trying. */
|
||||
return close_and_return_error (statp, resplen2);
|
||||
else {
|
||||
/* poll should not have returned > 0 in this case. */
|
||||
abort ();
|
||||
|
||||
@@ -58,7 +58,7 @@ tests := tstscanf test_rdwr test-popen tstgetln test-fseek \
|
||||
scanf16 scanf17 tst-setvbuf1 tst-grouping bug23 bug24 \
|
||||
bug-vfprintf-nargs tst-long-dbl-fphex tst-fphex-wide tst-sprintf3 \
|
||||
bug25 tst-printf-round bug23-2 bug23-3 bug23-4 bug26 tst-fmemopen3 \
|
||||
tst-printf-bz18872
|
||||
tst-printf-bz18872 tst-fmemopen4
|
||||
|
||||
test-srcs = tst-unbputc tst-printf
|
||||
|
||||
|
||||
+32
-19
@@ -209,9 +209,9 @@ hack_digit (struct hack_digit_param *p)
|
||||
}
|
||||
|
||||
int
|
||||
___printf_fp (FILE *fp,
|
||||
const struct printf_info *info,
|
||||
const void *const *args)
|
||||
__printf_fp_l (FILE *fp, locale_t loc,
|
||||
const struct printf_info *info,
|
||||
const void *const *args)
|
||||
{
|
||||
/* The floating-point value to output. */
|
||||
union
|
||||
@@ -263,18 +263,19 @@ ___printf_fp (FILE *fp,
|
||||
/* Figure out the decimal point character. */
|
||||
if (info->extra == 0)
|
||||
{
|
||||
decimal = _NL_CURRENT (LC_NUMERIC, DECIMAL_POINT);
|
||||
decimalwc = _NL_CURRENT_WORD (LC_NUMERIC, _NL_NUMERIC_DECIMAL_POINT_WC);
|
||||
decimal = _nl_lookup (loc, LC_NUMERIC, DECIMAL_POINT);
|
||||
decimalwc = _nl_lookup_word
|
||||
(loc, LC_NUMERIC, _NL_NUMERIC_DECIMAL_POINT_WC);
|
||||
}
|
||||
else
|
||||
{
|
||||
decimal = _NL_CURRENT (LC_MONETARY, MON_DECIMAL_POINT);
|
||||
decimal = _nl_lookup (loc, LC_MONETARY, MON_DECIMAL_POINT);
|
||||
if (*decimal == '\0')
|
||||
decimal = _NL_CURRENT (LC_NUMERIC, DECIMAL_POINT);
|
||||
decimalwc = _NL_CURRENT_WORD (LC_MONETARY,
|
||||
decimal = _nl_lookup (loc, LC_NUMERIC, DECIMAL_POINT);
|
||||
decimalwc = _nl_lookup_word (loc, LC_MONETARY,
|
||||
_NL_MONETARY_DECIMAL_POINT_WC);
|
||||
if (decimalwc == L'\0')
|
||||
decimalwc = _NL_CURRENT_WORD (LC_NUMERIC,
|
||||
decimalwc = _nl_lookup_word (loc, LC_NUMERIC,
|
||||
_NL_NUMERIC_DECIMAL_POINT_WC);
|
||||
}
|
||||
/* The decimal point character must not be zero. */
|
||||
@@ -284,9 +285,9 @@ ___printf_fp (FILE *fp,
|
||||
if (info->group)
|
||||
{
|
||||
if (info->extra == 0)
|
||||
grouping = _NL_CURRENT (LC_NUMERIC, GROUPING);
|
||||
grouping = _nl_lookup (loc, LC_NUMERIC, GROUPING);
|
||||
else
|
||||
grouping = _NL_CURRENT (LC_MONETARY, MON_GROUPING);
|
||||
grouping = _nl_lookup (loc, LC_MONETARY, MON_GROUPING);
|
||||
|
||||
if (*grouping <= 0 || *grouping == CHAR_MAX)
|
||||
grouping = NULL;
|
||||
@@ -296,19 +297,20 @@ ___printf_fp (FILE *fp,
|
||||
if (wide)
|
||||
{
|
||||
if (info->extra == 0)
|
||||
thousands_sepwc =
|
||||
_NL_CURRENT_WORD (LC_NUMERIC, _NL_NUMERIC_THOUSANDS_SEP_WC);
|
||||
thousands_sepwc = _nl_lookup_word
|
||||
(loc, LC_NUMERIC, _NL_NUMERIC_THOUSANDS_SEP_WC);
|
||||
else
|
||||
thousands_sepwc =
|
||||
_NL_CURRENT_WORD (LC_MONETARY,
|
||||
_nl_lookup_word (loc, LC_MONETARY,
|
||||
_NL_MONETARY_THOUSANDS_SEP_WC);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (info->extra == 0)
|
||||
thousands_sep = _NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP);
|
||||
thousands_sep = _nl_lookup (loc, LC_NUMERIC, THOUSANDS_SEP);
|
||||
else
|
||||
thousands_sep = _NL_CURRENT (LC_MONETARY, MON_THOUSANDS_SEP);
|
||||
thousands_sep = _nl_lookup
|
||||
(loc, LC_MONETARY, MON_THOUSANDS_SEP);
|
||||
}
|
||||
|
||||
if ((wide && thousands_sepwc == L'\0')
|
||||
@@ -1171,9 +1173,11 @@ ___printf_fp (FILE *fp,
|
||||
size_t decimal_len;
|
||||
size_t thousands_sep_len;
|
||||
wchar_t *copywc;
|
||||
size_t factor = (info->i18n
|
||||
? _NL_CURRENT_WORD (LC_CTYPE, _NL_CTYPE_MB_CUR_MAX)
|
||||
: 1);
|
||||
size_t factor;
|
||||
if (info->i18n)
|
||||
factor = _nl_lookup_word (loc, LC_CTYPE, _NL_CTYPE_MB_CUR_MAX);
|
||||
else
|
||||
factor = 1;
|
||||
|
||||
decimal_len = strlen (decimal);
|
||||
|
||||
@@ -1244,8 +1248,17 @@ ___printf_fp (FILE *fp,
|
||||
}
|
||||
return done;
|
||||
}
|
||||
libc_hidden_def (__printf_fp_l)
|
||||
|
||||
int
|
||||
___printf_fp (FILE *fp, const struct printf_info *info,
|
||||
const void *const *args)
|
||||
{
|
||||
return __printf_fp_l (fp, _NL_CURRENT_LOCALE, info, args);
|
||||
}
|
||||
ldbl_hidden_def (___printf_fp, __printf_fp)
|
||||
ldbl_strong_alias (___printf_fp, __printf_fp)
|
||||
|
||||
|
||||
/* Return the number of extra grouping characters that will be inserted
|
||||
into a number with INTDIG_MAX integer digits. */
|
||||
|
||||
@@ -25,8 +25,13 @@ static void
|
||||
print_buffer (const char *s, size_t n)
|
||||
{
|
||||
size_t i;
|
||||
printf ("{");
|
||||
for (i=0; i<n; ++i)
|
||||
printf ("0x%02X (%c), ", s[i], s[i]);
|
||||
{
|
||||
printf ("0x%02X (%c)", s[i], s[i]);
|
||||
if (i != n)
|
||||
printf (", ");
|
||||
}
|
||||
}
|
||||
|
||||
/* This test check append mode initial position (a/a+) based on POSIX defition
|
||||
@@ -185,6 +190,112 @@ do_test_read_seek_negative (void)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
do_test_write_append_2 (const char *str)
|
||||
{
|
||||
char buf[10];
|
||||
size_t strn = strlen (str);
|
||||
strcpy (buf, str);
|
||||
|
||||
FILE *fp = fmemopen (buf, sizeof (buf), "a+");
|
||||
size_t r = ftell (fp);
|
||||
size_t e = strlen (buf);
|
||||
if (r != e)
|
||||
{
|
||||
printf ("%s: ftell returned %zu, expected %zu\n", __FUNCTION__, r, e);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (fseek (fp, 0, SEEK_SET) == -1)
|
||||
{
|
||||
printf ("%s: fseek returned -1\n", __FUNCTION__);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int gr;
|
||||
for (int i=0; i<strn; ++i)
|
||||
{
|
||||
if ((gr = getc (fp)) != str[i])
|
||||
{
|
||||
printf ("%s: getc failed returned %d, expected %d\n", __FUNCTION__,
|
||||
gr, str[i]);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if ((gr = getc (fp)) != EOF)
|
||||
{
|
||||
printf ("%s: getc failed returned %d, expected EOF\n", __FUNCTION__,
|
||||
gr);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (fseek (fp, e+1, SEEK_SET) == -1)
|
||||
{
|
||||
printf ("%s: fseek returned -1\n", __FUNCTION__);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ((r = ftell (fp)) != e+1)
|
||||
{
|
||||
printf ("%s: ftell returned %zu, expected %zu\n", __FUNCTION__, r, e+1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ((gr = getc (fp)) != EOF)
|
||||
{
|
||||
printf ("%s: getc failed returned %i\n", __FUNCTION__, gr);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Check if internal position is not changed with a getc returning EOF. */
|
||||
if ((r = ftell (fp)) != e+1)
|
||||
{
|
||||
printf ("%s: ftell returned %zu, expected %zu\n", __FUNCTION__, r, e+1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (fseek (fp, 0, SEEK_CUR) == -1)
|
||||
{
|
||||
printf ("%s: fseek returned -1\n", __FUNCTION__);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* This should be overwritten by fprintf + fflush. */
|
||||
buf[e+2] = 'X';
|
||||
|
||||
if ((r = fprintf (fp, "%d", 101)) != 3)
|
||||
{
|
||||
printf ("%s: fprintf returned %zu, expected %d\n", __FUNCTION__, r, 3);
|
||||
return 1;
|
||||
}
|
||||
|
||||
fflush (fp);
|
||||
|
||||
/* Check if internal position is changed by 3 (strlen of '101'). */
|
||||
if ((r = ftell (fp)) != e+3)
|
||||
{
|
||||
printf ("%s: ftell returned %zu, expected %zu\n", __FUNCTION__, r, e+3);
|
||||
return 1;
|
||||
}
|
||||
|
||||
char exp[20];
|
||||
sprintf (exp, "%s%d", str, 101);
|
||||
if (memcmp (buf, exp, strlen (exp)) != 0)
|
||||
{
|
||||
printf ("%s: check failed:", __FUNCTION__);
|
||||
printf ("\nexpected: ");
|
||||
print_buffer (buf, sizeof (buf));
|
||||
printf ("\nbuffer: ");
|
||||
print_buffer (exp, sizeof (exp));
|
||||
printf ("\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
@@ -199,6 +310,11 @@ do_test (void)
|
||||
|
||||
ret += do_test_read_seek_negative ();
|
||||
|
||||
/* First test plus addend will fit in the define buffer of size 10. */
|
||||
ret += do_test_write_append_2 ("test");
|
||||
/* The second test will also fit, but not the final '\0'. */
|
||||
ret += do_test_write_append_2 ("testing");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
/* fmemopen tests for BZ#1930 and BZ#20005.
|
||||
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 <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
|
||||
/* Check if fflush does not reset the file position. */
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
char buffer[500] = "x";
|
||||
|
||||
FILE *stream = fmemopen (buffer, sizeof (buffer), "r+");
|
||||
if (stream == NULL)
|
||||
{
|
||||
printf ("error: fmemopen could not open stream\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
const char test[] = "test";
|
||||
|
||||
size_t r = fwrite (test, sizeof (char), sizeof (test), stream);
|
||||
if (r != sizeof (test))
|
||||
{
|
||||
printf ("error: fwrite returned %zu, expected %zu\n", r, sizeof(test));
|
||||
return 1;
|
||||
}
|
||||
|
||||
r = ftell (stream);
|
||||
if (r != sizeof (test))
|
||||
{
|
||||
printf ("error: ftell return %zu, expected %zu\n", r, sizeof(test));
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (fflush (stream) != 0)
|
||||
{
|
||||
printf ("error: fflush failed\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
r = ftell (stream);
|
||||
if (r != sizeof (test))
|
||||
{
|
||||
printf ("error: ftell return %zu, expected %zu\n", r, sizeof(test));
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define TEST_FUNCTION do_test ()
|
||||
#include "../test-skeleton.c"
|
||||
+4
-2
@@ -76,7 +76,7 @@ tests := tst-strtol tst-strtod testmb testrand testsort testdiv \
|
||||
tst-secure-getenv tst-strtod-overflow tst-strtod-round \
|
||||
tst-tininess tst-strtod-underflow tst-tls-atexit \
|
||||
tst-setcontext3 tst-tls-atexit-nodelete \
|
||||
tst-strtol-locale tst-strtod-nan-locale
|
||||
tst-strtol-locale tst-strtod-nan-locale tst-strfmon_l
|
||||
tests-static := tst-secure-getenv
|
||||
|
||||
modules-names = tst-tls-atexit-lib
|
||||
@@ -126,7 +126,8 @@ include ../Rules
|
||||
|
||||
ifeq ($(run-built-tests),yes)
|
||||
LOCALES := cs_CZ.UTF-8 de_DE.UTF-8 en_US.ISO-8859-1 tr_TR.UTF-8 \
|
||||
tr_TR.ISO-8859-9
|
||||
tr_TR.ISO-8859-9 tg_TJ.UTF-8 te_IN.UTF-8 bn_IN.UTF-8 \
|
||||
el_GR.UTF-8
|
||||
include ../gen-locales.mk
|
||||
|
||||
$(objpfx)bug-strtod2.out: $(gen-locales)
|
||||
@@ -137,6 +138,7 @@ $(objpfx)tst-strtod4.out: $(gen-locales)
|
||||
$(objpfx)tst-strtod5.out: $(gen-locales)
|
||||
$(objpfx)tst-strtol-locale.out: $(gen-locales)
|
||||
$(objpfx)tst-strtod-nan-locale.out: $(gen-locales)
|
||||
$(objpfx)tst-strfmon_l.out: $(gen-locales)
|
||||
endif
|
||||
|
||||
# Testdir has to be named stdlib and needs to be writable
|
||||
|
||||
+13
-11
@@ -278,18 +278,20 @@ unsetenv (const char *name)
|
||||
ep = __environ;
|
||||
if (ep != NULL)
|
||||
while (*ep != NULL)
|
||||
if (!strncmp (*ep, name, len) && (*ep)[len] == '=')
|
||||
{
|
||||
/* Found it. Remove this pointer by moving later ones back. */
|
||||
char **dp = ep;
|
||||
{
|
||||
if (!strncmp (*ep, name, len) && (*ep)[len] == '=')
|
||||
{
|
||||
/* Found it. Remove this pointer by moving later ones back. */
|
||||
char **dp = ep;
|
||||
|
||||
do
|
||||
dp[0] = dp[1];
|
||||
while (*dp++);
|
||||
/* Continue the loop in case NAME appears again. */
|
||||
}
|
||||
else
|
||||
++ep;
|
||||
do
|
||||
dp[0] = dp[1];
|
||||
while (*dp++);
|
||||
/* Continue the loop in case NAME appears again. */
|
||||
}
|
||||
else
|
||||
++ep;
|
||||
}
|
||||
|
||||
UNLOCK;
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user