Compare commits

...
Author SHA1 Message Date
Joseph Myers 0a62a5c401 Fix powerpc software sqrt (bug 17964).
As Adhemerval noted in
<https://sourceware.org/ml/libc-alpha/2015-01/msg00451.html>, the
powerpc sqrt implementation for when _ARCH_PPCSQ is not defined is
inaccurate in some cases.

The problem is that this code relies on fused multiply-add, and relies
on the compiler contracting a * b + c to get a fused operation.  But
sysdeps/ieee754/dbl-64/Makefile disables contraction for e_sqrt.c,
because the implementation in that directory relies on *not* having
contracted operations.

While it would be possible to arrange makefiles so that an earlier
sysdeps directory can disable the setting in
sysdeps/ieee754/dbl-64/Makefile, it seems a lot cleaner to make the
dependence on fused operations explicit in the .c file.  GCC 4.6
introduced support for __builtin_fma on powerpc and other
architectures with such instructions, so we can rely on that; this
patch duly makes the code use __builtin_fma for all such fused
operations.

Tested for powerpc32 (hard float).

2015-02-12  Joseph Myers  <joseph@codesourcery.com>

	[BZ #17964]
	* sysdeps/powerpc/fpu/e_sqrt.c (__slow_ieee754_sqrt): Use
	__builtin_fma instead of relying on contraction of a * b + c.

(cherry picked from commit e8bd5286c6)
2017-02-20 22:04:52 +01:00
Adhemerval Zanella a0b2d5b252 powerpc: Fix fsqrt build in libm [BZ#16576]
Some powerpc64 processors (e5500 core for instance) does not provide the
fsqrt instruction, however current check to use in math_private.h is
__WORDSIZE and _ARCH_PWR4 (ISA 2.02).  This is patch change it to use
the compiler flag _ARCH_PPCSQ (which is the same condition GCC uses to
decide whether to generate fsqrt instruction).

It fixes BZ#16576.

(cherry picked from commit 08cee2a464)
2016-11-21 17:13:40 +01:00
Andreas Schwab 7a609588a0 arm: mark __startcontext as .cantunwind (bug 20435)
__startcontext marks the bottom of the call stack of the contexts created
by makecontext.

(cherry picked from commit 9e2ff6c9cc)

Also includes the NEWS update, cherry-picked from commits
056dd72af8 and
4d047efdbc.
2016-08-19 09:22:19 +02:00
Eric Rannaud 9d328da0a8 linux: open and openat ignore 'mode' with O_TMPFILE in flags
Both open and openat load their last argument 'mode' lazily, using
va_arg() only if O_CREAT is found in oflag. This is wrong, mode is also
necessary if O_TMPFILE is in oflag.

By chance on x86_64, the problem wasn't evident when using O_TMPFILE
with open, as the 3rd argument of open, even when not loaded with
va_arg, is left untouched in RDX, where the syscall expects it.

However, openat was not so lucky, and O_TMPFILE couldn't be used: mode
is the 4th argument, in RCX, but the syscall expects its 4th argument in
a different register than the glibc wrapper, in R10.

Introduce a macro __OPEN_NEEDS_MODE (oflag) to test if either O_CREAT or
O_TMPFILE is set in oflag.

Tested on Linux x86_64.

	[BZ #17523]
	* io/fcntl.h (__OPEN_NEEDS_MODE): New macro.
	* io/bits/fcntl2.h (open): Use it.
	(openat): Likewise.
	* io/open.c (__libc_open): Likewise.
	* io/open64.c (__libc_open64): Likewise.
	* io/open64_2.c (__open64_2): Likewise.
	* io/open_2.c (__open_2): Likewise.
	* io/openat.c (__openat): Likewise.
	* io/openat64.c (__openat64): Likewise.
	* io/openat64_2.c (__openat64_2): Likewise.
	* io/openat_2.c (__openat_2): Likewise.
	* sysdeps/mach/hurd/open.c (__libc_open): Likewise.
	* sysdeps/mach/hurd/openat.c (__openat): Likewise.
	* sysdeps/posix/open64.c (__libc_open64): Likewise.
	* sysdeps/unix/sysv/linux/dl-openat64.c (openat64): Likewise.
	* ports/sysdeps/unix/sysv/linux/generic/open.c (__libc_open): Likewise.
	(__open_nocancel): Likewise.
	* ports/sysdeps/unix/sysv/linux/generic/open64.c (__libc_open64):
	Likewise.
	* sysdeps/unix/sysv/linux/open64.c (__libc_open64): Likewise.
	* sysdeps/unix/sysv/linux/openat.c (__OPENAT): Likewise.

(cherry picked from commit 65f6f938cd)
2016-08-14 18:16:12 +02:00
Florian Weimer 66986dec45 Harden tls_dtor_list with pointer mangling [BZ #19018]
(cherry picked from commit f586e13286)

Conflicts:
	NEWS
	stdlib/cxa_thread_atexit_impl.c
2016-07-11 13:53:12 -03:00
Florian Weimer dea992adae Always enable pointer guard [BZ #18928]
Honoring the LD_POINTER_GUARD environment variable in AT_SECURE mode
has security implications.  This commit enables pointer guard
unconditionally, and the environment variable is now ignored.

        [BZ #18928]
        * sysdeps/generic/ldsodefs.h (struct rtld_global_ro): Remove
        _dl_pointer_guard member.
        * elf/rtld.c (_rtld_global_ro): Remove _dl_pointer_guard
        initializer.
        (security_init): Always set up pointer guard.
        (process_envvars): Do not process LD_POINTER_GUARD.

(cherry picked from commit a014cecd82)

Conflicts:
	NEWS
2016-07-11 13:53:03 -03:00
Leonhard Holz 1a43fd3240 Fix memory handling in strxfrm_l [BZ #16009]
[Modified from the original email by Siddhesh Poyarekar]

This patch solves bug #16009 by implementing an additional path in
strxfrm that does not depend on caching the weight and rule indices.

In detail the following changed:

* The old main loop was factored out of strxfrm_l into the function
do_xfrm_cached to be able to alternativly use the non-caching version
do_xfrm.

* strxfrm_l allocates a a fixed size array on the stack. If this is not
sufficiant to store the weight and rule indices, the non-caching path is
taken. As the cache size is not dependent on the input there can be no
problems with integer overflows or stack allocations greater than
__MAX_ALLOCA_CUTOFF. Note that malloc-ing is not possible because the
definition of strxfrm does not allow an oom errorhandling.

* The uncached path determines the weight and rule index for every char
and for every pass again.

* Passing all the locale data array by array resulted in very long
parameter lists, so I introduced a structure that holds them.

* Checking for zero src string has been moved a bit upwards, it is
before the locale data initialization now.

* To verify that the non-caching path works correct I added a test run
to localedata/sort-test.sh & localedata/xfrm-test.c where all strings
are patched up with spaces so that they are too large for the caching path.

(cherry picked from commit 0f9e585480)

Conflicts:
	NEWS
	string/strxfrm_l.c
2016-07-11 13:52:20 -03:00
Florian Weimer ce92632d12 CVE-2016-4429: sunrpc: Do not use alloca in clntudp_call [BZ #20112]
The call is technically in a loop, and under certain circumstances
(which are quite difficult to reproduce in a test case), alloca
can be invoked repeatedly during a single call to clntudp_call.
As a result, the available stack space can be exhausted (even
though individual alloca sizes are bounded implicitly by what
can fit into a UDP packet, as a side effect of the earlier
successful send operation).

(cherry picked from commit bc779a1a5b)
2016-05-31 12:48:41 +02:00
Florian Weimer 10d268070a resolv: Always set *resplen2 out parameter in send_dg [BZ #19791]
Since commit 44d20bca52 (Implement
second fallback mode for DNS requests), there is a code path which
returns early, before *resplen2 is initialized.  This happens if the
name server address is immediately recognized as invalid (because of
lack of protocol support, or if it is a broadcast address such
255.255.255.255, or another invalid address).

If this happens and *resplen2 was non-zero (which is the case if a
previous query resulted in a failure), __libc_res_nquery would reuse
an existing second answer buffer.  This answer has been previously
identified as unusable (for example, it could be an NXDOMAIN
response).  Due to the presence of a second answer, no name server
switching will occur.  The result is a name resolution failure,
although a successful resolution would have been possible if name
servers have been switched and queries had proceeded along the search
path.

The above paragraph still simplifies the situation.  Before glibc
2.23, if the second answer needed malloc, the stub resolver would
still attempt to reuse the second answer, but this is not possible
because __libc_res_nsearch has freed it, after the unsuccessful call
to __libc_res_nquerydomain, and set the buffer pointer to NULL.  This
eventually leads to an assertion failure in __libc_res_nquery:

	/* Make sure both hp and hp2 are defined */
	assert((hp != NULL) && (hp2 != NULL));

If assertions are disabled, the consequence is a NULL pointer
dereference on the next line.

Starting with glibc 2.23, as a result of commit
e9db92d3ac (CVE-2015-7547: getaddrinfo()
stack-based buffer overflow (Bug 18665)), the second answer is always
allocated with malloc.  This means that the assertion failure happens
with small responses as well because there is no buffer to reuse, as
soon as there is a name resolution failure which triggers a search for
an answer along the search path.

This commit addresses the issue by ensuring that *resplen2 is
initialized before the send_dg function returns.

This commit also addresses a bug where an invalid second reply is
incorrectly returned as a valid to the caller.

(cherry picked from commit b66d837bb5)
2016-05-23 00:30:26 +02:00
Carlos O'Donell c08e8bd0ef CVE-2015-7547: getaddrinfo() stack-based buffer overflow (Bug 18665).
* A stack-based buffer overflow was found in libresolv when invoked from
  libnss_dns, allowing specially crafted DNS responses to seize control
  of execution flow in the DNS client.  The buffer overflow occurs in
  the functions send_dg (send datagram) and send_vc (send TCP) for the
  NSS module libnss_dns.so.2 when calling getaddrinfo with AF_UNSPEC
  family.  The use of AF_UNSPEC triggers the low-level resolver code to
  send out two parallel queries for A and AAAA.  A mismanagement of the
  buffers used for those queries could result in the response of a query
  writing beyond the alloca allocated buffer created by
  _nss_dns_gethostbyname4_r.  Buffer management is simplified to remove
  the overflow.  Thanks to the Google Security Team and Red Hat for
  reporting the security impact of this issue, and Robert Holiday of
  Ciena for reporting the related bug 18665. (CVE-2015-7547)

See also:
https://sourceware.org/ml/libc-alpha/2016-02/msg00416.html
https://sourceware.org/ml/libc-alpha/2016-02/msg00418.html

(cherry picked from commit e9db92d3ac)
2016-05-17 14:16:37 +02:00
Florian Weimer 762aafec34 CVE-2016-3706: getaddrinfo: stack overflow in hostent conversion [BZ #20010]
When converting a struct hostent response to struct gaih_addrtuple, the
gethosts macro (which is called from gaih_inet) used alloca, without
malloc fallback for large responses.  This commit changes this code to
use calloc unconditionally.

This commit also consolidated a second hostent-to-gaih_addrtuple
conversion loop (in gaih_inet) to use the new conversion function.

(cherry picked from commit 4ab2ab03d4)
2016-05-12 17:33:52 +02:00
Florian Weimer e97fb84811 CVE-2016-1234: glob: Do not copy d_name field of struct dirent [BZ #19779]
Instead, we store the data we need from the return value of
readdir in an object of the new type struct readdir_result.
This type is independent of the layout of struct dirent.

(cherry picked from commit 5171f3079f)
2016-05-12 17:32:07 +02:00
Florian Weimer 5ae82aa4bf glob: Simplify the interface for the GLOB_ALTDIRFUNC callback gl_readdir
Previously, application code had to set up the d_namlen member if
the target supported it, involving conditional compilation.  After
this change, glob will use the length of the string in d_name instead
of d_namlen to determine the file name length.  All glibc targets
provide the d_type and d_ino members, and setting them as needed for
gl_readdir is straightforward.

Changing the behavior with regards to d_ino is left to a future
cleanup.

(cherry picked from commit 137fe72eca)
2016-05-12 09:44:15 +02:00
Stefan Liebler 05cc5bbd3c S390: Fix "backtrace() returns infinitely deep stack frames with makecontext()" [BZ #18508].
On s390/s390x backtrace(buffer, size) returns the series of called functions until
"makecontext_ret" and additional entries (up to "size") with "makecontext_ret".
GDB-backtrace is also warning:
"Backtrace stopped: previous frame identical to this frame (corrupt stack?)"

To reproduce this scenario you have to setup a new context with makecontext()
and activate it with setcontext(). See e.g. cf() function in testcase stdlib/tst-makecontext.c.
Or see bug in libgo "Bug 66303 - runtime.Caller() returns infinitely deep stack frames
on s390x " (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66303).

This patch omits the cfi_startproc/cfi_endproc directives in ENTRY/END macro of
__makecontext_ret. Thus no frame information is generated in .eh_frame and backtrace
stops after __makecontext_ret. There is also no .eh_frame info for _start or
thread_start functions.

ChangeLog:

	[BZ #18508]
	* stdlib/Makefile ($(objpfx)tst-makecontext3):
	Depend on $(libdl).
	* stdlib/tst-makecontext.c (cf): Test if _Unwind_Backtrace
	is not called infinitely times.
	(backtrace_helper): New function.
	(trace_arg): New struct.
	(st1): Enlarge stack size.
	* sysdeps/unix/sysv/linux/s390/s390-32/__makecontext_ret.S:
	(__makecontext_ret): Omit cfi_startproc and cfi_endproc.
	* sysdeps/unix/sysv/linux/s390/s390-64/__makecontext_ret.S:
	Likewise.

(cherry picked from commit 890b7a4b33)
2016-04-28 10:21:58 +02:00
Stefan Liebler aa60d72514 S/390: Fix setcontext/swapcontext which are not restoring sigmask. [BZ #18080]
This patch uses sigprocmask(SIG_SETMASK) instead of SIG_BLOCK
in setcontext, swapcontext.

(cherry picked from commit 2e807f2959)
2016-04-28 10:12:05 +02:00
Florian Weimer a02f3e7959 CVE-2016-3075: Stack overflow in _nss_dns_getnetbyname_r [BZ #19879]
The defensive copy is not needed because the name may not alias the
output buffer.

(cherry picked from commit 317b199b4a)
2016-04-27 13:14:47 +02:00
Florian Weimer 78c76f7374 hsearch_r: Apply VM size limit in test case
(cherry picked from commit f34f146e68)
2016-02-16 21:57:29 +01:00
Florian Weimer 3c9e8d9477 Improve check against integer wraparound in hcreate_r [BZ #18240]
(cherry picked from commit bae7c7c764)
2016-01-29 18:42:36 +01:00
Ondřej Bílka b5cba5cff9 Handle overflow in __hcreate_r
Hi,

As in bugzilla entry there is overflow in hsearch when looking for prime
number as SIZE_MAX - 1 is divisible by 5. We fix that by rejecting large
inputs before looking for prime.

	* misc/hsearch_r.c (__hcreate_r): Handle overflow.

(cherry picked from commit 2f5c175055)
2016-01-29 18:38:16 +01:00
Paul Pluzhnikov fd6e33ebd1 Fix BZ #18985 -- out of range data to strftime() causes a segfault
(cherry picked from commit d36c75fc0d)
2016-01-27 17:03:18 +01:00
Paul Pluzhnikov 4d558c76f3 Fix trailing space.
(cherry picked from commit 7565d2a862)
2016-01-27 17:00:47 +01:00
Paul Pluzhnikov e12c42df43 Fix BZ #17905
(cherry picked from commit 0f58539030)
2016-01-27 17:00:06 +01:00
Siddhesh Poyarekar b963026c07 Avoid overlapping addresses to stpcpy calls in nscd (BZ #16760)
Calls to stpcpy from nscd netgroups code will have overlapping source
and destination when all three values in the returned triplet are
non-NULL and in the expected (host,user,domain) order.  This is seen
in valgrind as:

==3181== Source and destination overlap in stpcpy(0x19973b48, 0x19973b48)
==3181==    at 0x4C2F30A: stpcpy (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==3181==    by 0x12567A: addgetnetgrentX (string3.h:111)
==3181==    by 0x12722D: addgetnetgrent (netgroupcache.c:665)
==3181==    by 0x11114C: nscd_run_worker (connections.c:1338)
==3181==    by 0x4E3C102: start_thread (pthread_create.c:309)
==3181==    by 0x59B81AC: clone (clone.S:111)
==3181==

Fix this by using memmove instead of stpcpy.

(cherry picked from commit ea7d8b95e2)
2015-12-20 17:43:27 +01:00
Siddhesh Poyarekar 56b2cf5633 Return NULL for wildcard values in getnetgrent from nscd (BZ #16759)
getnetgrent is supposed to return NULL for values that are wildcards
in the (host, user, domain) triplet.  This works correctly with nscd
disabled, but with it enabled, it returns a blank ("") instead of a
NULL.  This is easily seen with the output of `getent netgroup foonet`
for a netgroup foonet defined as follows in /etc/netgroup:

    foonet (,foo,)

The output with nscd disabled is:

    foonet ( ,foo,)

while with nscd enabled, it is:

    foonet (,foo,)

The extra space with nscd disabled is due to the fact that `getent
netgroup` adds it if the return value from getnetgrent is NULL for
either host or user.

(cherry picked from commit dd3022d75e)
2015-12-20 17:42:13 +01:00
Siddhesh Poyarekar 2f3bd411ae Fix nscd lookup for innetgr when netgroup has wildcards (BZ #16758)
nscd works correctly when the request in innetgr is a wildcard,
i.e. when one or more of host, user or domain parameters is NULL.
However, it does not work when the the triplet in the netgroup
definition has a wildcard.  This is easy to reproduce for a triplet
defined as follows:

    foonet (,foo,)

Here, an innetgr call that looks like this:

    innetgr ("foonet", "foohost", "foo", NULL);

should succeed and so should:

    innetgr ("foonet", NULL, "foo", "foodomain");

It does succeed with nscd disabled, but not with nscd enabled.  This
fix adds this additional check for all three parts of the triplet so
that it gives the correct result.

	[BZ #16758]
	* nscd/netgroupcache.c (addinnetgrX): Succeed if triplet has
	blank values.

(cherry picked from commit fbd6b5a405)
2015-12-20 17:40:49 +01:00
Andreas Schwab 60f10f2326 Don't read past end of pattern in fnmatch (BZ #17062)
(cherry picked from commit b3a9f56ba5)

Conflicts:
	NEWS
	posix/Makefile
2015-11-24 11:34:14 -02:00
Florian Weimer 83e9e8b046 CVE-2014-8121: Do not close NSS files database during iteration [BZ #18007]
Robin Hack discovered Samba would enter an infinite loop processing
certain quota-related requests.  We eventually tracked this down to a
glibc issue.

Running a (simplified) test case under strace shows that /etc/passwd
is continuously opened and closed:

…
open("/etc/passwd", O_RDONLY|O_CLOEXEC) = 3
lseek(3, 0, SEEK_CUR)                   = 0
read(3, "root:x:0:0:root:/root:/bin/bash\n"..., 4096) = 2717
lseek(3, 2717, SEEK_SET)                = 2717
close(3)                                = 0
open("/etc/passwd", O_RDONLY|O_CLOEXEC) = 3
lseek(3, 0, SEEK_CUR)                   = 0
lseek(3, 0, SEEK_SET)                   = 0
read(3, "root:x:0:0:root:/root:/bin/bash\n"..., 4096) = 2717
lseek(3, 2717, SEEK_SET)                = 2717
close(3)                                = 0
open("/etc/passwd", O_RDONLY|O_CLOEXEC) = 3
lseek(3, 0, SEEK_CUR)                   = 0
…

The lookup function implementation in
nss/nss_files/files-XXX.c:DB_LOOKUP has code to prevent that.  It is
supposed skip closing the input file if it was already open.

  /* Reset file pointer to beginning or open file.  */			      \
  status = internal_setent (keep_stream);				      \
									      \
  if (status == NSS_STATUS_SUCCESS)					      \
    {									      \
      /* Tell getent function that we have repositioned the file pointer.  */ \
      last_use = getby;							      \
									      \
      while ((status = internal_getent (result, buffer, buflen, errnop	      \
					H_ERRNO_ARG EXTRA_ARGS_VALUE))	      \
	     == NSS_STATUS_SUCCESS)					      \
	{ break_if_match }						      \
									      \
      if (! keep_stream)						      \
	internal_endent ();						      \
    }									      \

keep_stream is initialized from the stayopen flag in internal_setent.
internal_setent is called from the set*ent implementation as:

  status = internal_setent (stayopen);

However, for non-host database, this flag is always 0, per the
STAYOPEN magic in nss/getXXent_r.c.

Thus, the fix is this:

-  status = internal_setent (stayopen);
+  status = internal_setent (1);

This is not a behavioral change even for the hosts database (where the
application can specify the stayopen flag) because with a call to
sethostent(0), the file handle is still not closed in the
implementation of gethostent.

(cherry picked from commit 03d2730b44)

Conflicts:
	ChangeLog
	NEWS
2015-10-19 12:27:37 +02:00
Paul Pluzhnikov 012adb3382 Fix BZ #17269 -- _IO_wstr_overflow integer overflow
(cherry picked from commit bdf1ff052a)

Conflicts:
	ChangeLog
	NEWS
2015-10-19 10:45:23 +02:00
Andreas Schwab fc843f6e48 Fix read past end of pattern in fnmatch (bug 18032)
(cherry picked from commit 4a28f4d55a)

Conflicts:
	ChangeLog
	NEWS
2015-10-19 10:44:00 +02:00
Andreas Schwab 3fd4982429 Don't ignore too long lines in nss_files (BZ #17079)
(cherry picked from commit ac60763eac)

Conflicts:
	ChangeLog
	NEWS
2015-10-18 22:59:08 +02:00
Andreas Schwab b0f0937975 Fix parsing of getai result from nscd for IPv6-only request
(cherry picked from commit 8dc9751764)
2015-10-02 09:21:25 +02:00
Alan Modra b59b0c6c3f Correct DT_PPC64_NUM
[BZ #17153]
	* elf/elf.h (DT_PPC64_NUM): Correct value.
	* NEWS: Add to fixed bug list.

(cherry picked from commit f6c44d4751)

Conflicts:
	NEWS
2015-09-11 16:03:47 -03:00
Andreas Schwab 1e7df7fdef Fix use of half-initialized result in getaddrinfo when using nscd (bug 16743)
This fixes a bug in the way the results from __nscd_getai are collected:
for every returned result a new entry is first added to the
gaih_addrtuple list, but if that result doesn't match the request this
entry remains uninitialized.  So for this non-matching result an extra
result with uninitialized content is returned.

To reproduce (with nscd running):

	$ getent ahostsv4 localhost
	127.0.0.1       STREAM localhost
	127.0.0.1       DGRAM
	127.0.0.1       RAW
	(null)          STREAM
	(null)          DGRAM
	(null)          RAW

(cherry picked from commit a071766ebf)

Conflicts:
	ChangeLog
	NEWS
2015-09-10 12:09:29 +02:00
Arjun Shankar 126e130086 CVE-2015-1781: resolv/nss_dns/dns-host.c buffer overflow [BZ#18287]
(cherry picked from commit 2959eda927)
2015-08-28 22:54:02 +02:00
Andreas Schwab 323e41a8d8 Properly handle forced elision in pthread_mutex_trylock (bug 16657)
(cherry picked from commit b0a3c1640a)
2015-08-28 21:44:41 +02:00
Adhemerval Zanella 980a63b384 PowerPC: Fix gprof entry point for LE
This patch fixes the ELFv2 gprof entry point since the ABI
does not define function descriptors.  It fixes BZ#17213.

Conflicts:
	NEWS
2015-08-24 15:28:04 -03:00
Renlin Li 262365511f [AArch64] End frame record chain correctly. 2014-11-11 15:50:07 +00:00
Florian Weimer daea1a9b2a CVE-2014-6040: Crashes on invalid input in IBM gconv modules [BZ #17325]
These changes are based on the fix for BZ #14134 in commit
6e230d1183.

(cherry picked from commit 41488498b6)

Conflicts:
	NEWS
	iconvdata/Makefile
2014-09-05 22:44:12 +10:00
Florian Weimer b8d0acdb33 __gconv_translit_find: Disable function [BZ #17187]
This functionality has never worked correctly, and the implementation
contained a security vulnerability (CVE-2014-5119).

(cherry picked from commit a1a6a401ab)
(cherry picked from commit f9df71e895)

Conflicts:
	NEWS
2014-09-05 22:44:12 +10:00
Stefan Liebler 92b410973f NEWS: Explain the s390 jmp_buf / ucontext_t ABI change reversal.
(cherry picked from commit 95ee7fb13b)

Typo fix as in commit 45ef66289a and
NEW enty adjusted to reflect revert occuring in 2.19.1 and 2.20.

Conflicts:
	NEWS
2014-09-05 22:44:12 +10:00
Stefan Liebler 424f645c51 S/390: Revert the jmp_buf/ucontext_t ABI change
Backport of commit 2f438e20ab
2014-09-05 22:44:11 +10:00
Florian Weimer 75f66fe467 manual: Update the locale documentation
(cherry picked from commit 5853672669)

Conflicts:
	manual/locale.texi
2014-09-05 22:44:11 +10:00
Florian Weimer ac39af9f19 _nl_find_locale: Improve handling of crafted locale names [BZ #17137]
Prevent directory traversal in locale-related environment variables
(CVE-2014-0475).

(cherry picked from commit 4e8f95a0df)

Addiational backporting fixes:
  Added tst-setlocale3-ENV to localedata/Makefile

Conflicts:
	NEWS
	localedata/Makefile
2014-09-05 22:44:11 +10:00
Florian Weimer 2da15d05c5 setlocale: Use the heap for the copy of the locale argument
This avoids alloca calls with potentially large arguments.

(cherry picked from commit d183645616)
2014-09-05 22:44:10 +10:00
Siddhesh Poyarekar 6ccc1c41f5 Use NSS_STATUS_TRYAGAIN to indicate insufficient buffer (BZ #16878)
The netgroups nss modules in the glibc tree use NSS_STATUS_UNAVAIL
(with errno as ERANGE) when the supplied buffer does not have
sufficient space for the result.  This is wrong, because the canonical
way to indicate insufficient buffer is to set the errno to ERANGE and
the status to NSS_STATUS_TRYAGAIN, as is used by all other modules.

This fixes nscd behaviour when the nss_ldap module returns
NSS_STATUS_TRYAGAIN to indicate that a netgroup entry is too long to
fit into the supplied buffer.

(cherry picked from commit c3ec475c5d)

Conflicts:
	NEWS
2014-09-05 22:44:10 +10:00
Siddhesh Poyarekar 4e27332819 Provide correct buffer length to netgroup queries in nscd (BZ #16695)
The buffer to query netgroup entries is allocated sufficient space for
the netgroup entries and the key to be appended at the end, but it
sends in an incorrect available length to the NSS netgroup query
functions, resulting in overflow of the buffer in some special cases.
The fix here is to factor in the key length when sending the available
buffer and buffer length to the query functions.

(cherry picked from commit c44496df2f)

Conflicts:
	NEWS
2014-09-05 22:44:10 +10:00
Maciej W. Rozycki 9583c35421 [BZ #16046] dl_iterate_phdr static executable test
(cherry picked from commit 257ce7127e)
2014-09-05 22:44:09 +10:00
Andreas Schwab 2ce47f454b Fix another memory leak in regexp compiler (BZ #17069)
(cherry picked from commit aa6ec754f3)

Conflicts:
	NEWS
2014-09-05 22:44:09 +10:00
Andreas Schwab 1f542fe398 Fix memory leak in regexp compiler (BZ #17069)
(cherry picked from commit 4d43ef1e74)

Conflicts:
	posix/Makefile
2014-09-05 22:44:09 +10:00
Andreas Schwab d3b2d64576 Fix invalid file descriptor reuse while sending DNS query (BZ #15946)
(cherry picked from commit f9d2d03254)

Conflicts:
	NEWS
2014-09-05 22:44:08 +10:00
Andreas Schwab 40da893a14 Properly fix memory leak in _nss_dns_gethostbyname4_r with big DNS answer
Instead of trying to guess whether the second buffer needs to be freed
set a flag at the place it is allocated

(cherry picked from commit ab09bf616a)
2014-09-05 22:44:08 +10:00
Ondřej Bílka 3a4f226eaf Deduplicate resolv/nss_dns/dns-host.c
In resolv/nss_dns/dns-host.c one of code path duplicated code after
that. We merge these paths.

(cherry picked from commit ab7ac0f2cf)
2014-09-05 22:44:08 +10:00
Andreas Schwab efbeb31ba5 Fix memory leak in _nss_dns_gethostbyname4_r with big DNS answer
(cherry picked from commit d668061994)

Conflicts:
	NEWS
2014-09-05 22:44:08 +10:00
Andreas Schwab 968b59ad2a Fix unbound stack use in NIS NSS module
(cherry picked from commit 315eb1d86a)

Conflicts:
	NEWS
2014-09-05 22:44:07 +10:00
Allan McRae 29fd33140d Mention CVE-2014-4043 in NEWS
(cherry picked from commit d03efb2f97)

Conflicts:
	NEWS
2014-09-05 22:44:07 +10:00
Stefan Liebler 8ec14bdc9c posix_spawn_faction_addopen: Add missing string.h include directive
This is needed to avoid a PLT call on s390.

(cherry picked from commit 35a5e3e338)
2014-09-05 22:44:06 +10:00
Florian Weimer e698ea2c03 posix_spawn_file_actions_addopen needs to copy the path argument (BZ 17048)
POSIX requires that we make a copy, so we allocate a new string
and free it in posix_spawn_file_actions_destroy.

Reported by David Reid, Alex Gaynor, and Glyph Lefkowitz.  This bug
may have security implications.

(cherry picked from commit 89e435f355)

Conflicts:
	NEWS
2014-06-22 17:11:06 +10:00
Guo Yixuan 344e61df02 Fixed pthread_spin_lock on sparc32/64 (bug 16882)
[BZ #16882]
	* nptl/sysdeps/sparc/sparc32/pthread_spin_lock.S
	(pthread_spin_lock): Branch out of spin loop to proper location.
	* nptl/sysdeps/sparc/sparc64/pthread_spin_lock.S
	(pthread_spin_lock): Likewise.

	* nptl/tst-spin4.c: New test.
	* nptl/Makefile (tests): Add tst-spin4.
2014-06-03 17:59:10 -07:00
Richard Henderson 690bb11f60 aarch64: Merge __local_multiple_threads offset with memory reference
This also highlights that we'd been loading 64-bits instead of
the proper 32-bits.  Caught by the linker as a relocation error,
since the variable happened to be unaligned for 64-bits.

Cherry-pick of a6b3657be6.
2014-05-21 13:24:03 -04:00
Jose E. Marchesi 9e6dad45f7 Fix sparc memcpy data corruption when using niagara2 optimized routines.
* sysdeps/sparc/sparc64/multiarch/memcpy-niagara2.S: Add missing
	membar to avoid block loads/stores to overlap previous stores.
2014-05-17 17:22:29 -04:00
Sami Kerola 1f2d5b7d00 tzselect: use zonedir instead of current working directory
(cherry picked from commit 893b4f3756)
(cherry picked from commit c72399fbc5)

Conflicts:
	timezone/Makefile
2014-05-16 14:49:26 +10:00
Allan McRae e089a3966d Update Swedish translations
(cherry picked from commit d51d659d11)
2014-05-16 14:38:56 +10:00
Aurelien Jarno 30a40bf191 SPARC: add prlimit and prlimit64 in <bits/resource.h> (BZ #16943)
prlimit and prlimit64 have been added in the main <bits/resource.h>, but
not in the SPARC specific version. Fix that.

Note: this is Debian bug#703559, reported by Emilio Pozuelo Monfort
<pochu@debian.org>

(cherry picked from commit d16e6ec7ca)
2014-05-16 00:15:30 +02:00
Aurelien Jarno e918929323 SPARC: add EFD_SEMAPHORE in <bits/eventfd.h> (BZ #16916)
EFD_SEMAPHORE has been added in the main <bits/eventfd.h>, but not in
the SPARC specific version. Fix that.

(cherry picked from commit 83df9ad0cc)
2014-05-07 00:12:56 +02:00
Serge Hallyn 5ed2072401 misc/sys/xattr.h: guard against linux uapi header inclusion
If the glibc xattr.h header is included after the uapi header,
compilation fails due to an enum re-using a #define from the
uapi header.  Protect against this by guarding the define and
enum inclusions against each other.

(A corresponding kernel patch has been sent here:
http://lkml.org/lkml/2014/3/7/331 )

(See https://lists.debian.org/debian-glibc/2014/03/msg00029.html
and https://sourceware.org/glibc/wiki/Synchronizing_Headers
for more information.)

Signed-off-by: Serge Hallyn <serge.hallyn@ubuntu.com>
(cherry picked from commit fdbe8eae2b)
2014-05-04 14:17:57 +10:00
Allan McRae 526fbebbbe Update Esperanto translations
(cherry picked from commit d69aeb1239)
2014-05-04 14:17:27 +10:00
David S. Miller 092976fd2f NEWS: Add 16885 to fixed bug list. 2014-05-01 16:44:59 -04:00
David S. Miller eec993cb1a Fix v9/64-bit strcmp when string ends in multiple zero bytes.
[BZ #16885]
	* sysdeps/sparc/sparc64/strcmp.S: Fix end comparison handling when
	multiple zero bytes exist at the end of a string.
	Reported by Aurelien Jarno <aurelien@aurel32.net>

	* string/test-strcmp.c (check): Add explicit test for situations where
	there are multiple zero bytes after the first.
2014-05-01 16:25:02 -04:00
Siddhesh Poyarekar ffe768a909 Fix sign of input to bsloww1 (BZ #16623)
In 84ba214c, I removed some redundant sign computations and in the
process, I incorrectly got rid of a temporary variable, thus passing
the absolute value of the input to bsloww1.  This caused #16623.

This fix undoes the incorrect change.
2014-02-27 21:29:16 +05:30
Dylan Alex Simon ac0b347743 Update x86_64 libm-test-ulps on AMD family 21h model 1 (bug 16545).
(cherry picked from commit fbfdf9cb03)

Conflicts:
	NEWS
2014-02-20 10:07:24 +10:00
154 changed files with 3865 additions and 1743 deletions
+642
View File
@@ -1,3 +1,645 @@
2015-02-12 Joseph Myers <joseph@codesourcery.com>
[BZ #17964]
* sysdeps/powerpc/fpu/e_sqrt.c (__slow_ieee754_sqrt): Use
__builtin_fma instead of relying on contraction of a * b + c.
2015-01-28 Adhemerval Zanellla <azanella@linux.vnet.ibm.com>
[BZ #16576]
* sysdeps/powerpc/fpu/math_private.h [__CPU_HAS_FSQRT]: Remove define
and use _ARCH_PPCSQ instead.
(__ieee754_sqrt): Likewise.
(__ieee754_sqrtf): Likewise.
* sysdeps/powerpc/fpu/e_sqrt.c (__slow_ieee754_sqrt): Build only if
_ARCH_PPCSQ is defined.
(__ieee754_sqrt): Use _ARCH_PPCSQ to select wheter to use hardware
fsqrt instruction.
* sysdeps/powerpc/fpu/e_sqrtf.c (__ieee754_sqrtf): Build only if
_ARCH_PPCSQ is defined.
(__ieee754_sqrtf): Use _ARCH_PPCSQ to select wheter to use hardware
fsqrts instruction.
* sysdeps/powerpc/powerpc64/fpu/e_sqrt.c: Remove file.
2016-08-15 Andreas Schwab <schwab@suse.de>
[BZ #20435]
* ports/sysdeps/unix/sysv/linux/arm/setcontext.S (__startcontext):
Mark as .cantunwind.
2015-02-24 Eric Rannaud <e@nanocritical.com>
[BZ #17523]
* io/fcntl.h (__OPEN_NEEDS_MODE): New macro.
* io/bits/fcntl2.h (open): Use it.
(openat): Likewise.
* io/open.c (__libc_open): Likewise.
* io/open64.c (__libc_open64): Likewise.
* io/open64_2.c (__open64_2): Likewise.
* io/open_2.c (__open_2): Likewise.
* io/openat.c (__openat): Likewise.
* io/openat64.c (__openat64): Likewise.
* io/openat64_2.c (__openat64_2): Likewise.
* io/openat_2.c (__openat_2): Likewise.
* sysdeps/mach/hurd/open.c (__libc_open): Likewise.
* sysdeps/mach/hurd/openat.c (__openat): Likewise.
* sysdeps/posix/open64.c (__libc_open64): Likewise.
* sysdeps/unix/sysv/linux/dl-openat64.c (openat64): Likewise.
* ports/sysdeps/unix/sysv/linux/generic/open.c (__libc_open): Likewise.
(__open_nocancel): Likewise.
* ports/sysdeps/unix/sysv/linux/generic/open64.c (__libc_open64):
Likewise.
* sysdeps/unix/sysv/linux/open64.c (__libc_open64): Likewise.
* sysdeps/unix/sysv/linux/openat.c (__OPENAT): Likewise.
2016-07-11 Florian Weimer <fweimer@redhat.com>
[BZ #19018]
* stdlib/cxa_thread_atexit_impl.c (__cxa_thread_atexit_impl):
Mangle function pointer before storing it.
(__call_tls_dtors): Demangle function pointer before calling it.
2016-07-11 Florian Weimer <fweimer@redhat.com>
[BZ #18928]
* sysdeps/generic/ldsodefs.h (struct rtld_global_ro): Remove
_dl_pointer_guard member.
* elf/rtld.c (_rtld_global_ro): Remove _dl_pointer_guard
initializer.
(security_init): Always set up pointer guard.
(process_envvars): Do not process LD_POINTER_GUARD.
2016-07-11 Leonhard Holz <leonhard.holz@web.de>
[BZ #16009]
* string/strxfrm_l.c (STRXFRM): Allocate fixed size cache for
weights and rules. Use do_xfrm_cached if data fits in cache,
do_xfrm otherwise. Moved former main loop to...
* (do_xfrm_cached): New function.
* (do_xfrm): Non-caching version of do_xfrm_cached. Uses
find_idx, find_position and stack_push.
* (find_idx): New function.
* (find_position): Likewise.
* localedata/sort-test.sh: Added test run for do_xfrm.
* localedata/xfrm-test.c (main): Added command line option
-nocache to run the test with strings that are too large for
the STRXFRM cache.
2016-05-23 Florian Weimer <fweimer@redhat.com>
CVE-2016-4429
[BZ #20112]
* sunrpc/clnt_udp.c (clntudp_call): Use malloc/free for the error
payload.
2016-03-25 Florian Weimer <fweimer@redhat.com>
[BZ #19791]
* resolv/res_send.c (close_and_return_error): New function.
(send_dg): Initialize *resplen2 after reopen failure. Call
close_and_return_error for error returns. On error paths without
__res_iclose, initialze *resplen2 explicitly. Update comment for
successful return.
2016-02-15 Carlos O'Donell <carlos@redhat.com>
[BZ #18665]
* resolv/nss_dns/dns-host.c (gaih_getanswer_slice): Always set
*herrno_p.
(gaih_getanswer): Document functional behviour. Return tryagain
if any result is tryagain.
* resolv/res_query.c (__libc_res_nsearch): Set buffer size to zero
when freed.
* resolv/res_send.c: Add copyright text.
(__libc_res_nsend): Document that MAXPACKET is expected.
(send_vc): Document. Remove buffer reuse.
(send_dg): Document. Remove buffer reuse. Set *thisanssizp to set the
size of the buffer. Add Dprint for truncated UDP buffer.
2016-04-29 Florian Weimer <fweimer@redhat.com>
[BZ #20010]
CVE-2016-3706
* sysdeps/posix/getaddrinfo.c
(convert_hostent_to_gaih_addrtuple): New function.
(gethosts): Call convert_hostent_to_gaih_addrtuple.
(gaih_inet): Use convert_hostent_to_gaih_addrtuple to convert
AF_INET data.
2016-05-04 Florian Weimer <fweimer@redhat.com>
[BZ #19779]
CVE-2016-1234
Avoid copying names of directory entries.
* posix/glob.c (DIRENT_MUST_BE, DIRENT_MIGHT_BE_SYMLINK)
(DIRENT_MIGHT_BE_DIR, CONVERT_D_INO, CONVERT_D_TYPE)
(CONVERT_DIRENT_DIRENT64, REAL_DIR_ENTRY): Remove macros.
(struct readdir_result): New type.
(D_TYPE_TO_RESULT, D_INO_TO_RESULT, READDIR_RESULT_INITIALIZER)
(GL_READDIR): New macros.
(readdir_result_might_be_symlink, readdir_result_might_be_dir)
(convert_dirent, convert_dirent64): New functions.
(glob_in_dir): Use struct readdir_result. Call convert_dirent or
convert_dirent64. Adjust references to the readdir result.
* sysdeps/unix/sysv/linux/i386/glob64.c:
(convert_dirent, GL_READDIR): Redefine for second file inclusion.
* posix/bug-glob2.c (LONG_NAME): Define.
(filesystem): Add LONG_NAME.
(my_DIR): Increase the size of room_for_dirent.
2016-04-29 Florian Weimer <fweimer@redhat.com>
glob: Simplify and document the interface for the GLOB_ALTDIRFUNC
callback function gl_readdir.
* posix/glob.c (NAMELEN, CONVERT_D_NAMLEN): Remove.
(CONVERT_DIRENT_DIRENT64): Use strcpy instead of memcpy.
(glob_in_dir): Remove len. Use strdup instead of malloc and
memcpy to copy the name.
* manual/pattern.texi (Calling Glob): Document requirements for
implementations of the gl_readdir callback function.
* manual/examples/mkdirent.c: New example.
* posix/bug-glob2.c (my_readdir): Set d_ino to 1 unconditionally,
per the manual guidance.
* posix/tst-gnuglob.c (my_readdir): Likewise.
2016-04-28 Stefan Liebler <stli@linux.vnet.ibm.com>
[BZ #18508]
* stdlib/Makefile ($(objpfx)tst-makecontext3):
Depend on $(libdl).
* stdlib/tst-makecontext.c (cf): Test if _Unwind_Backtrace
is not called infinitely times.
(backtrace_helper): New function.
(trace_arg): New struct.
(st1): Enlarge stack size.
* sysdeps/unix/sysv/linux/s390/s390-32/__makecontext_ret.S:
(__makecontext_ret): Omit cfi_startproc and cfi_endproc.
* sysdeps/unix/sysv/linux/s390/s390-64/__makecontext_ret.S:
Likewise.
2016-04-28 Stefan Liebler <stli@linux.vnet.ibm.com>
[BZ #18080]
* sysdeps/unix/sysv/linux/s390/s390-32/setcontext.S
(__setcontext): Use SIG_SETMASK instead of SIG_BLOCK.
* sysdeps/unix/sysv/linux/s390/s390-64/setcontext.S
(__setcontext): Likewise.
* sysdeps/unix/sysv/linux/s390/s390-32/swapcontext.S
(__swapcontext): Use SIG_SETMASK instead of SIG_BLOCK.
Call rt_sigprocmask syscall one time to set new signal mask
and retrieve the current signal mask instead of two calls.
* sysdeps/unix/sysv/linux/s390/s390-64/swapcontext.S
(__swapcontext): Likewise.
* stdlib/Makefile (tests): Add new testcase tst-setcontext2.
* stdlib/tst-setcontext2.c: New file.
2016-04-01 Florian Weimer <fweimer@redhat.com>
[BZ #19879]
CVE-2016-3075
* resolv/nss_dns/dns-network.c (_nss_dns_getnetbyname_r): Do not
copy name.
2016-02-12 Florian Weimer <fweimer@redhat.com>
* misc/bug18240.c (do_test): Set RLIMIT_AS.
2016-01-27 Paul Eggert <eggert@cs.ucla.edu>
[BZ #18240]
* misc/hsearch_r.c (isprime, __hcreate_r): Protect against
unsigned int wraparound.
2016-01-27 Florian Weimer <fweimer@redhat.com>
[BZ #18240]
* misc/bug18240.c: New test.
* misc/Makefile (tests): Add it.
2015-08-25 Ondřej Bílka <neleai@seznam.cz>
[BZ #18240]
* misc/hsearch_r.c (__hcreate_r): Handle overflow.
2015-09-26 Paul Pluzhnikov <ppluzhnikov@google.com>
[BZ #18985]
* time/strftime_l.c (a_wkday, f_wkday, a_month, f_month): Range check.
(__strftime_internal): Likewise.
* time/tst-strftime.c (do_bz18985): New test.
(do_test): Call it.
2015-08-08 Paul Pluzhnikov <ppluzhnikov@google.com>
[BZ #17905]
* catgets/Makefile (tst-catgets-mem): New test.
* catgets/catgets.c (catopen): Don't use unbounded alloca.
* catgets/open_catalog.c (__open_catalog): Likewise.
* catgets/tst-catgets.c (do_bz17905): Test unbounded alloca.
2015-12-20 Siddhesh Poyarekar <siddhesh@redhat.com>
[BZ #16758]
* nscd/netgroupcache.c (addinnetgrX): Succeed if triplet has
blank values.
[BZ #16759]
* inet/getnetgrent_r.c (get_nonempty_val): New function.
(nscd_getnetgrent): Use it.
[BZ #16760]
* nscd/netgroupcache.c (addgetnetgrentX): Use memmove instead
of stpcpy.
2015-11-24 Andreas Schwab <schwab@suse.de>
[BZ #17062]
* posix/fnmatch_loop.c (FCT): Rerrange loop for skipping over rest
of a bracket expr not to run off the end of the string.
* posix/Makefile (tests): Add tst-fnmatch3.
* posix/tst-fnmatch3.c: New file.
2015-04-29 Florian Weimer <fweimer@redhat.com>
[BZ #18007]
* nss/nss_files/files-XXX.c (CONCAT): Always enable stayopen.
(CVE-2014-8121)
* nss/tst-nss-getpwent.c: New file.
* nss/Makefile (tests): Add new test.
2015-02-22 Paul Pluzhnikov <ppluzhnikov@google.com>
[BZ #17269]
* libio/wstrops.c (_IO_wstr_overflow): Guard against integer overflow
(enlarge_userbuf): Likewise.
2015-02-26 Andreas Schwab <schwab@suse.de>
[BZ #18032]
* posix/fnmatch_loop.c (FCT): Remove extra increment when skipping
over collating symbol inside a bracket expression. Minor cleanup.
2014-06-23 Andreas Schwab <schwab@suse.de>
[BZ #17079]
* nss/nss_files/files-XXX.c (get_contents): Store overflow marker
before reading the next line.
2015-10-02 Andreas Schwab <schwab@suse.de>
* sysdeps/posix/getaddrinfo.c (gaih_inet): Advance address pointer
when skipping over non-matching result from nscd.
2015-09-11 Alan Modra <amodra@gmail.com>
[BZ #17153]
* elf/elf.h (DT_PPC64_NUM): Correct value.
* NEWS: Add to fixed bug list.
2014-03-20 Andreas Schwab <schwab@suse.de>
[BZ #16743]
* sysdeps/posix/getaddrinfo.c (gaih_inet): Properly skip over
non-matching result from nscd.
2015-04-21 Arjun Shankar <arjun.is@lostca.se>
[BZ #18287]
* resolv/nss_dns/dns-host.c (getanswer_r): Adjust buffer length
based on padding. (CVE-2015-1781)
2014-12-11 Andreas Schwab <schwab@suse.de>
[BZ #16657]
* nptl/pthread_mutex_trylock.c (__pthread_mutex_trylock): Use
FORCE_ELISION instead of DO_ELISION.
* nptl/sysdeps/unix/sysv/linux/x86/force-elision.h (DO_ELISION):
Remove.
2013-07-29 Adhemerval Zanella <azanella@linux.vnet.ibm.com>
[BZ #17213]
* sysdeps/powerpc/powerpc64/entry.h: Fix TEXT_START definition for
powerpc64le.
2014-11-11 Renlin Li <Renlin.Li@arm.com>
[BZ #17555]
* ports/sysdeps/aarch64/start.S (_start): Delete x29 overwritten
assignment.
2014-09-03 Florian Weimer <fweimer@redhat.com>
[BZ #17325]
* iconvdata/ibm1364.c (BODY): Fix check for sentinel.
* iconvdata/ibm932.c (BODY): Replace invalid sentinel check with
assert.
* iconvdata/ibm933.c (BODY): Fix check for sentinel.
* iconvdata/ibm935.c (BODY): Likewise.
* iconvdata/ibm937.c (BODY): Likewise.
* iconvdata/ibm939.c (BODY): Likewise.
* iconvdata/ibm943.c (BODY): Replace invalid sentinel check with
assert.
* iconvdata/Makefile (iconv-test.out): Pass module list to test
script.
* iconvdata/run-iconv-test.sh: New test loop for checking for
decoder crashers.
2014-08-26 Florian Weimer <fweimer@redhat.com>
[BZ #17187]
* iconv/gconv_trans.c (struct known_trans, search_tree, lock,
trans_compare, open_translit, __gconv_translit_find):
Remove module loading code.
2014-08-01 Stefan Liebler <stli@linux.vnet.ibm.com>
* NEWS: Explain the s390 jmp_buf / ucontext_t ABI change
reversal.
2014-07-31 Stefan Liebler <stli@linux.vnet.ibm.com>
* sysdeps/s390/Makefile: Delete file.
* sysdeps/s390/Versions (GLIBC_2.19): Remove __setjmp.
* sysdeps/s390/__longjmp.c: Delete file.
* sysdeps/s390/bits/setjmp.h (__s390_jmp_buf):
Remove fields __flags and __reserved.
* sysdeps/s390/longjmp.c: Include setjmp/longjmp.c
and add versioning.
* sysdeps/s390/rtld-__longjmp.c: Delete file.
* sysdeps/s390/rtld-global-offsets.sym: Likewise.
* sysdeps/s390/rtld-setjmp.S: Likewise.
* sysdeps/s390/s390-32/__longjmp-common.c: Move to ...
* sysdeps/s390/s390-32/__longjmp.c: ... here.
* sysdeps/s390/s390-32/setjmp-common.S: Move to ...
* sysdeps/s390/s390-32/setjmp.S: ... here.
Add versioning.
(__sigsetjmp): Remove setting __flags field.
* sysdeps/s390/s390-64/__longjmp-common.c:Move to ...
* sysdeps/s390/s390-64/__longjmp.c: ... here.
* sysdeps/s390/s390-64/setjmp-common.S: Move to ...
* sysdeps/s390/s390-64/setjmp.S: ... here.
Add versioning.
(__sigsetjmp): Remove setting __flags field.
* sysdeps/s390/setjmp.S: Delete file.
* sysdeps/s390/sigjmp.c: Likewise.
* sysdeps/s390/v1-longjmp.c: Likewise.
* sysdeps/s390/v1-setjmp.h: Likewise.
* sysdeps/s390/v1-sigjmp.c: Likewise.
* sysdeps/unix/sysv/linux/s390/Makefile (sysdep_routines):
Remove v1-longjmp_chk.
* sysdeps/unix/sysv/linux/s390/getcontext.S: Delete file.
* sysdeps/unix/sysv/linux/s390/longjmp_chk.c:
Include debug/longjmp_chk.c and add versioning.
* nptl/sysdeps/unix/sysv/linux/s390/pt-longjmp.c:
Include nptl/sysdeps/pthread/pt-longjmp.c and add versioning.
* sysdeps/unix/sysv/linux/s390/rtld-getcontext.S: Delete file.
* sysdeps/unix/sysv/linux/s390/s390-32/____longjmp_chk.c:
Include __longjmp.c.
* sysdeps/unix/sysv/linux/s390/s390-32/getcontext-common.S:
Move to ...
* sysdeps/unix/sysv/linux/s390/s390-32/getcontext.S: ... here.
(__getcontext): Remove setting __flags field.
Add versioning.
* sysdeps/unix/sysv/linux/s390/s390-32/setcontext.S:
DonÂt restore upper high grps.
* sysdeps/unix/sysv/linux/s390/s390-32/swapcontext.S:
Likewise.
(__swapcontext): Remove setting uc_flags field.
* sysdeps/unix/sysv/linux/s390/s390-32/ucontext_i.sym:
Delete file.
* sysdeps/unix/sysv/linux/s390/s390-64/____longjmp_chk.c:
Include __longjmp.c.
* sysdeps/unix/sysv/linux/s390/s390-64/getcontext-common.S:
Move to ...
* sysdeps/unix/sysv/linux/s390/s390-64/getcontext.S: ... here.
(__getcontext): Remove setting __flags field.
Add versioning.
* sysdeps/unix/sysv/linux/s390/s390-64/swapcontext.S:
(__swapcontext): Remove setting uc_flags field.
* unix/sysv/linux/s390/s390-64/ucontext_i.sym: Delete file.
* sysdeps/unix/sysv/linux/s390/sys/ucontext.h (ucontext):
Remove fields uc_high_gprs and __reserved.
* sysdeps/unix/sysv/linux/s390/ucontext_i.sym:
New file with reverted content.
* sysdeps/unix/sysv/linux/s390/v1-longjmp_chk.c: Delete file.
* sysdeps/unix/sysv/linux/s390/s390-32/nptl/libc.abilist:
Regenerated.
* sysdeps/unix/sysv/linux/s390/s390-64/nptl/libc.abilist:
Regenerated.
2014-07-02 Florian Weimer <fweimer@redhat.com>
* manual/locale.texi (Locale Names): New section documenting
locale name syntax. Adjust menu and node chaining accordingly.
(Choosing Locale): Reference Locale Names, Locale Categories.
Mention setting LC_ALL=C. Reflect that name syntax is now
documented.
(Locale Categories): New section title. Reference Locale Names.
LC_ALL is an environment variable, but not a category.
(Setting the Locale): Remove "locale -a" invocation and LOCPATH
description, now in Locale Name. Reference that section. Locale
name syntax is now documented.
2014-07-02 Florian Weimer <fweimer@redhat.com>
[BZ #17137]
* locale/findlocale.c (name_present, valid_locale_name): New
functions.
(_nl_find_locale): Use the loc_name variable to store name
candidates. Call name_present and valid_locale_name to check and
validate locale names. Return an error if the locale is invalid.
2014-07-02 Florian Weimer <fweimer@redhat.com>
* locale/setlocale.c (setlocale): Use strdup for allocating
composite name copy.
2014-05-26 Siddhesh Poyarekar <siddhesh@redhat.com>
[BZ #16878]
* nscd/netgroupcache.c (addgetnetgrentX): Look for
NSS_STATUS_TRYAGAIN to indicate insufficient buffer space.
* nscd/nss_files/files-netgrp.c (_nss_netgroup_parseline): Use
NSS_STATUS_TRYAGAIN to indicate insufficient buffer space.
2014-03-12 Siddhesh Poyarekar <siddhesh@redhat.com>
[BZ #16695]
* nscd/netgroupcache.c (addgetnetgrentX): Factor in space for
key in the buffer.
2014-06-20 Maciej W. Rozycki <macro@codesourcery.com>
[BZ #16046]
* elf/tst-dl-iter-static.c: New file.
* elf/Makefile (tests-static): Add tst-dl-iter-static.
2014-06-20 Andreas Schwab <schwab@linux-m68k.org>
[BZ #17069]
* posix/regcomp.c (parse_reg_exp): Deallocate partially
constructed tree before returning error.
* posix/bug-regexp36.c: Expand test case.
2014-06-19 Andreas Schwab <schwab@linux-m68k.org>
[BZ #17069]
* posix/regcomp.c (parse_expression): Deallocate partially
constructed tree before returning error.
* posix/Makefile.c (tests): Add bug-regex36.
(generated): Add bug-regex36.mtrace.
(tests-special): Add $(objpfx)bug-regex36-mem.out
(bug-regex36-ENV): New variable.
($(objpfx)bug-regex36-mem.out): New rule.
* posix/bug-regex36.c: New file.
2014-06-03 Andreas Schwab <schwab@suse.de>
[BZ #15946]
* resolv/res_send.c (send_dg): Reload file descriptor after
calling reopen.
2014-02-18 Andreas Schwab <schwab@suse.de>
[BZ #16574]
* resolv/res_send.c (send_vc): Add parameter ansp2_malloced.
Store non-zero if the second buffer was newly allocated.
(send_dg): Likewise.
(__libc_res_nsend): Add parameter ansp2_malloced and pass it down
to send_vc and send_dg.
(res_nsend): Pass NULL for ansp2_malloced.
* resolv/res_query.c (__libc_res_nquery): Add parameter
answerp2_malloced and pass it down to __libc_res_nsend.
(res_nquery): Pass additional NULL to __libc_res_nquery.
(__libc_res_nsearch): Add parameter answerp2_malloced and pass it
down to __libc_res_nquery and __libc_res_nquerydomain. Deallocate
second answer buffer if answerp2_malloced was set.
(res_nsearch): Pass additional NULL to __libc_res_nsearch.
(__libc_res_nquerydomain): Add parameter
answerp2_malloced and pass it down to __libc_res_nquery.
(res_nquerydomain): Pass additional NULL to
__libc_res_nquerydomain.
* resolv/nss_dns/dns-network.c (_nss_dns_getnetbyname_r): Pass
additional NULL to __libc_res_nsend and __libc_res_nquery.
* resolv/nss_dns/dns-host.c (_nss_dns_gethostbyname3_r): Pass
additional NULL to __libc_res_nsearch.
(_nss_dns_gethostbyname4_r): Revert last change. Use new
parameter of __libc_res_nsearch to check for separately allocated
second buffer.
(_nss_dns_gethostbyaddr2_r): Pass additional NULL to
__libc_res_nquery.
* resolv/nss_dns/dns-canon.c (_nss_dns_getcanonname_r): Pass
additional NULL to __libc_res_nquery.
* resolv/gethnamaddr.c (gethostbyname2): Pass additional NULL to
__libc_res_nsearch.
(gethostbyaddr): Pass additional NULL to __libc_res_nquery.
* include/resolv.h: Update prototypes of __libc_res_nquery,
__libc_res_nsearch, __libc_res_nsend.
2014-02-13 Andreas Schwab <schwab@suse.de>
[BZ #16574]
* resolv/nss_dns/dns-host.c (_nss_dns_gethostbyname4_r): Free the
second answer buffer if it was separately allocated.
2014-05-12 Andreas Schwab <schwab@suse.de>
[BZ #16932]
* nis/nss_nis/nis-hosts.c (internal_gethostbyname2_r)
(_nss_nis_gethostbyname4_r): Return error if item length is larger
than maximum RPC packet size.
* nis/nss_nis/nis-initgroups.c (initgroups_netid): Likewise.
* nis/nss_nis/nis-network.c (_nss_nis_getnetbyname_r): Likewise.
* nis/nss_nis/nis-service.c (_nss_nis_getservbyname_r)
(_nss_nis_getservbyport_r): Likewise.
2014-06-21 Allan McRae <allan@archlinux.org>
* NEWS: Mention CVE-2014-4043.
2014-06-12 Stefan Liebler <stli@linux.vnet.ibm.com>
* posix/spawn_faction_addopen.c: Include string.h.
2014-06-11 Florian Weimer <fweimer@redhat.com>
[BZ #17048]
* posix/spawn_int.h (struct __spawn_action): Make the path string
non-const to support deallocation.
* posix/spawn_faction_addopen.c
(posix_spawn_file_actions_addopen): Make a copy of the pathname.
* posix/spawn_faction_destroy.c
(posix_spawn_file_actions_destroy): Adjust comment. Deallocate
path in all spawn_do_open actions.
* posix/tst-spawn.c (do_test): Exercise the copy operation in
posix_spawn_file_actions_addopen.
2014-06-03 Guo Yixuan <culu.gyx@gmail.com>
[BZ #16882]
* nptl/sysdeps/sparc/sparc32/pthread_spin_lock.S
(pthread_spin_lock): Branch out of spin loop to proper location.
* nptl/sysdeps/sparc/sparc64/pthread_spin_lock.S
(pthread_spin_lock): Likewise.
* nptl/tst-spin4.c: New test.
* nptl/Makefile (tests): Add tst-spin4.
2014-05-17 Jose E. Marchesi <jose.marchesi@oracle.com>
[BZ #16958]
* sysdeps/sparc/sparc64/multiarch/memcpy-niagara2.S: Add missing
membar to avoid block loads/stores to overlap previous stores.
2014-05-13 Sami Kerola <kerolasa@iki.fi>
* timezone/Makefile ($(objpfx)tzselect): Use zonedir instead
current working directory
2014-05-16 Allan McRae <allan@archlinux.org>
* po/sv.po: Update Swedish translation from translation project.
2014-05-16 Aurelien Jarno <aurelien@aurel32.net>
[BZ #16943]
* sysdeps/unix/sysv/linux/sparc/bits/resource.h: Declare prlimit
and prlimit64.
2014-05-06 Aurelien Jarno <aurelien@aurel32.net>
[BZ# 16916]
* sysdeps/unix/sysv/linux/sparc/bits/eventfd.h (EFD_SEMAPHORE):
Define.
2014-05-04 Allan McRae <allan@archlinux.org>
* po/eo.po: Update Esperanto translation from translation project.
2014-05-01 David S. Miller <davem@davemloft.net>
[BZ #16885]
* sysdeps/sparc/sparc64/strcmp.S: Fix end comparison handling when
multiple zero bytes exist at the end of a string.
Reported by Aurelien Jarno <aurelien@aurel32.net>
* string/test-strcmp.c (check): Add explicit test for situations where
there are multiple zero bytes after the first.
2014-02-27 Siddhesh Poyarekar <siddhesh@redhat.com>
[BZ #16623]
* sysdeps/ieee754/dbl-64/s_sin.c (__sin): Preserve sign of A
and DA.
(__cos): Likewise.
2014-02-12 Dylan Alex Simon <dylan@dylex.net>
[BZ #16545]
* sysdeps/x86_64/fpu/libm-test-ulps: Update on AMD family 21h
model 1.
2014-02-06 Carlos O'Donell <carlos@redhat.com>
[BZ #16529]
+98
View File
@@ -5,6 +5,104 @@ 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.19.1
* The following bugs are resolved with this release:
15946, 16009, 16545, 16574, 16576, 16623, 16657, 16695, 16743, 16758,
16759, 16760, 16878, 16882, 16885, 16916, 16932, 16943, 16958, 17048,
17062, 17069, 17079, 17137, 17153, 17213, 17263, 17269, 17325, 17523,
17555, 17905, 17964, 18007, 18032, 18080, 18240, 18287, 18508, 18665,
18905, 18928, 19018, 19779, 19791, 19879, 20010, 20112.
* A buffer overflow in gethostbyname_r and related functions performing DNS
requests has been fixed. If the NSS functions were called with a
misaligned buffer, the buffer length change due to pointer alignment was
not taken into account. This could result in application crashes or,
potentially arbitrary code execution, using crafted, but syntactically
valid DNS responses. (CVE-2015-1781)
* Reverted change of ABI data structures for s390 and s390x:
On s390 and s390x the size of struct ucontext and jmp_buf was increased in
2.19. This change is reverted in 2.19.1 and 2.20. The introduced 2.19 symbol
versions of getcontext, setjmp, _setjmp, __sigsetjmp, longjmp, _longjmp,
siglongjmp are preserved pointing straight to the same implementation as the
old ones. Given that, new callers will simply provide a too-big buffer to
these functions. Any applications/libraries out there that embed jmp_buf or
ucontext_t in an ABI-relevant data structure that have already been rebuilt
against 2.19 headers will have to rebuilt again. This is necessary in any
case to revert the breakage in their ABI caused by the glibc change.
* CVE-2014-4043 The posix_spawn_file_actions_addopen implementation did not
copy the path argument. This allowed programs to cause posix_spawn to
deference a dangling pointer, or use an unexpected pathname argument if
the string was modified after the posix_spawn_file_actions_addopen
invocation.
* Locale names, including those obtained from environment variables (LANG
and the LC_* variables), are more tightly checked for proper syntax.
setlocale will now fail (with EINVAL) for locale names that are overly
long, contain slashes without starting with a slash, or contain ".." path
components. (CVE-2014-0475) Previously, some valid locale names were
silently replaced with the "C" locale when running in AT_SECURE mode
(e.g., in a SUID program). This is no longer necessary because of the
additional checks.
* Support for loadable gconv transliteration modules has been removed.
The support for transliteration modules has been non-functional for
over a decade, and the removal is prompted by security defects. The
normal gconv conversion modules are still supported. Transliteration
with //TRANSLIT is still possible, and the //IGNORE specifier
continues to be supported. (CVE-2014-5119)
* Decoding a crafted input sequence in the character sets IBM933, IBM935,
IBM937, IBM939, IBM1364 could result in an out-of-bounds array read,
resulting a denial-of-service security vulnerability in applications which
use functions related to iconv. (CVE-2014-6040)
* CVE-2014-8121 The NSS files backend would reset the file pointer used by
the get*ent functions if any of the query functions for the same database
are used during the iteration, causing a denial-of-service condition in
some applications.
* 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)
* Previously, getaddrinfo copied large amounts of address data to the stack,
even after the fix for CVE-2013-4458 has been applied, potentially
resulting in a stack overflow. getaddrinfo now uses a heap allocation
instead. Reported by Michael Petlan. (CVE-2016-3706)
* A stack-based buffer overflow was found in libresolv when invoked from
libnss_dns, allowing specially crafted DNS responses to seize control
of execution flow in the DNS client. The buffer overflow occurs in
the functions send_dg (send datagram) and send_vc (send TCP) for the
NSS module libnss_dns.so.2 when calling getaddrinfo with AF_UNSPEC
family. The use of AF_UNSPEC triggers the low-level resolver code to
send out two parallel queries for A and AAAA. A mismanagement of the
buffers used for those queries could result in the response of a query
writing beyond the alloca allocated buffer created by
_nss_dns_gethostbyname4_r. Buffer management is simplified to remove
the overflow. Thanks to the Google Security Team and Red Hat for
reporting the security impact of this issue, and Robert Holiday of
Ciena for reporting the related bug 18665. (CVE-2015-7547)
* The 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)
Version 2.19
* The following bugs are resolved with this release:
+8 -3
View File
@@ -45,14 +45,14 @@ catgets-CPPFLAGS := -DNLSPATH='"$(msgcatdir)/%L/%N:$(msgcatdir)/%L/LC_MESSAGES/%
CPPFLAGS-gencat = -DNOT_IN_libc
generated = de.msg test1.cat test1.h test2.cat test2.h sample.SJIS.cat \
test-gencat.h
test-gencat.h tst-catgets.mtrace tst-catgets-mem.out
generated-dirs = de
tst-catgets-ENV = NLSPATH="$(objpfx)%l/%N.cat" LANG=de
tst-catgets-ENV = NLSPATH="$(objpfx)%l/%N.cat" LANG=de MALLOC_TRACE=$(objpfx)tst-catgets.mtrace
ifeq ($(run-built-tests),yes)
tests: $(objpfx)de/libc.cat $(objpfx)test1.cat $(objpfx)test2.cat \
$(objpfx)test-gencat.out
$(objpfx)test-gencat.out $(objpfx)tst-catgets-mem.out
# This test just checks whether the program produces any error or not.
# The result is not tested.
$(objpfx)test1.cat: test1.msg $(objpfx)gencat
@@ -80,4 +80,9 @@ $(objpfx)test-gencat.out: test-gencat.sh $(objpfx)test-gencat \
$(objpfx)sample.SJIS.cat: sample.SJIS $(objpfx)gencat
GCONV_PATH=$(common-objpfx)iconvdata LC_ALL=C \
$(built-program-cmd) -H $(objpfx)test-gencat.h < $(word 1,$^) > $@
$(objpfx)tst-catgets-mem.out: $(objpfx)tst-catgets.out
$(common-objpfx)malloc/mtrace $(objpfx)tst-catgets.mtrace > $@; \
$(evaluate-test)
endif
+12 -7
View File
@@ -16,7 +16,6 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#include <alloca.h>
#include <errno.h>
#include <locale.h>
#include <nl_types.h>
@@ -35,6 +34,7 @@ catopen (const char *cat_name, int flag)
__nl_catd result;
const char *env_var = NULL;
const char *nlspath = NULL;
char *tmp = NULL;
if (strchr (cat_name, '/') == NULL)
{
@@ -54,7 +54,10 @@ catopen (const char *cat_name, int flag)
{
/* Append the system dependent directory. */
size_t len = strlen (nlspath) + 1 + sizeof NLSPATH;
char *tmp = alloca (len);
tmp = malloc (len);
if (__glibc_unlikely (tmp == NULL))
return (nl_catd) -1;
__stpcpy (__stpcpy (__stpcpy (tmp, nlspath), ":"), NLSPATH);
nlspath = tmp;
@@ -65,16 +68,18 @@ catopen (const char *cat_name, int flag)
result = (__nl_catd) malloc (sizeof (*result));
if (result == NULL)
/* We cannot get enough memory. */
return (nl_catd) -1;
if (__open_catalog (cat_name, nlspath, env_var, result) != 0)
{
/* We cannot get enough memory. */
result = (nl_catd) -1;
}
else if (__open_catalog (cat_name, nlspath, env_var, result) != 0)
{
/* Couldn't open the file. */
free ((void *) result);
return (nl_catd) -1;
result = (nl_catd) -1;
}
free (tmp);
return (nl_catd) result;
}
+14 -9
View File
@@ -47,6 +47,7 @@ __open_catalog (const char *cat_name, const char *nlspath, const char *env_var,
size_t tab_size;
const char *lastp;
int result = -1;
char *buf = NULL;
if (strchr (cat_name, '/') != NULL || nlspath == NULL)
fd = open_not_cancel_2 (cat_name, O_RDONLY);
@@ -57,23 +58,23 @@ __open_catalog (const char *cat_name, const char *nlspath, const char *env_var,
if (__builtin_expect (bufact + (n) >= bufmax, 0)) \
{ \
char *old_buf = buf; \
bufmax += 256 + (n); \
buf = (char *) alloca (bufmax); \
memcpy (buf, old_buf, bufact); \
bufmax += (bufmax < 256 + (n)) ? 256 + (n) : bufmax; \
buf = realloc (buf, bufmax); \
if (__glibc_unlikely (buf == NULL)) \
{ \
free (old_buf); \
return -1; \
} \
}
/* The RUN_NLSPATH variable contains a colon separated list of
descriptions where we expect to find catalogs. We have to
recognize certain % substitutions and stop when we found the
first existing file. */
char *buf;
size_t bufact;
size_t bufmax;
size_t bufmax = 0;
size_t len;
buf = NULL;
bufmax = 0;
fd = -1;
while (*run_nlspath != '\0')
{
@@ -188,7 +189,10 @@ __open_catalog (const char *cat_name, const char *nlspath, const char *env_var,
/* Avoid dealing with directories and block devices */
if (__builtin_expect (fd, 0) < 0)
return -1;
{
free (buf);
return -1;
}
if (__builtin_expect (__fxstat64 (_STAT_VER, fd, &st), 0) < 0)
goto close_unlock_return;
@@ -325,6 +329,7 @@ __open_catalog (const char *cat_name, const char *nlspath, const char *env_var,
/* Release the lock again. */
close_unlock_return:
close_not_cancel_no_status (fd);
free (buf);
return result;
}
+31
View File
@@ -1,7 +1,10 @@
#include <assert.h>
#include <mcheck.h>
#include <nl_types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/resource.h>
static const char *msgs[] =
@@ -12,6 +15,33 @@ static const char *msgs[] =
};
#define nmsgs (sizeof (msgs) / sizeof (msgs[0]))
/* Test for unbounded alloca. */
static int
do_bz17905 (void)
{
char *buf;
struct rlimit rl;
nl_catd result;
const int sz = 1024 * 1024;
getrlimit (RLIMIT_STACK, &rl);
rl.rlim_cur = sz;
setrlimit (RLIMIT_STACK, &rl);
buf = malloc (sz + 1);
memset (buf, 'A', sz);
buf[sz] = '\0';
setenv ("NLSPATH", buf, 1);
result = catopen (buf, NL_CAT_LOCALE);
assert (result == (nl_catd) -1);
free (buf);
return 0;
}
#define ROUNDS 5
int
@@ -62,5 +92,6 @@ main (void)
}
}
result += do_bz17905 ();
return result;
}
+1 -1
View File
@@ -123,7 +123,7 @@ tests = tst-tls1 tst-tls2 tst-tls9 tst-leaks1 \
tst-auxv
tests-static = tst-tls1-static tst-tls2-static tst-stackguard1-static \
tst-leaks1-static tst-array1-static tst-array5-static \
tst-ptrguard1-static
tst-ptrguard1-static tst-dl-iter-static
ifeq (yes,$(build-shared))
tests-static += tst-tls9-static
tst-tls9-static-ENV = \
+1 -1
View File
@@ -2283,7 +2283,7 @@ typedef Elf32_Addr Elf32_Conflict;
#define DT_PPC64_OPD (DT_LOPROC + 1)
#define DT_PPC64_OPDSZ (DT_LOPROC + 2)
#define DT_PPC64_OPT (DT_LOPROC + 3)
#define DT_PPC64_NUM 3
#define DT_PPC64_NUM 4
/* PowerPC64 specific values for the DT_PPC64_OPT Dyn entry. */
#define PPC64_OPT_TLS 1
+4 -11
View File
@@ -162,7 +162,6 @@ struct rtld_global_ro _rtld_global_ro attribute_relro =
._dl_hwcap_mask = HWCAP_IMPORTANT,
._dl_lazy = 1,
._dl_fpu_control = _FPU_DEFAULT,
._dl_pointer_guard = 1,
._dl_pagesize = EXEC_PAGESIZE,
._dl_inhibit_cache = 0,
@@ -857,15 +856,12 @@ security_init (void)
#endif
/* Set up the pointer guard as well, if necessary. */
if (GLRO(dl_pointer_guard))
{
uintptr_t pointer_chk_guard = _dl_setup_pointer_guard (_dl_random,
stack_chk_guard);
uintptr_t pointer_chk_guard
= _dl_setup_pointer_guard (_dl_random, stack_chk_guard);
#ifdef THREAD_SET_POINTER_GUARD
THREAD_SET_POINTER_GUARD (pointer_chk_guard);
THREAD_SET_POINTER_GUARD (pointer_chk_guard);
#endif
__pointer_chk_guard_local = pointer_chk_guard;
}
__pointer_chk_guard_local = pointer_chk_guard;
/* We do not need the _dl_random value anymore. The less
information we leave behind, the better, so clear the
@@ -2605,9 +2601,6 @@ process_envvars (enum mode *modep)
GLRO(dl_use_load_bias) = envline[14] == '1' ? -1 : 0;
break;
}
if (memcmp (envline, "POINTER_GUARD", 13) == 0)
GLRO(dl_pointer_guard) = envline[14] != '0';
break;
case 14:
@@ -1,4 +1,5 @@
/* Copyright (C) 1992-2013 Free Software Foundation, Inc.
/* BZ #16046 dl_iterate_phdr static executable test.
Copyright (C) 2014 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -15,20 +16,32 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#include <stddef.h>
#include <setjmp.h>
#include <signal.h>
#include <link.h>
/* This function is called by the `sigsetjmp' macro
before doing a `__setjmp' on ENV[0].__jmpbuf.
Always return zero. */
/* Check that the link map of the static executable itself is iterated
over exactly once. */
int
__v2__sigjmp_save (sigjmp_buf env, int savemask)
static int
callback (struct dl_phdr_info *info, size_t size, void *data)
{
env[0].__mask_was_saved = (savemask &&
__sigprocmask (SIG_BLOCK, (sigset_t *) NULL,
&env[0].__saved_mask) == 0);
int *count = data;
if (info->dlpi_name[0] == '\0')
(*count)++;
return 0;
}
static int
do_test (void)
{
int count = 0;
int status;
status = dl_iterate_phdr (callback, &count);
return status || count != 1;
}
#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"
+4 -173
View File
@@ -238,181 +238,12 @@ __gconv_transliterate (struct __gconv_step *step,
return __GCONV_ILLEGAL_INPUT;
}
/* Structure to represent results of found (or not) transliteration
modules. */
struct known_trans
{
/* This structure must remain the first member. */
struct trans_struct info;
char *fname;
void *handle;
int open_count;
};
/* Tree with results of previous calls to __gconv_translit_find. */
static void *search_tree;
/* We modify global data. */
__libc_lock_define_initialized (static, lock);
/* Compare two transliteration entries. */
static int
trans_compare (const void *p1, const void *p2)
{
const struct known_trans *s1 = (const struct known_trans *) p1;
const struct known_trans *s2 = (const struct known_trans *) p2;
return strcmp (s1->info.name, s2->info.name);
}
/* Open (maybe reopen) the module named in the struct. Get the function
and data structure pointers we need. */
static int
open_translit (struct known_trans *trans)
{
__gconv_trans_query_fct queryfct;
trans->handle = __libc_dlopen (trans->fname);
if (trans->handle == NULL)
/* Not available. */
return 1;
/* Find the required symbol. */
queryfct = __libc_dlsym (trans->handle, "gconv_trans_context");
if (queryfct == NULL)
{
/* We cannot live with that. */
close_and_out:
__libc_dlclose (trans->handle);
trans->handle = NULL;
return 1;
}
/* Get the context. */
if (queryfct (trans->info.name, &trans->info.csnames, &trans->info.ncsnames)
!= 0)
goto close_and_out;
/* Of course we also have to have the actual function. */
trans->info.trans_fct = __libc_dlsym (trans->handle, "gconv_trans");
if (trans->info.trans_fct == NULL)
goto close_and_out;
/* Now the optional functions. */
trans->info.trans_init_fct =
__libc_dlsym (trans->handle, "gconv_trans_init");
trans->info.trans_context_fct =
__libc_dlsym (trans->handle, "gconv_trans_context");
trans->info.trans_end_fct =
__libc_dlsym (trans->handle, "gconv_trans_end");
trans->open_count = 1;
return 0;
}
int
internal_function
__gconv_translit_find (struct trans_struct *trans)
{
struct known_trans **found;
const struct path_elem *runp;
int res = 1;
/* We have to have a name. */
assert (trans->name != NULL);
/* Acquire the lock. */
__libc_lock_lock (lock);
/* See whether we know this module already. */
found = __tfind (trans, &search_tree, trans_compare);
if (found != NULL)
{
/* Is this module available? */
if ((*found)->handle != NULL)
{
/* Maybe we have to reopen the file. */
if ((*found)->handle != (void *) -1)
/* The object is not unloaded. */
res = 0;
else if (open_translit (*found) == 0)
{
/* Copy the data. */
*trans = (*found)->info;
(*found)->open_count++;
res = 0;
}
}
}
else
{
size_t name_len = strlen (trans->name) + 1;
int need_so = 0;
struct known_trans *newp;
/* We have to continue looking for the module. */
if (__gconv_path_elem == NULL)
__gconv_get_path ();
/* See whether we have to append .so. */
if (name_len <= 4 || memcmp (&trans->name[name_len - 4], ".so", 3) != 0)
need_so = 1;
/* Create a new entry. */
newp = (struct known_trans *) malloc (sizeof (struct known_trans)
+ (__gconv_max_path_elem_len
+ name_len + 3)
+ name_len);
if (newp != NULL)
{
char *cp;
/* Clear the struct. */
memset (newp, '\0', sizeof (struct known_trans));
/* Store a copy of the module name. */
newp->info.name = cp = (char *) (newp + 1);
cp = __mempcpy (cp, trans->name, name_len);
newp->fname = cp;
/* Search in all the directories. */
for (runp = __gconv_path_elem; runp->name != NULL; ++runp)
{
cp = __mempcpy (__stpcpy ((char *) newp->fname, runp->name),
trans->name, name_len);
if (need_so)
memcpy (cp, ".so", sizeof (".so"));
if (open_translit (newp) == 0)
{
/* We found a module. */
res = 0;
break;
}
}
if (res)
newp->fname = NULL;
/* In any case we'll add the entry to our search tree. */
if (__tsearch (newp, &search_tree, trans_compare) == NULL)
{
/* Yickes, this should not happen. Unload the object. */
res = 1;
/* XXX unload here. */
}
}
}
__libc_lock_unlock (lock);
return res;
/* Transliteration module loading has been removed because it never
worked as intended and suffered from a security vulnerability.
Consequently, this function always fails. */
return 1;
}
+1
View File
@@ -299,6 +299,7 @@ $(objpfx)tst-iconv7.out: $(objpfx)gconv-modules \
$(objpfx)iconv-test.out: run-iconv-test.sh $(objpfx)gconv-modules \
$(addprefix $(objpfx),$(modules.so)) \
$(common-objdir)/iconv/iconv_prog TESTS
iconv_modules="$(modules)" \
$(SHELL) $< $(common-objdir) '$(test-wrapper)' > $@
$(objpfx)tst-tables.out: tst-tables.sh $(objpfx)gconv-modules \
+2 -1
View File
@@ -220,7 +220,8 @@ enum
++rp2; \
\
uint32_t res; \
if (__builtin_expect (ch < rp2->start, 0) \
if (__builtin_expect (rp2->start == 0xffff, 0) \
|| __builtin_expect (ch < rp2->start, 0) \
|| (res = DB_TO_UCS4[ch + rp2->idx], \
__builtin_expect (res, L'\1') == L'\0' && ch != '\0')) \
{ \
+3 -2
View File
@@ -73,11 +73,12 @@
} \
\
ch = (ch * 0x100) + inptr[1]; \
/* ch was less than 0xfd. */ \
assert (ch < 0xfd00); \
while (ch > rp2->end) \
++rp2; \
\
if (__builtin_expect (rp2 == NULL, 0) \
|| __builtin_expect (ch < rp2->start, 0) \
if (__builtin_expect (ch < rp2->start, 0) \
|| (res = __ibm932db_to_ucs4[ch + rp2->idx], \
__builtin_expect (res, '\1') == 0 && ch !=0)) \
{ \
+1 -1
View File
@@ -161,7 +161,7 @@ enum
while (ch > rp2->end) \
++rp2; \
\
if (__builtin_expect (rp2 == NULL, 0) \
if (__builtin_expect (rp2->start == 0xffff, 0) \
|| __builtin_expect (ch < rp2->start, 0) \
|| (res = __ibm933db_to_ucs4[ch + rp2->idx], \
__builtin_expect (res, L'\1') == L'\0' && ch != '\0')) \
+1 -1
View File
@@ -161,7 +161,7 @@ enum
while (ch > rp2->end) \
++rp2; \
\
if (__builtin_expect (rp2 == NULL, 0) \
if (__builtin_expect (rp2->start == 0xffff, 0) \
|| __builtin_expect (ch < rp2->start, 0) \
|| (res = __ibm935db_to_ucs4[ch + rp2->idx], \
__builtin_expect (res, L'\1') == L'\0' && ch != '\0')) \
+1 -1
View File
@@ -161,7 +161,7 @@ enum
while (ch > rp2->end) \
++rp2; \
\
if (__builtin_expect (rp2 == NULL, 0) \
if (__builtin_expect (rp2->start == 0xffff, 0) \
|| __builtin_expect (ch < rp2->start, 0) \
|| (res = __ibm937db_to_ucs4[ch + rp2->idx], \
__builtin_expect (res, L'\1') == L'\0' && ch != '\0')) \
+1 -1
View File
@@ -161,7 +161,7 @@ enum
while (ch > rp2->end) \
++rp2; \
\
if (__builtin_expect (rp2 == NULL, 0) \
if (__builtin_expect (rp2->start == 0xffff, 0) \
|| __builtin_expect (ch < rp2->start, 0) \
|| (res = __ibm939db_to_ucs4[ch + rp2->idx], \
__builtin_expect (res, L'\1') == L'\0' && ch != '\0')) \
+3 -2
View File
@@ -74,11 +74,12 @@
} \
\
ch = (ch * 0x100) + inptr[1]; \
/* ch was less than 0xfd. */ \
assert (ch < 0xfd00); \
while (ch > rp2->end) \
++rp2; \
\
if (__builtin_expect (rp2 == NULL, 0) \
|| __builtin_expect (ch < rp2->start, 0) \
if (__builtin_expect (ch < rp2->start, 0) \
|| (res = __ibm943db_to_ucs4[ch + rp2->idx], \
__builtin_expect (res, '\1') == 0 && ch !=0)) \
{ \
+18
View File
@@ -188,6 +188,24 @@ while read utf8 from filename; do
done < TESTS2
# Check for crashes in decoders.
printf '\016\377\377\377\377\377\377\377' > $temp1
for from in $iconv_modules ; do
echo $ac_n "test decoder $from $ac_c"
PROG=`eval echo $ICONV`
if $PROG < $temp1 >/dev/null 2>&1 ; then
: # fall through
else
status=$?
if test $status -gt 1 ; then
echo "/FAILED"
failed=1
continue
fi
fi
echo "OK"
done
exit $failed
# Local Variables:
# mode:shell-script
+3 -3
View File
@@ -48,11 +48,11 @@ libc_hidden_proto (__res_randomid)
libc_hidden_proto (__res_state)
int __libc_res_nquery (res_state, const char *, int, int, u_char *, int,
u_char **, u_char **, int *, int *);
u_char **, u_char **, int *, int *, int *);
int __libc_res_nsearch (res_state, const char *, int, int, u_char *, int,
u_char **, u_char **, int *, int *);
u_char **, u_char **, int *, int *, int *);
int __libc_res_nsend (res_state, const u_char *, int, const u_char *, int,
u_char *, int, u_char **, u_char **, int *, int *)
u_char *, int, u_char **, u_char **, int *, int *, int *)
attribute_hidden;
libresolv_hidden_proto (_sethtent)
+11 -3
View File
@@ -235,6 +235,14 @@ endnetgrent (void)
}
#ifdef USE_NSCD
static const char *
get_nonempty_val (const char *in)
{
if (*in == '\0')
return NULL;
return in;
}
static enum nss_status
nscd_getnetgrent (struct __netgrent *datap, char *buffer, size_t buflen,
int *errnop)
@@ -243,11 +251,11 @@ nscd_getnetgrent (struct __netgrent *datap, char *buffer, size_t buflen,
return NSS_STATUS_UNAVAIL;
datap->type = triple_val;
datap->val.triple.host = datap->cursor;
datap->val.triple.host = get_nonempty_val (datap->cursor);
datap->cursor = (char *) __rawmemchr (datap->cursor, '\0') + 1;
datap->val.triple.user = datap->cursor;
datap->val.triple.user = get_nonempty_val (datap->cursor);
datap->cursor = (char *) __rawmemchr (datap->cursor, '\0') + 1;
datap->val.triple.domain = datap->cursor;
datap->val.triple.domain = get_nonempty_val (datap->cursor);
datap->cursor = (char *) __rawmemchr (datap->cursor, '\0') + 1;
return NSS_STATUS_SUCCESS;
+9 -9
View File
@@ -20,7 +20,7 @@
# error "Never include <bits/fcntl2.h> directly; use <fcntl.h> instead."
#endif
/* Check that calls to open and openat with O_CREAT set have an
/* Check that calls to open and openat with O_CREAT or O_TMPFILE set have an
appropriate third/fourth parameter. */
#ifndef __USE_FILE_OFFSET64
extern int __open_2 (const char *__path, int __oflag) __nonnull ((1));
@@ -35,7 +35,7 @@ extern int __REDIRECT (__open_alias, (const char *__path, int __oflag, ...),
__errordecl (__open_too_many_args,
"open can be called either with 2 or 3 arguments, not more");
__errordecl (__open_missing_mode,
"open with O_CREAT in second argument needs 3 arguments");
"open with O_CREAT or O_TMPFILE in second argument needs 3 arguments");
__fortify_function int
open (const char *__path, int __oflag, ...)
@@ -45,7 +45,7 @@ open (const char *__path, int __oflag, ...)
if (__builtin_constant_p (__oflag))
{
if ((__oflag & O_CREAT) != 0 && __va_arg_pack_len () < 1)
if (__OPEN_NEEDS_MODE (__oflag) && __va_arg_pack_len () < 1)
{
__open_missing_mode ();
return __open_2 (__path, __oflag);
@@ -67,7 +67,7 @@ extern int __REDIRECT (__open64_alias, (const char *__path, int __oflag,
__errordecl (__open64_too_many_args,
"open64 can be called either with 2 or 3 arguments, not more");
__errordecl (__open64_missing_mode,
"open64 with O_CREAT in second argument needs 3 arguments");
"open64 with O_CREAT or O_TMPFILE in second argument needs 3 arguments");
__fortify_function int
open64 (const char *__path, int __oflag, ...)
@@ -77,7 +77,7 @@ open64 (const char *__path, int __oflag, ...)
if (__builtin_constant_p (__oflag))
{
if ((__oflag & O_CREAT) != 0 && __va_arg_pack_len () < 1)
if (__OPEN_NEEDS_MODE (__oflag) && __va_arg_pack_len () < 1)
{
__open64_missing_mode ();
return __open64_2 (__path, __oflag);
@@ -111,7 +111,7 @@ extern int __REDIRECT (__openat_alias, (int __fd, const char *__path,
__errordecl (__openat_too_many_args,
"openat can be called either with 3 or 4 arguments, not more");
__errordecl (__openat_missing_mode,
"openat with O_CREAT in third argument needs 4 arguments");
"openat with O_CREAT or O_TMPFILE in third argument needs 4 arguments");
__fortify_function int
openat (int __fd, const char *__path, int __oflag, ...)
@@ -121,7 +121,7 @@ openat (int __fd, const char *__path, int __oflag, ...)
if (__builtin_constant_p (__oflag))
{
if ((__oflag & O_CREAT) != 0 && __va_arg_pack_len () < 1)
if (__OPEN_NEEDS_MODE (__oflag) && __va_arg_pack_len () < 1)
{
__openat_missing_mode ();
return __openat_2 (__fd, __path, __oflag);
@@ -145,7 +145,7 @@ extern int __REDIRECT (__openat64_alias, (int __fd, const char *__path,
__errordecl (__openat64_too_many_args,
"openat64 can be called either with 3 or 4 arguments, not more");
__errordecl (__openat64_missing_mode,
"openat64 with O_CREAT in third argument needs 4 arguments");
"openat64 with O_CREAT or O_TMPFILE in third argument needs 4 arguments");
__fortify_function int
openat64 (int __fd, const char *__path, int __oflag, ...)
@@ -155,7 +155,7 @@ openat64 (int __fd, const char *__path, int __oflag, ...)
if (__builtin_constant_p (__oflag))
{
if ((__oflag & O_CREAT) != 0 && __va_arg_pack_len () < 1)
if (__OPEN_NEEDS_MODE (__oflag) && __va_arg_pack_len () < 1)
{
__openat64_missing_mode ();
return __openat64_2 (__fd, __path, __oflag);
+12 -2
View File
@@ -34,6 +34,15 @@ __BEGIN_DECLS
numbers and flag bits for `open', `fcntl', et al. */
#include <bits/fcntl.h>
/* Detect if open needs mode as a third argument (or for openat as a fourth
argument). */
#ifdef __O_TMPFILE
# define __OPEN_NEEDS_MODE(oflag) \
(((oflag) & O_CREAT) != 0 || ((oflag) & __O_TMPFILE) == __O_TMPFILE)
#else
# define __OPEN_NEEDS_MODE(oflag) (((oflag) & O_CREAT) != 0)
#endif
/* POSIX.1-2001 specifies that these types are defined by <fcntl.h>.
Earlier POSIX standards permitted any type ending in `_t' to be defined
by any POSIX header, so we don't conditionalize the definitions here. */
@@ -160,8 +169,9 @@ typedef __pid_t pid_t;
extern int fcntl (int __fd, int __cmd, ...);
/* Open FILE and return a new file descriptor for it, or -1 on error.
OFLAG determines the type of access used. If O_CREAT is on OFLAG,
the third argument is taken as a `mode_t', the mode of the created file.
OFLAG determines the type of access used. If O_CREAT or O_TMPFILE is set
in OFLAG, the third argument is taken as a `mode_t', the mode of the
created file.
This function is a cancellation point and therefore not marked with
__THROW. */
+2 -2
View File
@@ -23,7 +23,7 @@
#include <stdio.h>
/* Open FILE with access OFLAG. If OFLAG includes O_CREAT,
/* Open FILE with access OFLAG. If O_CREAT or O_TMPFILE is in OFLAG,
a third argument is the file protection. */
int
__libc_open (file, oflag)
@@ -38,7 +38,7 @@ __libc_open (file, oflag)
return -1;
}
if (oflag & O_CREAT)
if (__OPEN_NEEDS_MODE (oflag))
{
va_list arg;
va_start(arg, oflag);
+2 -2
View File
@@ -21,7 +21,7 @@
#include <stddef.h>
#include <stdio.h>
/* Open FILE with access OFLAG. If OFLAG includes O_CREAT,
/* Open FILE with access OFLAG. If O_CREAT or O_TMPFILE is in OFLAG,
a third argument is the file protection. */
int
__libc_open64 (file, oflag)
@@ -36,7 +36,7 @@ __libc_open64 (file, oflag)
return -1;
}
if (oflag & O_CREAT)
if (__OPEN_NEEDS_MODE (oflag))
{
va_list arg;
va_start (arg, oflag);
+2 -2
View File
@@ -22,8 +22,8 @@
int
__open64_2 (const char *file, int oflag)
{
if (oflag & O_CREAT)
__fortify_fail ("invalid open64 call: O_CREAT without mode");
if (__OPEN_NEEDS_MODE (oflag))
__fortify_fail ("invalid open64 call: O_CREAT or O_TMPFILE without mode");
return __open64 (file, oflag);
}
+2 -2
View File
@@ -22,8 +22,8 @@
int
__open_2 (const char *file, int oflag)
{
if (oflag & O_CREAT)
__fortify_fail ("invalid open call: O_CREAT without mode");
if (__OPEN_NEEDS_MODE (oflag))
__fortify_fail ("invalid open call: O_CREAT or O_TMPFILE without mode");
return __open (file, oflag);
}
+2 -2
View File
@@ -30,7 +30,7 @@ int __have_atfcts;
#endif
/* Open FILE with access OFLAG. Interpret relative paths relative to
the directory associated with FD. If OFLAG includes O_CREAT, a
the directory associated with FD. If O_CREAT or O_TMPFILE is in OFLAG, a
third argument is the file protection. */
int
__openat (fd, file, oflag)
@@ -60,7 +60,7 @@ __openat (fd, file, oflag)
}
}
if (oflag & O_CREAT)
if (__OPEN_NEEDS_MODE (oflag))
{
va_list arg;
va_start (arg, oflag);
+2 -2
View File
@@ -23,7 +23,7 @@
#include <sys/stat.h>
/* Open FILE with access OFLAG. Interpret relative paths relative to
the directory associated with FD. If OFLAG includes O_CREAT, a
the directory associated with FD. If O_CREAT or O_TMPFILE is in OFLAG, a
third argument is the file protection. */
int
__openat64 (fd, file, oflag)
@@ -53,7 +53,7 @@ __openat64 (fd, file, oflag)
}
}
if (oflag & O_CREAT)
if (__OPEN_NEEDS_MODE (oflag))
{
va_list arg;
va_start (arg, oflag);
+2 -2
View File
@@ -22,8 +22,8 @@
int
__openat64_2 (int fd, const char *file, int oflag)
{
if (oflag & O_CREAT)
__fortify_fail ("invalid openat64 call: O_CREAT without mode");
if (__OPEN_NEEDS_MODE (oflag))
__fortify_fail ("invalid openat64 call: O_CREAT or O_TMPFILE without mode");
return __openat64 (fd, file, oflag);
}
+2 -2
View File
@@ -22,8 +22,8 @@
int
__openat_2 (int fd, const char *file, int oflag)
{
if (oflag & O_CREAT)
__fortify_fail ("invalid openat call: O_CREAT without mode");
if (__OPEN_NEEDS_MODE (oflag))
__fortify_fail ("invalid openat call: O_CREAT or O_TMPFILE without mode");
return __openat (fd, file, oflag);
}
+7 -1
View File
@@ -95,8 +95,11 @@ _IO_wstr_overflow (fp, c)
wchar_t *old_buf = fp->_wide_data->_IO_buf_base;
size_t old_wblen = _IO_wblen (fp);
_IO_size_t new_size = 2 * old_wblen + 100;
if (new_size < old_wblen)
if (__glibc_unlikely (new_size < old_wblen)
|| __glibc_unlikely (new_size > SIZE_MAX / sizeof (wchar_t)))
return EOF;
new_buf
= (wchar_t *) (*((_IO_strfile *) fp)->_s._allocate_buffer) (new_size
* sizeof (wchar_t));
@@ -186,6 +189,9 @@ enlarge_userbuf (_IO_FILE *fp, _IO_off64_t offset, int reading)
return 1;
_IO_size_t newsize = offset + 100;
if (__glibc_unlikely (newsize > SIZE_MAX / sizeof (wchar_t)))
return 1;
wchar_t *oldbuf = wd->_IO_buf_base;
wchar_t *newbuf
= (wchar_t *) (*((_IO_strfile *) fp)->_s._allocate_buffer) (newsize
+61 -13
View File
@@ -17,6 +17,7 @@
<http://www.gnu.org/licenses/>. */
#include <assert.h>
#include <errno.h>
#include <locale.h>
#include <stdlib.h>
#include <string.h>
@@ -57,6 +58,45 @@ struct loaded_l10nfile *_nl_locale_file_list[__LC_LAST];
const char _nl_default_locale_path[] attribute_hidden = LOCALEDIR;
/* Checks if the name is actually present, that is, not NULL and not
empty. */
static inline int
name_present (const char *name)
{
return name != NULL && name[0] != '\0';
}
/* Checks that the locale name neither extremely long, nor contains a
".." path component (to prevent directory traversal). */
static inline int
valid_locale_name (const char *name)
{
/* Not set. */
size_t namelen = strlen (name);
/* Name too long. The limit is arbitrary and prevents stack overflow
issues later. */
if (__glibc_unlikely (namelen > 255))
return 0;
/* Directory traversal attempt. */
static const char slashdot[4] = {'/', '.', '.', '/'};
if (__glibc_unlikely (memmem (name, namelen,
slashdot, sizeof (slashdot)) != NULL))
return 0;
if (namelen == 2 && __glibc_unlikely (name[0] == '.' && name [1] == '.'))
return 0;
if (namelen >= 3
&& __glibc_unlikely (((name[0] == '.'
&& name[1] == '.'
&& name[2] == '/')
|| (name[namelen - 3] == '/'
&& name[namelen - 2] == '.'
&& name[namelen - 1] == '.'))))
return 0;
/* If there is a slash in the name, it must start with one. */
if (__glibc_unlikely (memchr (name, '/', namelen) != NULL) && name[0] != '/')
return 0;
return 1;
}
struct __locale_data *
internal_function
@@ -65,7 +105,7 @@ _nl_find_locale (const char *locale_path, size_t locale_path_len,
{
int mask;
/* Name of the locale for this category. */
char *loc_name;
char *loc_name = (char *) *name;
const char *language;
const char *modifier;
const char *territory;
@@ -73,31 +113,39 @@ _nl_find_locale (const char *locale_path, size_t locale_path_len,
const char *normalized_codeset;
struct loaded_l10nfile *locale_file;
if ((*name)[0] == '\0')
if (loc_name[0] == '\0')
{
/* The user decides which locale to use by setting environment
variables. */
*name = getenv ("LC_ALL");
if (*name == NULL || (*name)[0] == '\0')
*name = getenv (_nl_category_names.str
loc_name = getenv ("LC_ALL");
if (!name_present (loc_name))
loc_name = getenv (_nl_category_names.str
+ _nl_category_name_idxs[category]);
if (*name == NULL || (*name)[0] == '\0')
*name = getenv ("LANG");
if (!name_present (loc_name))
loc_name = getenv ("LANG");
if (!name_present (loc_name))
loc_name = (char *) _nl_C_name;
}
if (*name == NULL || (*name)[0] == '\0'
|| (__builtin_expect (__libc_enable_secure, 0)
&& strchr (*name, '/') != NULL))
*name = (char *) _nl_C_name;
/* We used to fall back to the C locale if the name contains a slash
character '/', but we now check for directory traversal in
valid_locale_name, so this is no longer necessary. */
if (__builtin_expect (strcmp (*name, _nl_C_name), 1) == 0
|| __builtin_expect (strcmp (*name, _nl_POSIX_name), 1) == 0)
if (__builtin_expect (strcmp (loc_name, _nl_C_name), 1) == 0
|| __builtin_expect (strcmp (loc_name, _nl_POSIX_name), 1) == 0)
{
/* We need not load anything. The needed data is contained in
the library itself. */
*name = (char *) _nl_C_name;
return _nl_C[category];
}
else if (!valid_locale_name (loc_name))
{
__set_errno (EINVAL);
return NULL;
}
*name = loc_name;
/* We really have to load some data. First we try the archive,
but only if there was no LOCPATH environment variable specified. */
+12 -2
View File
@@ -272,6 +272,8 @@ setlocale (int category, const char *locale)
of entries of the form `CATEGORY=VALUE'. */
const char *newnames[__LC_LAST];
struct __locale_data *newdata[__LC_LAST];
/* Copy of the locale argument, for in-place splitting. */
char *locale_copy = NULL;
/* Set all name pointers to the argument name. */
for (category = 0; category < __LC_LAST; ++category)
@@ -281,7 +283,13 @@ setlocale (int category, const char *locale)
if (__builtin_expect (strchr (locale, ';') != NULL, 0))
{
/* This is a composite name. Make a copy and split it up. */
char *np = strdupa (locale);
locale_copy = strdup (locale);
if (__glibc_unlikely (locale_copy == NULL))
{
__libc_rwlock_unlock (__libc_setlocale_lock);
return NULL;
}
char *np = locale_copy;
char *cp;
int cnt;
@@ -299,6 +307,7 @@ setlocale (int category, const char *locale)
{
error_return:
__libc_rwlock_unlock (__libc_setlocale_lock);
free (locale_copy);
/* Bogus category name. */
ERROR_RETURN;
@@ -391,8 +400,9 @@ setlocale (int category, const char *locale)
/* Critical section left. */
__libc_rwlock_unlock (__libc_setlocale_lock);
/* Free the resources (the locale path variable). */
/* Free the resources. */
free (locale_path);
free (locale_copy);
return composite;
}
+6
View File
@@ -1,3 +1,9 @@
2014-07-02 Florian Weimer <fweimer@redhat.com>
* tst-setlocale3.c: New file.
* Makefile (tests): Add tst-setlocale3.
(tst-setlocale3-ENV): New variable.
2013-12-26 Chris Leonard <cjl@sugarlabs.org>
* locales/sa_IN: Add lang_name.
+3 -2
View File
@@ -77,7 +77,7 @@ locale_test_suite := tst_iswalnum tst_iswalpha tst_iswcntrl \
tests = $(locale_test_suite) tst-digits tst-setlocale bug-iconv-trans \
tst-leaks tst-mbswcs6 tst-xlocale1 tst-xlocale2 bug-usesetlocale \
tst-strfmon1 tst-sscanf bug-setlocale1 tst-setlocale2
tst-strfmon1 tst-sscanf bug-setlocale1 tst-setlocale2 tst-setlocale3
tests-static = bug-setlocale1-static
tests += $(tests-static)
ifeq (yes,$(build-shared))
@@ -276,7 +276,7 @@ tst-xlocale2-ENV = $(TEST_MBWC_ENV)
tst-strfmon1-ENV = $(TEST_MBWC_ENV)
tst-strptime-ENV = $(TEST_MBWC_ENV)
tst-setlocale-ENV = LOCPATH=$(common-objpfx)localedata LC_ALL=ja_JP.EUC-JP
tst-setlocale-ENV = LOCPATH=$(common-objpfx)localedata LC_ALL=ja_JP.EUC-
bug-iconv-trans-ENV = LOCPATH=$(common-objpfx)localedata
@@ -292,6 +292,7 @@ bug-setlocale1-ARGS = -- $(host-test-program-cmd)
bug-setlocale1-static-ENV = $(bug-setlocale1-ENV)
bug-setlocale1-static-ARGS = $(bug-setlocale1-ARGS)
tst-setlocale2-ENV = LOCPATH=$(common-objpfx)localedata
tst-setlocale3-ENV = LOCPATH=$(common-objpfx)localedata
$(objdir)/iconvdata/gconv-modules:
$(MAKE) -C ../iconvdata subdir=iconvdata $@
+6
View File
@@ -49,11 +49,17 @@ for l in $lang; do
${common_objpfx}localedata/xfrm-test $id < $cns.in \
> ${common_objpfx}localedata/$cns.xout || here=1
cmp -s $cns.in ${common_objpfx}localedata/$cns.xout || here=1
LOCPATH=${common_objpfx}localedata GCONV_PATH=${common_objpfx}/iconvdata \
LC_ALL=$l ${test_program_prefix} \
${common_objpfx}localedata/xfrm-test $id -nocache < $cns.in \
> ${common_objpfx}localedata/$cns.nocache.xout || here=1
cmp -s $cns.in ${common_objpfx}localedata/$cns.nocache.xout || here=1
if test $here -eq 0; then
echo "$l xfrm-test OK"
else
echo "$l xfrm-test FAIL"
diff -u $cns.in ${common_objpfx}localedata/$cns.xout | sed 's/^/ /'
diff -u $cns.in ${common_objpfx}localedata/$cns.nocache.xout | sed 's/^/ /'
status=1
fi
done
+203
View File
@@ -0,0 +1,203 @@
/* Regression test for setlocale invalid environment variable handling.
Copyright (C) 2014 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#include <locale.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* The result of setlocale may be overwritten by subsequent calls, so
this wrapper makes a copy. */
static char *
setlocale_copy (int category, const char *locale)
{
const char *result = setlocale (category, locale);
if (result == NULL)
return NULL;
return strdup (result);
}
static char *de_locale;
static void
setlocale_fail (const char *envstring)
{
setenv ("LC_CTYPE", envstring, 1);
if (setlocale (LC_CTYPE, "") != NULL)
{
printf ("unexpected setlocale success for \"%s\" locale\n", envstring);
exit (1);
}
const char *newloc = setlocale (LC_CTYPE, NULL);
if (strcmp (newloc, de_locale) != 0)
{
printf ("failed setlocale call \"%s\" changed locale to \"%s\"\n",
envstring, newloc);
exit (1);
}
}
static void
setlocale_success (const char *envstring)
{
setenv ("LC_CTYPE", envstring, 1);
char *newloc = setlocale_copy (LC_CTYPE, "");
if (newloc == NULL)
{
printf ("setlocale for \"%s\": %m\n", envstring);
exit (1);
}
if (strcmp (newloc, de_locale) == 0)
{
printf ("setlocale with LC_CTYPE=\"%s\" left locale at \"%s\"\n",
envstring, de_locale);
exit (1);
}
if (setlocale (LC_CTYPE, de_locale) == NULL)
{
printf ("restoring locale \"%s\" with LC_CTYPE=\"%s\": %m\n",
de_locale, envstring);
exit (1);
}
char *newloc2 = setlocale_copy (LC_CTYPE, newloc);
if (newloc2 == NULL)
{
printf ("restoring locale \"%s\" following \"%s\": %m\n",
newloc, envstring);
exit (1);
}
if (strcmp (newloc, newloc2) != 0)
{
printf ("representation of locale \"%s\" changed from \"%s\" to \"%s\"",
envstring, newloc, newloc2);
exit (1);
}
free (newloc);
free (newloc2);
if (setlocale (LC_CTYPE, de_locale) == NULL)
{
printf ("restoring locale \"%s\" with LC_CTYPE=\"%s\": %m\n",
de_locale, envstring);
exit (1);
}
}
/* Checks that a known-good locale still works if LC_ALL contains a
value which should be ignored. */
static void
setlocale_ignore (const char *to_ignore)
{
const char *fr_locale = "fr_FR.UTF-8";
setenv ("LC_CTYPE", fr_locale, 1);
char *expected_locale = setlocale_copy (LC_CTYPE, "");
if (expected_locale == NULL)
{
printf ("setlocale with LC_CTYPE=\"%s\" failed: %m\n", fr_locale);
exit (1);
}
if (setlocale (LC_CTYPE, de_locale) == NULL)
{
printf ("failed to restore locale: %m\n");
exit (1);
}
unsetenv ("LC_CTYPE");
setenv ("LC_ALL", to_ignore, 1);
setenv ("LC_CTYPE", fr_locale, 1);
const char *actual_locale = setlocale (LC_CTYPE, "");
if (actual_locale == NULL)
{
printf ("setlocale with LC_ALL, LC_CTYPE=\"%s\" failed: %m\n",
fr_locale);
exit (1);
}
if (strcmp (actual_locale, expected_locale) != 0)
{
printf ("setlocale under LC_ALL failed: got \"%s\", expected \"%s\"\n",
actual_locale, expected_locale);
exit (1);
}
unsetenv ("LC_CTYPE");
setlocale_success (fr_locale);
unsetenv ("LC_ALL");
free (expected_locale);
}
static int
do_test (void)
{
/* The glibc test harness sets this environment variable
uncondionally. */
unsetenv ("LC_ALL");
de_locale = setlocale_copy (LC_CTYPE, "de_DE.UTF-8");
if (de_locale == NULL)
{
printf ("setlocale (LC_CTYPE, \"de_DE.UTF-8\"): %m\n");
return 1;
}
setlocale_success ("C");
setlocale_success ("en_US.UTF-8");
setlocale_success ("/en_US.UTF-8");
setlocale_success ("//en_US.UTF-8");
setlocale_ignore ("");
setlocale_fail ("does-not-exist");
setlocale_fail ("/");
setlocale_fail ("/../localedata/en_US.UTF-8");
setlocale_fail ("en_US.UTF-8/");
setlocale_fail ("en_US.UTF-8/..");
setlocale_fail ("en_US.UTF-8/../en_US.UTF-8");
setlocale_fail ("../localedata/en_US.UTF-8");
{
size_t large_length = 1024;
char *large_name = malloc (large_length + 1);
if (large_name == NULL)
{
puts ("malloc failure");
return 1;
}
memset (large_name, '/', large_length);
const char *suffix = "en_US.UTF-8";
strcpy (large_name + large_length - strlen (suffix), suffix);
setlocale_fail (large_name);
free (large_name);
}
{
size_t huge_length = 64 * 1024 * 1024;
char *huge_name = malloc (huge_length + 1);
if (huge_name == NULL)
{
puts ("malloc failure");
return 1;
}
memset (huge_name, 'X', huge_length);
huge_name[huge_length] = '\0';
/* Construct a composite locale specification. */
const char *prefix = "LC_CTYPE=de_DE.UTF-8;LC_TIME=";
memcpy (huge_name, prefix, strlen (prefix));
setlocale_fail (huge_name);
free (huge_name);
}
return 0;
}
#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"
+46 -6
View File
@@ -23,7 +23,10 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
/* Keep in sync with string/strxfrm_l.c. */
#define SMALL_STR_SIZE 4095
struct lines
{
@@ -37,6 +40,7 @@ int
main (int argc, char *argv[])
{
int result = 0;
bool nocache = false;
size_t nstrings, nstrings_max;
struct lines *strings;
char *line = NULL;
@@ -44,7 +48,18 @@ main (int argc, char *argv[])
size_t n;
if (argc < 2)
error (1, 0, "usage: %s <random seed>", argv[0]);
error (1, 0, "usage: %s <random seed> [-nocache]", argv[0]);
if (argc == 3)
{
if (strcmp (argv[2], "-nocache") == 0)
nocache = true;
else
{
printf ("Unknown option %s!\n", argv[2]);
exit (1);
}
}
setlocale (LC_ALL, "");
@@ -59,9 +74,9 @@ main (int argc, char *argv[])
while (1)
{
char saved, *newp;
int needed;
int l;
char saved, *word, *newp;
size_t l, line_len, needed;
if (getline (&line, &len, stdin) < 0)
break;
@@ -83,10 +98,35 @@ main (int argc, char *argv[])
saved = line[l];
line[l] = '\0';
needed = strxfrm (NULL, line, 0);
if (nocache)
{
line_len = strlen (line);
word = malloc (line_len + SMALL_STR_SIZE + 1);
if (word == NULL)
{
printf ("malloc failed: %m\n");
exit (1);
}
memset (word, ' ', SMALL_STR_SIZE);
memcpy (word + SMALL_STR_SIZE, line, line_len);
word[line_len + SMALL_STR_SIZE] = '\0';
}
else
word = line;
needed = strxfrm (NULL, word, 0);
newp = malloc (needed + 1);
strxfrm (newp, line, needed + 1);
if (newp == NULL)
{
printf ("malloc failed: %m\n");
exit (1);
}
strxfrm (newp, word, needed + 1);
strings[nstrings].xfrm = newp;
if (nocache)
free (word);
line[l] = saved;
++nstrings;
}
+42
View File
@@ -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;
}
+114 -32
View File
@@ -29,6 +29,7 @@ will follow the conventions preferred by the user.
* Setting the Locale:: How a program specifies the locale
with library functions.
* Standard Locales:: Locale names available on all systems.
* Locale Names:: Format of system-specific locale names.
* Locale Information:: How to access the information for the locale.
* Formatting Numbers:: A dedicated function to format numbers.
* Yes-or-No Questions:: Check a Response against the locale.
@@ -99,14 +100,16 @@ locale named @samp{espana-castellano} to use the standard conventions of
most of Spain.
The set of locales supported depends on the operating system you are
using, and so do their names. We can't make any promises about what
locales will exist, except for one standard locale called @samp{C} or
@samp{POSIX}. Later we will describe how to construct locales.
@comment (@pxref{Building Locale Files}).
using, and so do their names, except that the standard locale called
@samp{C} or @samp{POSIX} always exist. @xref{Locale Names}.
In order to force the system to always use the default locale, the
user can set the @code{LC_ALL} environment variable to @samp{C}.
@cindex combining locales
A user also has the option of specifying different locales for different
purposes---in effect, choosing a mixture of multiple locales.
A user also has the option of specifying different locales for
different purposes---in effect, choosing a mixture of multiple
locales. @xref{Locale Categories}.
For example, the user might specify the locale @samp{espana-castellano}
for most purposes, but specify the locale @samp{usa-english} for
@@ -120,7 +123,7 @@ which locales apply. However, the user can choose to use each locale
for a particular subset of those purposes.
@node Locale Categories, Setting the Locale, Choosing Locale, Locales
@section Categories of Activities that Locales Affect
@section Locale Categories
@cindex categories for locales
@cindex locale categories
@@ -128,7 +131,11 @@ The purposes that locales serve are grouped into @dfn{categories}, so
that a user or a program can choose the locale for each category
independently. Here is a table of categories; each name is both an
environment variable that a user can set, and a macro name that you can
use as an argument to @code{setlocale}.
use as the first argument to @code{setlocale}.
The contents of the environment variable (or the string in the second
argument to @code{setlocale}) has to be a valid locale name.
@xref{Locale Names}.
@vtable @code
@comment locale.h
@@ -172,7 +179,7 @@ for affirmative and negative responses.
@comment locale.h
@comment ISO
@item LC_ALL
This is not an environment variable; it is only a macro that you can use
This is not a category; it is only a macro that you can use
with @code{setlocale} to set a single locale for all purposes. Setting
this environment variable overwrites all selections by the other
@code{LC_*} variables or @code{LANG}.
@@ -355,13 +362,7 @@ The symbols in this section are defined in the header file @file{locale.h}.
@c strndup @ascuheap @acsmem
@c strcasecmp_l ok (C locale)
The function @code{setlocale} sets the current locale for category
@var{category} to @var{locale}. A list of all the locales the system
provides can be created by running
@pindex locale
@smallexample
locale -a
@end smallexample
@var{category} to @var{locale}.
If @var{category} is @code{LC_ALL}, this specifies the locale for all
purposes. The other possible values of @var{category} specify an
@@ -386,10 +387,9 @@ is passed in as @var{locale} parameter.
When you read the current locale for category @code{LC_ALL}, the value
encodes the entire combination of selected locales for all categories.
In this case, the value is not just a single locale name. In fact, we
don't make any promises about what it looks like. But if you specify
the same ``locale name'' with @code{LC_ALL} in a subsequent call to
@code{setlocale}, it restores the same combination of locale selections.
If you specify the same ``locale name'' with @code{LC_ALL} in a
subsequent call to @code{setlocale}, it restores the same combination
of locale selections.
To be sure you can use the returned string encoding the currently selected
locale at a later time, you must make a copy of the string. It is not
@@ -405,20 +405,15 @@ for @var{category}.
If a nonempty string is given for @var{locale}, then the locale of that
name is used if possible.
The effective locale name (either the second argument to
@code{setlocale}, or if the argument is an empty string, the name
obtained from the process environment) must be valid locale name.
@xref{Locale Names}.
If you specify an invalid locale name, @code{setlocale} returns a null
pointer and leaves the current locale unchanged.
@end deftypefun
The path used for finding locale data can be set using the
@code{LOCPATH} environment variable. The default path for finding
locale data is system specific. It is computed from the value given
as the prefix while configuring the C library. This value normally is
@file{/usr} or @file{/}. For the former the complete path is:
@smallexample
/usr/lib/locale
@end smallexample
Here is an example showing how you might use @code{setlocale} to
temporarily switch to a new locale.
@@ -458,7 +453,7 @@ locale categories, and future versions of the library will do so. For
portability, assume that any symbol beginning with @samp{LC_} might be
defined in @file{locale.h}.
@node Standard Locales, Locale Information, Setting the Locale, Locales
@node Standard Locales, Locale Names, Setting the Locale, Locales
@section Standard Locales
The only locale names you can count on finding on all operating systems
@@ -492,7 +487,94 @@ with the environment, rather than trying to specify some non-standard
locale explicitly by name. Remember, different machines might have
different sets of locales installed.
@node Locale Information, Formatting Numbers, Standard Locales, Locales
@node Locale Names, Locale Information, Standard Locales, Locales
@section Locale Names
The following command prints a list of locales supported by the
system:
@pindex locale
@smallexample
locale -a
@end smallexample
@strong{Portability Note:} With the notable exception of the standard
locale names @samp{C} and @samp{POSIX}, locale names are
system-specific.
Most locale names follow XPG syntax and consist of up to four parts:
@smallexample
@var{language}[_@var{territory}[.@var{codeset}]][@@@var{modifier}]
@end smallexample
Beside the first part, all of them are allowed to be missing. If the
full specified locale is not found, less specific ones are looked for.
The various parts will be stripped off, in the following order:
@enumerate
@item
codeset
@item
normalized codeset
@item
territory
@item
modifier
@end enumerate
For example, the locale name @samp{de_AT.iso885915@@euro} denotes a
German-language locale for use in Austria, using the ISO-8859-15
(Latin-9) character set, and with the Euro as the currency symbol.
In addition to locale names which follow XPG syntax, systems may
provide aliases such as @samp{german}. Both categories of names must
not contain the slash character @samp{/}.
If the locale name starts with a slash @samp{/}, it is treated as a
path relative to the configured locale directories; see @code{LOCPATH}
below. The specified path must not contain a component @samp{..}, or
the name is invalid, and @code{setlocale} will fail.
@strong{Portability Note:} POSIX suggests that if a locale name starts
with a slash @samp{/}, it is resolved as an absolute path. However,
@theglibc{} treats it as a relative path under the directories listed
in @code{LOCPATH} (or the default locale directory if @code{LOCPATH}
is unset).
Locale names which are longer than an implementation-defined limit are
invalid and cause @code{setlocale} to fail.
As a special case, locale names used with @code{LC_ALL} can combine
several locales, reflecting different locale settings for different
categories. For example, you might want to use a U.S. locale with ISO
A4 paper format, so you set @code{LANG} to @samp{en_US.UTF-8}, and
@code{LC_PAPER} to @samp{de_DE.UTF-8}. In this case, the
@code{LC_ALL}-style combined locale name is
@smallexample
LC_CTYPE=en_US.UTF-8;LC_TIME=en_US.UTF-8;LC_PAPER=de_DE.UTF-8;@dots{}
@end smallexample
followed by other category settings not shown here.
@vindex LOCPATH
The path used for finding locale data can be set using the
@code{LOCPATH} environment variable. This variable lists the
directories in which to search for locale definitions, separated by a
colon @samp{:}.
The default path for finding locale data is system specific. A typical
value for the @code{LOCPATH} default is:
@smallexample
/usr/share/locale
@end smallexample
The value of @code{LOCPATH} is ignored by privileged programs for
security reasons, and only the default directory is used.
@node Locale Information, Formatting Numbers, Locale Names, Locales
@section Accessing Locale Information
There are several ways to access locale information. The simplest
+38 -1
View File
@@ -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
View File
@@ -76,7 +76,8 @@ install-lib := libg.a
gpl2lgpl := error.c error.h
tests := tst-dirname tst-tsearch tst-fdset tst-efgcvt tst-mntent tst-hsearch \
tst-error1 tst-pselect tst-insremque tst-mntent2 bug-hsearch1
tst-error1 tst-pselect tst-insremque tst-mntent2 bug-hsearch1 \
bug18240
ifeq ($(run-built-tests),yes)
tests: $(objpfx)tst-error1-mem
endif
+97
View File
@@ -0,0 +1,97 @@
/* Test integer wraparound in hcreate.
Copyright (C) 2016 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#include <errno.h>
#include <limits.h>
#include <search.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/resource.h>
static void
test_size (size_t size)
{
int res = hcreate (size);
if (res == 0)
{
if (errno == ENOMEM)
return;
printf ("error: hcreate (%zu): %m\n", size);
exit (1);
}
char *keys[100];
for (int i = 0; i < 100; ++i)
{
if (asprintf (keys + i, "%d", i) < 0)
{
printf ("error: asprintf: %m\n");
exit (1);
}
ENTRY e = { keys[i], (char *) "value" };
if (hsearch (e, ENTER) == NULL)
{
printf ("error: hsearch (\"%s\"): %m\n", keys[i]);
exit (1);
}
}
hdestroy ();
for (int i = 0; i < 100; ++i)
free (keys[i]);
}
static int
do_test (void)
{
/* Limit the size of the process, so that memory allocation will
fail without impacting the entire system. */
{
struct rlimit limit;
if (getrlimit (RLIMIT_AS, &limit) != 0)
{
printf ("getrlimit (RLIMIT_AS) failed: %m\n");
return 1;
}
long target = 100 * 1024 * 1024;
if (limit.rlim_cur == RLIM_INFINITY || limit.rlim_cur > target)
{
limit.rlim_cur = target;
if (setrlimit (RLIMIT_AS, &limit) != 0)
{
printf ("setrlimit (RLIMIT_AS) failed: %m\n");
return 1;
}
}
}
test_size (500);
test_size (-1);
test_size (-3);
test_size (INT_MAX - 2);
test_size (INT_MAX - 1);
test_size (INT_MAX);
test_size (((unsigned) INT_MAX) + 1);
test_size (UINT_MAX - 2);
test_size (UINT_MAX - 1);
test_size (UINT_MAX);
return 0;
}
#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"
+18 -12
View File
@@ -19,7 +19,7 @@
#include <errno.h>
#include <malloc.h>
#include <string.h>
#include <stdint.h>
#include <search.h>
/* [Aho,Sethi,Ullman] Compilers: Principles, Techniques and Tools, 1986
@@ -46,15 +46,12 @@ static int
isprime (unsigned int number)
{
/* no even number will be passed */
unsigned int div = 3;
while (div * div < number && number % div != 0)
div += 2;
return number % div != 0;
for (unsigned int div = 3; div <= number / div; div += 2)
if (number % div == 0)
return 0;
return 1;
}
/* Before using the hash table we must allocate memory for it.
Test for an existing table are done. We allocate one element
more as the found prime number says. This is done for more effective
@@ -81,10 +78,19 @@ hcreate_r (nel, htab)
use will not work. */
if (nel < 3)
nel = 3;
/* Change nel to the first prime number not smaller as nel. */
nel |= 1; /* make odd */
while (!isprime (nel))
nel += 2;
/* Change nel to the first prime number in the range [nel, UINT_MAX - 2],
The '- 2' means 'nel += 2' cannot overflow. */
for (nel |= 1; ; nel += 2)
{
if (UINT_MAX - 2 < nel)
{
__set_errno (ENOMEM);
return 0;
}
if (isprime (nel))
break;
}
htab->size = nel;
htab->filled = 0;
+2
View File
@@ -26,6 +26,7 @@ __BEGIN_DECLS
/* The following constants should be used for the fifth parameter of
`*setxattr'. */
#ifndef __USE_KERNEL_XATTR_DEFS
enum
{
XATTR_CREATE = 1, /* set value, fail if attr already exists. */
@@ -33,6 +34,7 @@ enum
XATTR_REPLACE = 2 /* set value, fail if attr does not exist. */
#define XATTR_REPLACE XATTR_REPLACE
};
#endif
/* Set the attribute NAME of the file pointed to by PATH to VALUE (which
is SIZE bytes long). Return 0 on success, -1 for errors. */
+14
View File
@@ -270,6 +270,13 @@ internal_gethostbyname2_r (const char *name, int af, struct hostent *host,
/* Convert name to lowercase. */
size_t namlen = strlen (name);
/* Limit name length to the maximum size of an RPC packet. */
if (namlen > UDPMSGSIZE)
{
*errnop = ERANGE;
return NSS_STATUS_UNAVAIL;
}
char name2[namlen + 1];
size_t i;
@@ -461,6 +468,13 @@ _nss_nis_gethostbyname4_r (const char *name, struct gaih_addrtuple **pat,
/* Convert name to lowercase. */
size_t namlen = strlen (name);
/* Limit name length to the maximum size of an RPC packet. */
if (namlen > UDPMSGSIZE)
{
*errnop = ERANGE;
return NSS_STATUS_UNAVAIL;
}
char name2[namlen + 1];
size_t i;
+7
View File
@@ -150,6 +150,13 @@ initgroups_netid (uid_t uid, gid_t group, long int *start, long int *size,
gid_t **groupsp, long int limit, int *errnop,
const char *domainname)
{
/* Limit domainname length to the maximum size of an RPC packet. */
if (strlen (domainname) > UDPMSGSIZE)
{
*errnop = ERANGE;
return NSS_STATUS_UNAVAIL;
}
/* Prepare the key. The form is "unix.UID@DOMAIN" with the UID and
DOMAIN field filled in appropriately. */
char key[sizeof ("unix.@") + sizeof (uid_t) * 3 + strlen (domainname)];
+7
View File
@@ -179,6 +179,13 @@ _nss_nis_getnetbyname_r (const char *name, struct netent *net, char *buffer,
/* Convert name to lowercase. */
size_t namlen = strlen (name);
/* Limit name length to the maximum size of an RPC packet. */
if (namlen > UDPMSGSIZE)
{
*errnop = ERANGE;
return NSS_STATUS_UNAVAIL;
}
char name2[namlen + 1];
size_t i;
+14
View File
@@ -271,6 +271,13 @@ _nss_nis_getservbyname_r (const char *name, const char *protocol,
/* If the protocol is given, we could try if our NIS server knows
about services.byservicename map. If yes, we only need one query. */
size_t keylen = strlen (name) + (protocol ? 1 + strlen (protocol) : 0);
/* Limit key length to the maximum size of an RPC packet. */
if (keylen > UDPMSGSIZE)
{
*errnop = ERANGE;
return NSS_STATUS_UNAVAIL;
}
char key[keylen + 1];
/* key is: "name/proto" */
@@ -355,6 +362,13 @@ _nss_nis_getservbyport_r (int port, const char *protocol,
Otherwise try first port/tcp, then port/udp and then fallback
to sequential scanning of services.byname. */
const char *proto = protocol != NULL ? protocol : "tcp";
/* Limit protocol name length to the maximum size of an RPC packet. */
if (strlen (proto) > UDPMSGSIZE)
{
*errnop = ERANGE;
return NSS_STATUS_UNAVAIL;
}
do
{
/* key is: "port/proto" */
+1 -1
View File
@@ -208,7 +208,7 @@ tests = tst-typesizes \
tst-mutexpi1 tst-mutexpi2 tst-mutexpi3 tst-mutexpi4 tst-mutexpi5 \
tst-mutexpi5a tst-mutexpi6 tst-mutexpi7 tst-mutexpi7a tst-mutexpi8 \
tst-mutexpi9 \
tst-spin1 tst-spin2 tst-spin3 \
tst-spin1 tst-spin2 tst-spin3 tst-spin4 \
tst-cond1 tst-cond2 tst-cond3 tst-cond4 tst-cond5 tst-cond6 tst-cond7 \
tst-cond8 tst-cond9 tst-cond10 tst-cond11 tst-cond12 tst-cond13 \
tst-cond14 tst-cond15 tst-cond16 tst-cond17 tst-cond18 tst-cond19 \
+4 -5
View File
@@ -26,8 +26,8 @@
#define lll_trylock_elision(a,t) lll_trylock(a)
#endif
#ifndef DO_ELISION
#define DO_ELISION(m) 0
#ifndef FORCE_ELISION
#define FORCE_ELISION(m, s)
#endif
/* We don't force elision in trylock, because this can lead to inconsistent
@@ -69,7 +69,7 @@ __pthread_mutex_trylock (mutex)
break;
case PTHREAD_MUTEX_TIMED_ELISION_NP:
elision:
elision: __attribute__((unused))
if (lll_trylock_elision (mutex->__data.__lock,
mutex->__data.__elision) != 0)
break;
@@ -77,8 +77,7 @@ __pthread_mutex_trylock (mutex)
return 0;
case PTHREAD_MUTEX_TIMED_NP:
if (DO_ELISION (mutex))
goto elision;
FORCE_ELISION (mutex, goto elision);
/*FALL THROUGH*/
case PTHREAD_MUTEX_ADAPTIVE_NP:
case PTHREAD_MUTEX_ERRORCHECK_NP:
@@ -19,11 +19,11 @@
.text
ENTRY(pthread_spin_lock)
ldstub [%o0], %g1
1: ldstub [%o0], %g1
orcc %g1, 0x0, %g0
bne,a 2f
ldub [%o0], %g1
1: retl
retl
mov 0, %o0
2: orcc %g1, 0x0, %g0
bne,a 2b
@@ -19,10 +19,10 @@
.text
ENTRY(pthread_spin_lock)
ldstub [%o0], %g1
1: ldstub [%o0], %g1
brnz,pn %g1, 2f
membar #StoreLoad | #StoreStore
1: retl
retl
mov 0, %o0
2: ldub [%o0], %g1
brnz,pt %g1, 2b
+20 -39
View File
@@ -1,4 +1,4 @@
/* Copyright (C) 2013 Free Software Foundation, Inc.
/* Copyright (C) 2014 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -15,49 +15,30 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>.
This is a copy of pthread/pt-longjmp.c made for extending the
jmpbuf structure on System z. */
Versioned copy of nptl/pt-longjmp.c modified for versioning
the reverted jmpbuf extension. */
#include <setjmp.h>
#include <stdlib.h>
#include <bits/wordsize.h>
#include "pthreadP.h"
#include <shlib-compat.h>
#if defined SHARED && SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_19)
/* The __v1 version prototypes are declared in v1-setjmp.h which
cannot be included together with setjmp.h. So we put the
prototypes here manually. */
extern void __v1__libc_siglongjmp (sigjmp_buf env, int val)
__attribute__ ((noreturn));
extern void __v1__libc_longjmp (sigjmp_buf env, int val)
__attribute__ ((noreturn));
#if defined SHARED && SHLIB_COMPAT (libpthread, GLIBC_2_19, GLIBC_2_20)
/* we need a unique name in case of symbol versioning. */
# define longjmp __v1longjmp
#endif /* defined SHARED && SHLIB_COMPAT (libpthread, GLIBC_2_19, GLIBC_2_20)) */
void __v1_siglongjmp (sigjmp_buf env, int val)
{
__v1__libc_siglongjmp (env, val);
}
#include <nptl/sysdeps/pthread/pt-longjmp.c>
void __v1_longjmp (jmp_buf env, int val)
{
__v1__libc_longjmp (env, val);
}
#if defined SHARED && SHLIB_COMPAT (libpthread, GLIBC_2_19, GLIBC_2_20)
/* In glibc release 2.19 new versions of longjmp-functions were introduced,
but were reverted before 2.20. Thus both versions are the same function. */
compat_symbol (libpthread, __v1_longjmp, longjmp, GLIBC_2_0);
compat_symbol (libpthread, __v1_siglongjmp, siglongjmp, GLIBC_2_0);
#endif /* defined SHARED && SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_19)) */
# undef longjmp
void
__v2_longjmp (jmp_buf env, int val)
{
__libc_longjmp (env, val);
}
strong_alias (__v1longjmp, __v2longjmp)
versioned_symbol (libpthread, __v1longjmp, longjmp, GLIBC_2_0);
compat_symbol (libpthread, __v2longjmp, longjmp, GLIBC_2_19);
void
__v2_siglongjmp (jmp_buf env, int val)
{
__libc_siglongjmp (env, val);
}
versioned_symbol (libpthread, __v2_longjmp, longjmp, GLIBC_2_19);
versioned_symbol (libpthread, __v2_siglongjmp, siglongjmp, GLIBC_2_19);
weak_alias (siglongjmp, __v1siglongjmp)
weak_alias (siglongjmp, __v2siglongjmp)
versioned_symbol (libpthread, __v1siglongjmp, siglongjmp, GLIBC_2_0);
compat_symbol (libpthread, __v2siglongjmp, siglongjmp, GLIBC_2_19);
#endif /* defined SHARED && SHLIB_COMPAT (libpthread, GLIBC_2_19, GLIBC_2_20)) */
@@ -16,11 +16,6 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
/* Check for elision on this lock without upgrading. */
#define DO_ELISION(m) \
(__pthread_force_elision \
&& (m->__data.__kind & PTHREAD_MUTEX_NO_ELISION_NP) == 0) \
/* Automatically enable elision for existing user lock kinds. */
#define FORCE_ELISION(m, s) \
if (__pthread_force_elision \
+109
View File
@@ -0,0 +1,109 @@
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
static int count = 0;
static void *
thread_add_one (void *arg)
{
int tmp;
pthread_spinlock_t *lock = (pthread_spinlock_t *) arg;
/* When do_test holds the lock for 1 sec, the two thread will be
in contention for the lock. */
if (pthread_spin_lock (lock) != 0)
{
puts ("thread_add_one(): spin_lock failed");
pthread_exit ((void *) 1l);
}
/* sleep 1s before modifying count */
tmp = count;
sleep (1);
count = tmp + 1;
if (pthread_spin_unlock (lock) != 0)
{
puts ("thread_add_one(): spin_unlock failed");
pthread_exit ((void *) 1l);
}
return NULL;
}
static int
do_test (void)
{
pthread_t thr1, thr2;
pthread_spinlock_t lock;
int tmp;
if (pthread_spin_init (&lock, PTHREAD_PROCESS_PRIVATE) != 0)
{
puts ("spin_init failed");
return 1;
}
if (pthread_spin_lock (&lock) != 0)
{
puts ("1st spin_lock failed");
return 1;
}
if (pthread_create (&thr1, NULL, thread_add_one, (void *) &lock) != 0)
{
puts ("1st pthread_create failed");
return 1;
}
if (pthread_create (&thr2, NULL, thread_add_one, (void *) &lock) != 0)
{
puts ("2nd pthread_create failed");
return 1;
}
/* sleep 1s before modifying count */
tmp = count;
sleep (1);
count = tmp + 1;
if (pthread_spin_unlock (&lock) != 0)
{
puts ("1st spin_unlock failed");
return 1;
}
void *status;
if (pthread_join (thr1, &status) != 0)
{
puts ("1st pthread_join failed");
return 1;
}
if (status != NULL)
{
puts ("failure in the 1st thread");
return 1;
}
if (pthread_join (thr2, &status) != 0)
{
puts ("2nd pthread_join failed");
return 1;
}
if (status != NULL)
{
puts ("failure in the 2nd thread");
return 1;
}
if (count != 3)
{
printf ("count is %d, should be 3\n", count);
return 1;
}
return 0;
}
#define TIMEOUT 5
#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"
+26 -16
View File
@@ -202,12 +202,7 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
{
int e;
status = getfct.f (&data, buffer + buffilled,
buflen - buffilled, &e);
if (status == NSS_STATUS_RETURN
|| status == NSS_STATUS_NOTFOUND)
/* This was either the last one for this group or the
group was empty. Look at next group if available. */
break;
buflen - buffilled - req->key_len, &e);
if (status == NSS_STATUS_SUCCESS)
{
if (data.type == triple_val)
@@ -216,6 +211,10 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
const char *nuser = data.val.triple.user;
const char *ndomain = data.val.triple.domain;
size_t hostlen = strlen (nhost ?: "") + 1;
size_t userlen = strlen (nuser ?: "") + 1;
size_t domainlen = strlen (ndomain ?: "") + 1;
if (nhost == NULL || nuser == NULL || ndomain == NULL
|| nhost > nuser || nuser > ndomain)
{
@@ -233,9 +232,6 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
: last + strlen (last) + 1 - buffer);
/* We have to make temporary copies. */
size_t hostlen = strlen (nhost ?: "") + 1;
size_t userlen = strlen (nuser ?: "") + 1;
size_t domainlen = strlen (ndomain ?: "") + 1;
size_t needed = hostlen + userlen + domainlen;
if (buflen - req->key_len - bufused < needed)
@@ -269,9 +265,12 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
}
char *wp = buffer + buffilled;
wp = stpcpy (wp, nhost) + 1;
wp = stpcpy (wp, nuser) + 1;
wp = stpcpy (wp, ndomain) + 1;
wp = memmove (wp, nhost ?: "", hostlen);
wp += hostlen;
wp = memmove (wp, nuser ?: "", userlen);
wp += userlen;
wp = memmove (wp, ndomain ?: "", domainlen);
wp += domainlen;
buffilled = wp - buffer;
++nentries;
}
@@ -322,11 +321,18 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
}
}
}
else if (status == NSS_STATUS_UNAVAIL && e == ERANGE)
else if (status == NSS_STATUS_TRYAGAIN && e == ERANGE)
{
buflen *= 2;
buffer = xrealloc (buffer, buflen);
}
else if (status == NSS_STATUS_RETURN
|| status == NSS_STATUS_NOTFOUND
|| status == NSS_STATUS_UNAVAIL)
/* This was either the last one for this group or the
group was empty or the NSS module had an internal
failure. Look at next group if available. */
break;
}
enum nss_status (*endfct) (struct __netgrent *);
@@ -560,15 +566,19 @@ addinnetgrX (struct database_dyn *db, int fd, request_header *req,
{
bool success = true;
if (host != NULL)
/* For the host, user and domain in each triplet, we assume success
if the value is blank because that is how the wildcard entry to
match anything is stored in the netgroup cache. */
if (host != NULL && *triplets != '\0')
success = strcmp (host, triplets) == 0;
triplets = (const char *) rawmemchr (triplets, '\0') + 1;
if (success && user != NULL)
if (success && user != NULL && *triplets != '\0')
success = strcmp (user, triplets) == 0;
triplets = (const char *) rawmemchr (triplets, '\0') + 1;
if (success && (domain == NULL || strcmp (domain, triplets) == 0))
if (success && (domain == NULL || *triplets == '\0'
|| strcmp (domain, triplets) == 0))
{
dataset->resp.result = 1;
break;
+1 -1
View File
@@ -37,7 +37,7 @@ install-bin := getent makedb
makedb-modules = xmalloc hash-string
extra-objs += $(makedb-modules:=.o)
tests = test-netdb tst-nss-test1 test-digits-dots
tests = test-netdb tst-nss-test1 test-digits-dots tst-nss-getpwent
xtests = bug-erange
include ../Makeconfig
+4 -2
View File
@@ -134,7 +134,7 @@ CONCAT(_nss_files_set,ENTNAME) (int stayopen)
__libc_lock_lock (lock);
status = internal_setent (stayopen);
status = internal_setent (1);
if (status == NSS_STATUS_SUCCESS && fgetpos (stream, &position) < 0)
{
@@ -198,10 +198,12 @@ get_contents (char *linebuf, size_t len, FILE *stream)
{
int curlen = ((remaining_len > (size_t) INT_MAX) ? INT_MAX
: remaining_len);
char *p = fgets_unlocked (curbuf, curlen, stream);
/* Terminate the line so that we can test for overflow. */
((unsigned char *) curbuf)[curlen - 1] = 0xff;
char *p = fgets_unlocked (curbuf, curlen, stream);
/* EOF or read error. */
if (p == NULL)
return gcr_error;
+1 -1
View File
@@ -252,7 +252,7 @@ _nss_netgroup_parseline (char **cursor, struct __netgrent *result,
if (cp - host > buflen)
{
*errnop = ERANGE;
status = NSS_STATUS_UNAVAIL;
status = NSS_STATUS_TRYAGAIN;
}
else
{
+118
View File
@@ -0,0 +1,118 @@
/* Copyright (C) 2015 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#include <pwd.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int
do_test (void)
{
/* Count the number of entries in the password database, and fetch
data from the first and last entries. */
size_t count = 0;
struct passwd * pw;
char *first_name = NULL;
uid_t first_uid = 0;
char *last_name = NULL;
uid_t last_uid = 0;
setpwent ();
while ((pw = getpwent ()) != NULL)
{
if (first_name == NULL)
{
first_name = strdup (pw->pw_name);
if (first_name == NULL)
{
printf ("strdup: %m\n");
return 1;
}
first_uid = pw->pw_uid;
}
free (last_name);
last_name = strdup (pw->pw_name);
if (last_name == NULL)
{
printf ("strdup: %m\n");
return 1;
}
last_uid = pw->pw_uid;
++count;
}
endpwent ();
if (count == 0)
{
printf ("No entries in the password database.\n");
return 0;
}
/* Try again, this time interleaving with name-based and UID-based
lookup operations. The counts do not match if the interleaved
lookups affected the enumeration. */
size_t new_count = 0;
setpwent ();
while ((pw = getpwent ()) != NULL)
{
if (new_count == count)
{
printf ("Additional entry in the password database.\n");
return 1;
}
++new_count;
struct passwd *pw2 = getpwnam (first_name);
if (pw2 == NULL)
{
printf ("getpwnam (%s) failed: %m\n", first_name);
return 1;
}
pw2 = getpwnam (last_name);
if (pw2 == NULL)
{
printf ("getpwnam (%s) failed: %m\n", last_name);
return 1;
}
pw2 = getpwuid (first_uid);
if (pw2 == NULL)
{
printf ("getpwuid (%llu) failed: %m\n",
(unsigned long long) first_uid);
return 1;
}
pw2 = getpwuid (last_uid);
if (pw2 == NULL)
{
printf ("getpwuid (%llu) failed: %m\n",
(unsigned long long) last_uid);
return 1;
}
}
endpwent ();
if (new_count < count)
{
printf ("Missing entry in the password database.\n");
return 1;
}
return 0;
}
#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"
+11 -11
View File
@@ -10,7 +10,7 @@ msgstr ""
"Project-Id-Version: libc 2.18.90.20140105\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2014-01-05 17:40+1000\n"
"PO-Revision-Date: 2014-01-08 21:23+0100\n"
"PO-Revision-Date: 2014-04-22 22:50+0200\n"
"Last-Translator: Benno Schulenberg <benno@vertaalt.nl>\n"
"Language-Team: Esperanto <translation-team-eo@lists.sourceforge.net>\n"
"Language: eo\n"
@@ -967,7 +967,7 @@ msgstr "mankas dosieraj argumentoj"
#. TRANS expected to already exist.
#: elf/ldd.bash.in:147 sysdeps/gnu/errlist.c:36
msgid "No such file or directory"
msgstr "Dosiero aü dosierujo ne ekzistas"
msgstr "Dosiero aŭ dosierujo ne ekzistas"
#: elf/ldd.bash.in:150 inet/rcmd.c:488
msgid "not regular file"
@@ -992,7 +992,7 @@ msgstr "eraro: vi ne havas permeson legi"
#: elf/pldd-xx.c:105
#, c-format
msgid "cannot find program header of process"
msgstr ""
msgstr "ne eblas trovi programĉapon de procezo"
#: elf/pldd-xx.c:110
#, c-format
@@ -1055,7 +1055,7 @@ msgstr "ne eblas malfermi %s/task"
#: elf/pldd.c:145
#, c-format
msgid "cannot prepare reading %s/task"
msgstr ""
msgstr "ne eblas prepari legado de %s/task"
#: elf/pldd.c:158
#, c-format
@@ -1070,7 +1070,7 @@ msgstr ""
#: elf/pldd.c:261
#, c-format
msgid "cannot get information about process %lu"
msgstr ""
msgstr "ne eblas ekhavi informon pri procezo %lu"
#: elf/pldd.c:274
#, c-format
@@ -1080,7 +1080,7 @@ msgstr "procezo %lu ne estas ELF-programo"
#: elf/readelflib.c:34
#, c-format
msgid "file %s is truncated\n"
msgstr ""
msgstr "dosiero %s trunkiĝis\n"
#: elf/readelflib.c:66
#, c-format
@@ -1105,7 +1105,7 @@ msgstr ""
#: elf/readelflib.c:108
#, c-format
msgid "more than one dynamic segment\n"
msgstr ""
msgstr "pli ol unu dinamika segmento\n"
#: elf/readlib.c:96
#, c-format
@@ -1191,7 +1191,7 @@ msgstr ""
#: elf/sotruss.ksh:46
msgid "Mandatory arguments to long options are also mandatory for any corresponding\\nshort options.\\n"
msgstr ""
msgstr "Endaj argumentoj por longaj opcioj ankaŭ endas por korespondaj mallongaj opcioj.\\n"
#: elf/sotruss.ksh:55
msgid "%s: option requires an argument -- '%s'\\n"
@@ -1576,7 +1576,7 @@ msgstr "malsukcesis eltrovi statinformon"
#: inet/rcmd.c:493
msgid "cannot open"
msgstr ""
msgstr "ne eblas malfermi"
#: inet/rcmd.c:495
msgid "fstat failed"
@@ -5788,7 +5788,7 @@ msgstr "Eraro de en-eligo"
#. TRANS computer.
#: sysdeps/gnu/errlist.c:82
msgid "No such device or address"
msgstr "Tiu aparato aü adreso ne ekzistas"
msgstr "Tiu aparato aŭ adreso ne ekzistas"
#. TRANS Argument list too long; used when the arguments passed to a new program
#. TRANS being executed with one of the @code{exec} functions (@pxref{Executing a
@@ -6311,7 +6311,7 @@ msgstr "Ne subtenatas"
#. TRANS or an incomplete sequence of bytes or the given wide character is invalid.
#: sysdeps/gnu/errlist.c:931
msgid "Invalid or incomplete multibyte or wide character"
msgstr "Nevalida aü nekompleta plurbajta aü larĝa signo"
msgstr "Nevalida aŭ nekompleta plurbajta aŭ larĝa signo"
#. TRANS On @gnuhurdsystems{}, servers supporting the @code{term} protocol return
#. TRANS this error for certain operations when the caller is not in the
+6 -6
View File
@@ -6,7 +6,7 @@ msgid ""
msgstr ""
"Project-Id-Version: libc 2.18.90.20140105\n"
"POT-Creation-Date: 2014-01-05 17:40+1000\n"
"PO-Revision-Date: 2014-01-09 10:33+0100\n"
"PO-Revision-Date: 2014-05-06 18:15+0200\n"
"Last-Translator: Jan Djärv <jan.h.d@swipnet.se>\n"
"Language-Team: Swedish <tp-sv@listor.tp-sv.se>\n"
"Language: sv\n"
@@ -883,7 +883,7 @@ msgstr "bibliotek %s och %s i katalog %s har samma \"soname\" men olika typ."
#: elf/ldconfig.c:1072
#, c-format
msgid "Warning: ignoring configuration file that cannot be opened: %s"
msgstr "Varning: Ignorerar konfigurationsfil som inte kan öppnas: %s"
msgstr "Varning: ignorerar konfigurationsfil som inte kan öppnas: %s"
#: elf/ldconfig.c:1138
#, c-format
@@ -4104,7 +4104,7 @@ msgstr "Skapa inte barnprocess, visa meddelanden på nuvarande tty"
#: nscd/nscd.c:120
msgid "Do not fork, but otherwise behave like a daemon"
msgstr "Skapa inte brnprocess, men i allt annat uppträd som en demon"
msgstr "Skapa inte barnprocess, men i allt annat uppträd som en demon"
#: nscd/nscd.c:121
msgid "NUMBER"
@@ -4630,7 +4630,7 @@ msgstr "problem när \"%s\" lästes"
#: nss/makedb.c:799
#, c-format
msgid "failed to write new database file"
msgstr "misslyckades med att skriva databasfil"
msgstr "misslyckades med att skriva ny databasfil"
#: nss/makedb.c:812
#, c-format
@@ -5496,7 +5496,7 @@ msgstr "-Y sökväg\t\tkatalog för att hitta C preprocessorn (cpp)\n"
#: sunrpc/rpc_main.c:1445
#, c-format
msgid "-5\t\tSysVr4 compatibility mode\n"
msgstr "-5\t\tSysVr4 kompabilitetsläge\n"
msgstr "-5\t\tSysVr4-kompatibilitetsläge\n"
#: sunrpc/rpc_main.c:1446
#, c-format
@@ -6812,7 +6812,7 @@ msgid ""
"\n"
"Report bugs to %s.\n"
msgstr ""
"%s: användning är %s [ --version ] [ --help ] [ -{vV} ] [ -{ct} [start,]slut] zonnamn ...\n"
"%s: användning: %s [ --version ] [ --help ] [ -{vV} ] [ -{ct} [start,]slut] zonnamn ...\n"
"Rapportera fel till %s.\n"
"Rapportera fel eller synpunkter på översättningen till <tp-sv@listor.tp-sv.se>.\n"
+6
View File
@@ -1,3 +1,9 @@
2014-05-21 Richard Henderson <rth@redhat.com>
* sysdeps/unix/sysv/linux/aarch64/nptl/sysdep-cancel.h
(SINGLE_THREAD_P): Use the correct width load. Fold an add
into the ldr offset.
2014-01-22 Marcus Shawcroft <marcus.shawcroft@arm.com>
* sysdeps/aarch64/libm-test-ulps: Regenerated.
-1
View File
@@ -47,7 +47,6 @@ _start:
/* Create an initial frame with 0 LR and FP */
mov x29, #0
mov x30, #0
mov x29, sp
/* Setup rtld_fini in argument register */
mov x5, x0
@@ -162,9 +162,8 @@ extern int __local_multiple_threads attribute_hidden;
# else
# define SINGLE_THREAD_P \
adrp x16, __local_multiple_threads; \
add x16, x16, #:lo12:__local_multiple_threads; \
ldr x16, [x16]; \
cmp x16, 0;
ldr w16, [x16, :lo12:__local_multiple_threads]; \
cmp w16, 0;
# endif
# else
/* There is no __local_multiple_threads for librt, so use the TCB. */
@@ -180,12 +179,12 @@ extern int __local_multiple_threads attribute_hidden;
cfi_rel_offset (x30, 8); \
bl __read_tp; \
sub x0, x0, PTHREAD_SIZEOF; \
ldr x16, [x0, PTHREAD_MULTIPLE_THREADS_OFFSET]; \
ldr w16, [x0, PTHREAD_MULTIPLE_THREADS_OFFSET]; \
ldp x0, x30, [sp], 16; \
cfi_restore (x0); \
cfi_restore (x30); \
cfi_adjust_cfa_offset (-16); \
cmp x16, 0
cmp w16, 0
# define SINGLE_THREAD_P_PIC(x) SINGLE_THREAD_P
# endif
# endif
@@ -86,12 +86,19 @@ weak_alias(__setcontext, setcontext)
/* Called when a makecontext() context returns. Start the
context in R4 or fall through to exit(). */
/* Unwind descriptors are looked up based on PC - 2, so we have to
make sure to mark the instruction preceding the __startcontext
label as .cantunwind. */
.fnstart
.cantunwind
nop
ENTRY(__startcontext)
movs r0, r4
bne PLTJMP(__setcontext)
@ New context was 0 - exit
b PLTJMP(HIDDEN_JUMPTARGET(_exit))
.fnend
END(__startcontext)
#ifdef PIC
+3 -3
View File
@@ -22,14 +22,14 @@
#include <stdio.h>
#include <sysdep-cancel.h>
/* Open FILE with access OFLAG. If OFLAG includes O_CREAT,
/* Open FILE with access OFLAG. If O_CREAT or O_TMPFILE is in OFLAG,
a third argument is the file protection. */
int
__libc_open (const char *file, int oflag, ...)
{
int mode = 0;
if (oflag & O_CREAT)
if (__OPEN_NEEDS_MODE (oflag))
{
va_list arg;
va_start (arg, oflag);
@@ -59,7 +59,7 @@ __open_nocancel (const char *file, int oflag, ...)
{
int mode = 0;
if (oflag & O_CREAT)
if (__OPEN_NEEDS_MODE (oflag))
{
va_list arg;
va_start (arg, oflag);
@@ -22,14 +22,14 @@
#include <stdio.h>
#include <sysdep-cancel.h>
/* Open FILE with access OFLAG. If OFLAG includes O_CREAT,
/* Open FILE with access OFLAG. If O_CREAT or O_TMPFILE is in OFLAG,
a third argument is the file protection. */
int
__libc_open64 (const char *file, int oflag, ...)
{
int mode = 0;
if (oflag & O_CREAT)
if (__OPEN_NEEDS_MODE (oflag))
{
va_list arg;
va_start (arg, oflag);
+8 -2
View File
@@ -86,7 +86,7 @@ tests := tstgetopt testfnm runtests runptests \
tst-getaddrinfo3 tst-fnmatch2 tst-cpucount tst-cpuset \
bug-getopt1 bug-getopt2 bug-getopt3 bug-getopt4 \
bug-getopt5 tst-getopt_long1 bug-regex34 bug-regex35 \
tst-pathconf tst-getaddrinfo4
tst-pathconf tst-getaddrinfo4 bug-regex36 tst-fnmatch3
xtests := bug-ga2
ifeq (yes,$(build-shared))
test-srcs := globtest
@@ -110,7 +110,7 @@ generated := $(addprefix wordexp-test-result, 1 2 3 4 5 6 7 8 9 10) \
tst-pcre-mem tst-pcre.mtrace tst-boost-mem tst-boost.mtrace \
bug-ga2.mtrace bug-ga2-mem bug-glob2.mtrace bug-glob2-mem \
tst-vfork3-mem tst-vfork3.mtrace getconf.speclist \
tst-fnmatch-mem tst-fnmatch.mtrace
tst-fnmatch-mem tst-fnmatch.mtrace bug-regex36.mtrace
include ../Rules
@@ -260,6 +260,12 @@ bug-regex31-ENV = MALLOC_TRACE=$(objpfx)bug-regex31.mtrace
$(objpfx)bug-regex31-mem: $(objpfx)bug-regex31.out
$(common-objpfx)malloc/mtrace $(objpfx)bug-regex31.mtrace > $@
bug-regex36-ENV = MALLOC_TRACE=$(objpfx)bug-regex36.mtrace
$(objpfx)bug-regex36-mem.out: $(objpfx)bug-regex36.out
$(common-objpfx)malloc/mtrace $(objpfx)bug-regex36.mtrace > $@; \
$(evaluate-test)
tst-vfork3-ENV = MALLOC_TRACE=$(objpfx)tst-vfork3.mtrace
$(objpfx)tst-vfork3-mem: $(objpfx)tst-vfork3.out
+14 -2
View File
@@ -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;
@@ -1,4 +1,5 @@
/* Copyright (C) 2013 Free Software Foundation, Inc.
/* Test regcomp not leaking memory on parse errors
Copyright (C) 2014 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -15,5 +16,14 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
/* Build a non-versioned object for rtld-*. */
#include "getcontext-common.S"
#include <mcheck.h>
#include <regex.h>
int
main (int argc, char **argv)
{
regex_t r;
mtrace ();
regcomp (&r, "[a]\\|[a]\\{-2,}", 0);
regfree (&r);
}
+5 -13
View File
@@ -899,11 +899,8 @@ FCT (pattern, string, string_end, no_leading_period, flags, ends, alloca_used)
matched:
/* Skip the rest of the [...] that already matched. */
do
while ((c = *p++) != L (']'))
{
ignore_next:
c = *p++;
if (c == L('\0'))
/* [... (unterminated) loses. */
return FNM_NOMATCH;
@@ -931,12 +928,11 @@ FCT (pattern, string, string_end, no_leading_period, flags, ends, alloca_used)
if (c < L('a') || c >= L('z'))
{
p = startp;
goto ignore_next;
p = startp - 2;
break;
}
}
p += 2;
c = *p++;
}
else if (c == L('[') && *p == L('='))
{
@@ -947,25 +943,21 @@ FCT (pattern, string, string_end, no_leading_period, flags, ends, alloca_used)
if (c != L('=') || p[1] != L(']'))
return FNM_NOMATCH;
p += 2;
c = *p++;
}
else if (c == L('[') && *p == L('.'))
{
++p;
while (1)
{
c = *++p;
if (c == '\0')
if (c == L('\0'))
return FNM_NOMATCH;
if (*p == L('.') && p[1] == L(']'))
if (c == L('.') && p[1] == L(']'))
break;
}
p += 2;
c = *p++;
}
}
while (c != L(']'));
if (not)
return FNM_NOMATCH;
}
+125 -118
View File
@@ -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
@@ -1561,56 +1590,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 (__builtin_expect (flags & GLOB_ALTDIRFUNC, 0))
{
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)
{
@@ -1630,12 +1639,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;
}
}
+15 -4
View File
@@ -2154,7 +2154,11 @@ parse_reg_exp (re_string_t *regexp, regex_t *preg, re_token_t *token,
{
branch = parse_branch (regexp, preg, token, syntax, nest, err);
if (BE (*err != REG_NOERROR && branch == NULL, 0))
return NULL;
{
if (tree != NULL)
postorder (tree, free_tree, NULL);
return NULL;
}
}
else
branch = NULL;
@@ -2415,14 +2419,21 @@ parse_expression (re_string_t *regexp, regex_t *preg, re_token_t *token,
while (token->type == OP_DUP_ASTERISK || token->type == OP_DUP_PLUS
|| token->type == OP_DUP_QUESTION || token->type == OP_OPEN_DUP_NUM)
{
tree = parse_dup_op (tree, regexp, dfa, token, syntax, err);
if (BE (*err != REG_NOERROR && tree == NULL, 0))
return NULL;
bin_tree_t *dup_tree = parse_dup_op (tree, regexp, dfa, token, syntax, err);
if (BE (*err != REG_NOERROR && dup_tree == NULL, 0))
{
if (tree != NULL)
postorder (tree, free_tree, NULL);
return NULL;
}
tree = dup_tree;
/* In BRE consecutive duplications are not allowed. */
if ((syntax & RE_CONTEXT_INVALID_DUP)
&& (token->type == OP_DUP_ASTERISK
|| token->type == OP_OPEN_DUP_NUM))
{
if (tree != NULL)
postorder (tree, free_tree, NULL);
*err = REG_BADRPT;
return NULL;
}
+11 -3
View File
@@ -18,6 +18,7 @@
#include <errno.h>
#include <spawn.h>
#include <unistd.h>
#include <string.h>
#include "spawn_int.h"
@@ -35,17 +36,24 @@ posix_spawn_file_actions_addopen (posix_spawn_file_actions_t *file_actions,
if (fd < 0 || fd >= maxfd)
return EBADF;
char *path_copy = strdup (path);
if (path_copy == NULL)
return ENOMEM;
/* Allocate more memory if needed. */
if (file_actions->__used == file_actions->__allocated
&& __posix_spawn_file_actions_realloc (file_actions) != 0)
/* This can only mean we ran out of memory. */
return ENOMEM;
{
/* This can only mean we ran out of memory. */
free (path_copy);
return ENOMEM;
}
/* Add the new value. */
rec = &file_actions->__actions[file_actions->__used];
rec->tag = spawn_do_open;
rec->action.open_action.fd = fd;
rec->action.open_action.path = path;
rec->action.open_action.path = path_copy;
rec->action.open_action.oflag = oflag;
rec->action.open_action.mode = mode;
+20 -2
View File
@@ -18,11 +18,29 @@
#include <spawn.h>
#include <stdlib.h>
/* Initialize data structure for file attribute for `spawn' call. */
#include "spawn_int.h"
/* Deallocate the file actions. */
int
posix_spawn_file_actions_destroy (posix_spawn_file_actions_t *file_actions)
{
/* Free the memory allocated. */
/* Free the paths in the open actions. */
for (int i = 0; i < file_actions->__used; ++i)
{
struct __spawn_action *sa = &file_actions->__actions[i];
switch (sa->tag)
{
case spawn_do_open:
free (sa->action.open_action.path);
break;
case spawn_do_close:
case spawn_do_dup2:
/* No cleanup required. */
break;
}
}
/* Free the array of actions. */
free (file_actions->__actions);
return 0;
}
+1 -1
View File
@@ -22,7 +22,7 @@ struct __spawn_action
struct
{
int fd;
const char *path;
char *path;
int oflag;
mode_t mode;
} open_action;
@@ -1,5 +1,5 @@
/* Single-precision floating point square root.
Copyright (C) 1997-2014 Free Software Foundation, Inc.
/* Test for fnmatch not reading past the end of the pattern.
Copyright (C) 2014 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -16,15 +16,15 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#include <math.h>
#include <math_private.h>
#include <fnmatch.h>
#undef __ieee754_sqrtf
float
__ieee754_sqrtf (float x)
int
do_test (void)
{
double z;
__asm ("fsqrts %0,%1" : "=f" (z) : "f" (x));
return z;
const char *pattern = "[[:alpha:]'[:alpha:]\0]";
return fnmatch (pattern, "a", 0) != FNM_NOMATCH;
}
strong_alias (__ieee754_sqrtf, __sqrtf_finite)
#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"
+1 -1
View File
@@ -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;
+9 -1
View File
@@ -168,6 +168,7 @@ do_test (int argc, char *argv[])
char fd2name[18];
char fd3name[18];
char fd4name[18];
char *name3_copy;
char *spargv[12];
int i;
@@ -222,9 +223,15 @@ do_test (int argc, char *argv[])
if (posix_spawn_file_actions_addclose (&actions, fd1) != 0)
error (EXIT_FAILURE, errno, "posix_spawn_file_actions_addclose");
/* We want to open the third file. */
if (posix_spawn_file_actions_addopen (&actions, fd3, name3,
name3_copy = strdup (name3);
if (name3_copy == NULL)
error (EXIT_FAILURE, errno, "strdup");
if (posix_spawn_file_actions_addopen (&actions, fd3, name3_copy,
O_RDONLY, 0666) != 0)
error (EXIT_FAILURE, errno, "posix_spawn_file_actions_addopen");
/* Overwrite the name to check that a copy has been made. */
memset (name3_copy, 'X', strlen (name3_copy));
/* We dup the second descriptor. */
fd4 = MAX (2, MAX (fd1, MAX (fd2, fd3))) + 1;
if (posix_spawn_file_actions_adddup2 (&actions, fd2, fd4) != 0)
@@ -253,6 +260,7 @@ do_test (int argc, char *argv[])
/* Cleanup. */
if (posix_spawn_file_actions_destroy (&actions) != 0)
error (EXIT_FAILURE, errno, "posix_spawn_file_actions_destroy");
free (name3_copy);
/* Wait for the child. */
if (waitpid (pid, &status, 0) != pid)
+3 -3
View File
@@ -621,7 +621,7 @@ gethostbyname2(name, af)
buf.buf = origbuf = (querybuf *) alloca (1024);
if ((n = __libc_res_nsearch(&_res, name, C_IN, type, buf.buf->buf, 1024,
&buf.ptr, NULL, NULL, NULL)) < 0) {
&buf.ptr, NULL, NULL, NULL, NULL)) < 0) {
if (buf.buf != origbuf)
free (buf.buf);
Dprintf("res_nsearch failed (%d)\n", n);
@@ -716,12 +716,12 @@ gethostbyaddr(addr, len, af)
buf.buf = orig_buf = (querybuf *) alloca (1024);
n = __libc_res_nquery(&_res, qbuf, C_IN, T_PTR, buf.buf->buf, 1024,
&buf.ptr, NULL, NULL, NULL);
&buf.ptr, NULL, NULL, NULL, NULL);
if (n < 0 && af == AF_INET6 && (_res.options & RES_NOIP6DOTINT) == 0) {
strcpy(qp, "ip6.int");
n = __libc_res_nquery(&_res, qbuf, C_IN, T_PTR, buf.buf->buf,
buf.buf != orig_buf ? MAXPACKET : 1024,
&buf.ptr, NULL, NULL, NULL);
&buf.ptr, NULL, NULL, NULL, NULL);
}
if (n < 0) {
if (buf.buf != orig_buf)
+1 -1
View File
@@ -62,7 +62,7 @@ _nss_dns_getcanonname_r (const char *name, char *buffer, size_t buflen,
{
int r = __libc_res_nquery (&_res, name, ns_c_in, qtypes[i],
buf, sizeof (buf), &ansp.ptr, NULL, NULL,
NULL);
NULL, NULL);
if (r > 0)
{
/* We need to decode the response. Just one question record.
+128 -18
View File
@@ -190,7 +190,7 @@ _nss_dns_gethostbyname3_r (const char *name, int af, struct hostent *result,
host_buffer.buf = orig_host_buffer = (querybuf *) alloca (1024);
n = __libc_res_nsearch (&_res, name, C_IN, type, host_buffer.buf->buf,
1024, &host_buffer.ptr, NULL, NULL, NULL);
1024, &host_buffer.ptr, NULL, NULL, NULL, NULL);
if (n < 0)
{
switch (errno)
@@ -225,7 +225,7 @@ _nss_dns_gethostbyname3_r (const char *name, int af, struct hostent *result,
n = __libc_res_nsearch (&_res, name, C_IN, T_A, host_buffer.buf->buf,
host_buffer.buf != orig_host_buffer
? MAXPACKET : 1024, &host_buffer.ptr,
NULL, NULL, NULL);
NULL, NULL, NULL, NULL);
if (n < 0)
{
@@ -308,13 +308,20 @@ _nss_dns_gethostbyname4_r (const char *name, struct gaih_addrtuple **pat,
u_char *ans2p = NULL;
int nans2p = 0;
int resplen2 = 0;
int ans2p_malloced = 0;
int olderr = errno;
enum nss_status status;
int n = __libc_res_nsearch (&_res, name, C_IN, T_UNSPEC,
host_buffer.buf->buf, 2048, &host_buffer.ptr,
&ans2p, &nans2p, &resplen2);
if (n < 0)
&ans2p, &nans2p, &resplen2, &ans2p_malloced);
if (n >= 0)
{
status = gaih_getanswer (host_buffer.buf, n, (const querybuf *) ans2p,
resplen2, name, pat, buffer, buflen,
errnop, herrnop, ttlp);
}
else
{
switch (errno)
{
@@ -341,16 +348,11 @@ _nss_dns_gethostbyname4_r (const char *name, struct gaih_addrtuple **pat,
*errnop = EAGAIN;
else
__set_errno (olderr);
if (host_buffer.buf != orig_host_buffer)
free (host_buffer.buf);
return status;
}
status = gaih_getanswer(host_buffer.buf, n, (const querybuf *) ans2p,
resplen2, name, pat, buffer, buflen,
errnop, herrnop, ttlp);
/* Check whether ans2p was separately allocated. */
if (ans2p_malloced)
free (ans2p);
if (host_buffer.buf != orig_host_buffer)
free (host_buffer.buf);
@@ -460,7 +462,7 @@ _nss_dns_gethostbyaddr2_r (const void *addr, socklen_t len, int af,
strcpy (qp, "].ip6.arpa");
n = __libc_res_nquery (&_res, qbuf, C_IN, T_PTR,
host_buffer.buf->buf, 1024, &host_buffer.ptr,
NULL, NULL, NULL);
NULL, NULL, NULL, NULL);
if (n >= 0)
goto got_it_already;
}
@@ -481,14 +483,14 @@ _nss_dns_gethostbyaddr2_r (const void *addr, socklen_t len, int af,
}
n = __libc_res_nquery (&_res, qbuf, C_IN, T_PTR, host_buffer.buf->buf,
1024, &host_buffer.ptr, NULL, NULL, NULL);
1024, &host_buffer.ptr, NULL, NULL, NULL, NULL);
if (n < 0 && af == AF_INET6 && (_res.options & RES_NOIP6DOTINT) == 0)
{
strcpy (qp, "ip6.int");
n = __libc_res_nquery (&_res, qbuf, C_IN, T_PTR, host_buffer.buf->buf,
host_buffer.buf != orig_host_buffer
? MAXPACKET : 1024, &host_buffer.ptr,
NULL, NULL, NULL);
NULL, NULL, NULL, NULL);
}
if (n < 0)
{
@@ -613,7 +615,8 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype,
int have_to_map = 0;
uintptr_t pad = -(uintptr_t) buffer % __alignof__ (struct host_data);
buffer += pad;
if (__builtin_expect (buflen < sizeof (struct host_data) + pad, 0))
buflen = buflen > pad ? buflen - pad : 0;
if (__builtin_expect (buflen < sizeof (struct host_data), 0))
{
/* The buffer is too small. */
too_small:
@@ -1049,7 +1052,10 @@ gaih_getanswer_slice (const querybuf *answer, int anslen, const char *qname,
int h_namelen = 0;
if (ancount == 0)
return NSS_STATUS_NOTFOUND;
{
*h_errnop = HOST_NOT_FOUND;
return NSS_STATUS_NOTFOUND;
}
while (ancount-- > 0 && cp < end_of_message && had_error == 0)
{
@@ -1226,7 +1232,14 @@ gaih_getanswer_slice (const querybuf *answer, int anslen, const char *qname,
/* Special case here: if the resolver sent a result but it only
contains a CNAME while we are looking for a T_A or T_AAAA record,
we fail with NOTFOUND instead of TRYAGAIN. */
return canon == NULL ? NSS_STATUS_TRYAGAIN : NSS_STATUS_NOTFOUND;
if (canon != NULL)
{
*h_errnop = HOST_NOT_FOUND;
return NSS_STATUS_NOTFOUND;
}
*h_errnop = NETDB_INTERNAL;
return NSS_STATUS_TRYAGAIN;
}
@@ -1240,11 +1253,101 @@ gaih_getanswer (const querybuf *answer1, int anslen1, const querybuf *answer2,
enum nss_status status = NSS_STATUS_NOTFOUND;
/* Combining the NSS status of two distinct queries requires some
compromise and attention to symmetry (A or AAAA queries can be
returned in any order). What follows is a breakdown of how this
code is expected to work and why. We discuss only SUCCESS,
TRYAGAIN, NOTFOUND and UNAVAIL, since they are the only returns
that apply (though RETURN and MERGE exist). We make a distinction
between TRYAGAIN (recoverable) and TRYAGAIN' (not-recoverable).
A recoverable TRYAGAIN is almost always due to buffer size issues
and returns ERANGE in errno and the caller is expected to retry
with a larger buffer.
Lastly, you may be tempted to make significant changes to the
conditions in this code to bring about symmetry between responses.
Please don't change anything without due consideration for
expected application behaviour. Some of the synthesized responses
aren't very well thought out and sometimes appear to imply that
IPv4 responses are always answer 1, and IPv6 responses are always
answer 2, but that's not true (see the implementation of send_dg
and send_vc to see response can arrive in any order, particularly
for UDP). However, we expect it holds roughly enough of the time
that this code works, but certainly needs to be fixed to make this
a more robust implementation.
----------------------------------------------
| Answer 1 Status / | Synthesized | Reason |
| Answer 2 Status | Status | |
|--------------------------------------------|
| SUCCESS/SUCCESS | SUCCESS | [1] |
| SUCCESS/TRYAGAIN | TRYAGAIN | [5] |
| SUCCESS/TRYAGAIN' | SUCCESS | [1] |
| SUCCESS/NOTFOUND | SUCCESS | [1] |
| SUCCESS/UNAVAIL | SUCCESS | [1] |
| TRYAGAIN/SUCCESS | TRYAGAIN | [2] |
| TRYAGAIN/TRYAGAIN | TRYAGAIN | [2] |
| TRYAGAIN/TRYAGAIN' | TRYAGAIN | [2] |
| TRYAGAIN/NOTFOUND | TRYAGAIN | [2] |
| TRYAGAIN/UNAVAIL | TRYAGAIN | [2] |
| TRYAGAIN'/SUCCESS | SUCCESS | [3] |
| TRYAGAIN'/TRYAGAIN | TRYAGAIN | [3] |
| TRYAGAIN'/TRYAGAIN' | TRYAGAIN' | [3] |
| TRYAGAIN'/NOTFOUND | TRYAGAIN' | [3] |
| TRYAGAIN'/UNAVAIL | UNAVAIL | [3] |
| NOTFOUND/SUCCESS | SUCCESS | [3] |
| NOTFOUND/TRYAGAIN | TRYAGAIN | [3] |
| NOTFOUND/TRYAGAIN' | TRYAGAIN' | [3] |
| NOTFOUND/NOTFOUND | NOTFOUND | [3] |
| NOTFOUND/UNAVAIL | UNAVAIL | [3] |
| UNAVAIL/SUCCESS | UNAVAIL | [4] |
| UNAVAIL/TRYAGAIN | UNAVAIL | [4] |
| UNAVAIL/TRYAGAIN' | UNAVAIL | [4] |
| UNAVAIL/NOTFOUND | UNAVAIL | [4] |
| UNAVAIL/UNAVAIL | UNAVAIL | [4] |
----------------------------------------------
[1] If the first response is a success we return success.
This ignores the state of the second answer and in fact
incorrectly sets errno and h_errno to that of the second
answer. However because the response is a success we ignore
*errnop and *h_errnop (though that means you touched errno on
success). We are being conservative here and returning the
likely IPv4 response in the first answer as a success.
[2] If the first response is a recoverable TRYAGAIN we return
that instead of looking at the second response. The
expectation here is that we have failed to get an IPv4 response
and should retry both queries.
[3] If the first response was not a SUCCESS and the second
response is not NOTFOUND (had a SUCCESS, need to TRYAGAIN,
or failed entirely e.g. TRYAGAIN' and UNAVAIL) then use the
result from the second response, otherwise the first responses
status is used. Again we have some odd side-effects when the
second response is NOTFOUND because we overwrite *errnop and
*h_errnop that means that a first answer of NOTFOUND might see
its *errnop and *h_errnop values altered. Whether it matters
in practice that a first response NOTFOUND has the wrong
*errnop and *h_errnop is undecided.
[4] If the first response is UNAVAIL we return that instead of
looking at the second response. The expectation here is that
it will have failed similarly e.g. configuration failure.
[5] Testing this code is complicated by the fact that truncated
second response buffers might be returned as SUCCESS if the
first answer is a SUCCESS. To fix this we add symmetry to
TRYAGAIN with the second response. If the second response
is a recoverable error we now return TRYAGIN even if the first
response was SUCCESS. */
if (anslen1 > 0)
status = gaih_getanswer_slice(answer1, anslen1, qname,
&pat, &buffer, &buflen,
errnop, h_errnop, ttlp,
&first);
if ((status == NSS_STATUS_SUCCESS || status == NSS_STATUS_NOTFOUND
|| (status == NSS_STATUS_TRYAGAIN
/* We want to look at the second answer in case of an
@@ -1260,8 +1363,15 @@ gaih_getanswer (const querybuf *answer1, int anslen1, const querybuf *answer2,
&pat, &buffer, &buflen,
errnop, h_errnop, ttlp,
&first);
/* Use the second response status in some cases. */
if (status != NSS_STATUS_SUCCESS && status2 != NSS_STATUS_NOTFOUND)
status = status2;
/* Do not return a truncated second response (unless it was
unavoidable e.g. unrecoverable TRYAGAIN). */
if (status == NSS_STATUS_SUCCESS
&& (status2 == NSS_STATUS_TRYAGAIN
&& *errnop == ERANGE && *h_errnop != NO_RECOVERY))
status = NSS_STATUS_TRYAGAIN;
}
return status;
+3 -6
View File
@@ -118,18 +118,15 @@ _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,
1024, &net_buffer.ptr, NULL, NULL, NULL);
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)
{
/* Nothing found. */
@@ -205,7 +202,7 @@ _nss_dns_getnetbyaddr_r (uint32_t net, int type, struct netent *result,
net_buffer.buf = orig_net_buffer = (querybuf *) alloca (1024);
anslen = __libc_res_nquery (&_res, qbuf, C_IN, T_PTR, net_buffer.buf->buf,
1024, &net_buffer.ptr, NULL, NULL, NULL);
1024, &net_buffer.ptr, NULL, NULL, NULL, NULL);
if (anslen < 0)
{
/* Nothing found. */
+29 -19
View File
@@ -98,7 +98,7 @@ static int
__libc_res_nquerydomain(res_state statp, const char *name, const char *domain,
int class, int type, u_char *answer, int anslen,
u_char **answerp, u_char **answerp2, int *nanswerp2,
int *resplen2);
int *resplen2, int *answerp2_malloced);
/*
* Formulate a normal query, send, and await answer.
@@ -119,7 +119,8 @@ __libc_res_nquery(res_state statp,
u_char **answerp, /* if buffer needs to be enlarged */
u_char **answerp2,
int *nanswerp2,
int *resplen2)
int *resplen2,
int *answerp2_malloced)
{
HEADER *hp = (HEADER *) answer;
HEADER *hp2;
@@ -224,7 +225,8 @@ __libc_res_nquery(res_state statp,
}
assert (answerp == NULL || (void *) *answerp == (void *) answer);
n = __libc_res_nsend(statp, query1, nquery1, query2, nquery2, answer,
anslen, answerp, answerp2, nanswerp2, resplen2);
anslen, answerp, answerp2, nanswerp2, resplen2,
answerp2_malloced);
if (use_malloc)
free (buf);
if (n < 0) {
@@ -316,7 +318,7 @@ res_nquery(res_state statp,
int anslen) /* size of answer buffer */
{
return __libc_res_nquery(statp, name, class, type, answer, anslen,
NULL, NULL, NULL, NULL);
NULL, NULL, NULL, NULL, NULL);
}
libresolv_hidden_def (res_nquery)
@@ -335,7 +337,8 @@ __libc_res_nsearch(res_state statp,
u_char **answerp,
u_char **answerp2,
int *nanswerp2,
int *resplen2)
int *resplen2,
int *answerp2_malloced)
{
const char *cp, * const *domain;
HEADER *hp = (HEADER *) answer;
@@ -360,7 +363,7 @@ __libc_res_nsearch(res_state statp,
if (!dots && (cp = res_hostalias(statp, name, tmp, sizeof tmp))!= NULL)
return (__libc_res_nquery(statp, cp, class, type, answer,
anslen, answerp, answerp2,
nanswerp2, resplen2));
nanswerp2, resplen2, answerp2_malloced));
#ifdef DEBUG
if (statp->options & RES_DEBUG)
@@ -377,7 +380,8 @@ __libc_res_nsearch(res_state statp,
if (dots >= statp->ndots || trailing_dot) {
ret = __libc_res_nquerydomain(statp, name, NULL, class, type,
answer, anslen, answerp,
answerp2, nanswerp2, resplen2);
answerp2, nanswerp2, resplen2,
answerp2_malloced);
if (ret > 0 || trailing_dot)
return (ret);
saved_herrno = h_errno;
@@ -386,11 +390,12 @@ __libc_res_nsearch(res_state statp,
answer = *answerp;
anslen = MAXPACKET;
}
if (answerp2
&& (*answerp2 < answer || *answerp2 >= answer + anslen))
if (answerp2 && *answerp2_malloced)
{
free (*answerp2);
*answerp2 = NULL;
*nanswerp2 = 0;
*answerp2_malloced = 0;
}
}
@@ -417,7 +422,7 @@ __libc_res_nsearch(res_state statp,
class, type,
answer, anslen, answerp,
answerp2, nanswerp2,
resplen2);
resplen2, answerp2_malloced);
if (ret > 0)
return (ret);
@@ -425,12 +430,12 @@ __libc_res_nsearch(res_state statp,
answer = *answerp;
anslen = MAXPACKET;
}
if (answerp2
&& (*answerp2 < answer
|| *answerp2 >= answer + anslen))
if (answerp2 && *answerp2_malloced)
{
free (*answerp2);
*answerp2 = NULL;
*nanswerp2 = 0;
*answerp2_malloced = 0;
}
/*
@@ -486,7 +491,8 @@ __libc_res_nsearch(res_state statp,
&& !(tried_as_is || root_on_list)) {
ret = __libc_res_nquerydomain(statp, name, NULL, class, type,
answer, anslen, answerp,
answerp2, nanswerp2, resplen2);
answerp2, nanswerp2, resplen2,
answerp2_malloced);
if (ret > 0)
return (ret);
}
@@ -498,10 +504,12 @@ __libc_res_nsearch(res_state statp,
* else send back meaningless H_ERRNO, that being the one from
* the last DNSRCH we did.
*/
if (answerp2 && (*answerp2 < answer || *answerp2 >= answer + anslen))
if (answerp2 && *answerp2_malloced)
{
free (*answerp2);
*answerp2 = NULL;
*nanswerp2 = 0;
*answerp2_malloced = 0;
}
if (saved_herrno != -1)
RES_SET_H_ERRNO(statp, saved_herrno);
@@ -521,7 +529,7 @@ res_nsearch(res_state statp,
int anslen) /* size of answer */
{
return __libc_res_nsearch(statp, name, class, type, answer,
anslen, NULL, NULL, NULL, NULL);
anslen, NULL, NULL, NULL, NULL, NULL);
}
libresolv_hidden_def (res_nsearch)
@@ -539,7 +547,8 @@ __libc_res_nquerydomain(res_state statp,
u_char **answerp,
u_char **answerp2,
int *nanswerp2,
int *resplen2)
int *resplen2,
int *answerp2_malloced)
{
char nbuf[MAXDNAME];
const char *longname = nbuf;
@@ -581,7 +590,7 @@ __libc_res_nquerydomain(res_state statp,
}
return (__libc_res_nquery(statp, longname, class, type, answer,
anslen, answerp, answerp2, nanswerp2,
resplen2));
resplen2, answerp2_malloced));
}
int
@@ -593,7 +602,8 @@ res_nquerydomain(res_state statp,
int anslen) /* size of answer */
{
return __libc_res_nquerydomain(statp, name, domain, class, type,
answer, anslen, NULL, NULL, NULL, NULL);
answer, anslen, NULL, NULL, NULL, NULL,
NULL);
}
libresolv_hidden_def (res_nquerydomain)
+251 -91
View File
@@ -1,3 +1,20 @@
/* Copyright (C) 2016 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
/*
* Copyright (c) 1985, 1989, 1993
* The Regents of the University of California. All rights reserved.
@@ -186,12 +203,12 @@ evNowTime(struct timespec *res) {
static int send_vc(res_state, const u_char *, int,
const u_char *, int,
u_char **, int *, int *, int, u_char **,
u_char **, int *, int *);
u_char **, int *, int *, int *);
static int send_dg(res_state, const u_char *, int,
const u_char *, int,
u_char **, int *, int *, int,
int *, int *, u_char **,
u_char **, int *, int *);
u_char **, int *, int *, int *);
#ifdef DEBUG
static void Aerror(const res_state, FILE *, const char *, int,
const struct sockaddr *);
@@ -343,7 +360,7 @@ int
__libc_res_nsend(res_state statp, const u_char *buf, int buflen,
const u_char *buf2, int buflen2,
u_char *ans, int anssiz, u_char **ansp, u_char **ansp2,
int *nansp2, int *resplen2)
int *nansp2, int *resplen2, int *ansp2_malloced)
{
int gotsomewhere, terrno, try, v_circuit, resplen, ns, n;
@@ -360,6 +377,8 @@ __libc_res_nsend(res_state statp, const u_char *buf, int buflen,
#ifdef USE_HOOKS
if (__builtin_expect (statp->qhook || statp->rhook, 0)) {
if (anssiz < MAXPACKET && ansp) {
/* Always allocate MAXPACKET, callers expect
this specific size. */
u_char *buf = malloc (MAXPACKET);
if (buf == NULL)
return (-1);
@@ -546,7 +565,8 @@ __libc_res_nsend(res_state statp, const u_char *buf, int buflen,
try = statp->retry;
n = send_vc(statp, buf, buflen, buf2, buflen2,
&ans, &anssiz, &terrno,
ns, ansp, ansp2, nansp2, resplen2);
ns, ansp, ansp2, nansp2, resplen2,
ansp2_malloced);
if (n < 0)
return (-1);
if (n == 0 && (buf2 == NULL || *resplen2 == 0))
@@ -556,7 +576,7 @@ __libc_res_nsend(res_state statp, const u_char *buf, int buflen,
n = send_dg(statp, buf, buflen, buf2, buflen2,
&ans, &anssiz, &terrno,
ns, &v_circuit, &gotsomewhere, ansp,
ansp2, nansp2, resplen2);
ansp2, nansp2, resplen2, ansp2_malloced);
if (n < 0)
return (-1);
if (n == 0 && (buf2 == NULL || *resplen2 == 0))
@@ -646,26 +666,105 @@ res_nsend(res_state statp,
const u_char *buf, int buflen, u_char *ans, int anssiz)
{
return __libc_res_nsend(statp, buf, buflen, NULL, 0, ans, anssiz,
NULL, NULL, NULL, NULL);
NULL, NULL, NULL, NULL, NULL);
}
libresolv_hidden_def (res_nsend)
/* Private */
/* Close the resolver structure, assign zero to *RESPLEN2 if RESPLEN2
is not NULL, and return zero. */
static int
__attribute__ ((warn_unused_result))
close_and_return_error (res_state statp, int *resplen2)
{
__res_iclose(statp, false);
if (resplen2 != NULL)
*resplen2 = 0;
return 0;
}
/* The send_vc function is responsible for sending a DNS query over TCP
to the nameserver numbered NS from the res_state STATP i.e.
EXT(statp).nssocks[ns]. The function supports sending both IPv4 and
IPv6 queries at the same serially on the same socket.
Please note that for TCP there is no way to disable sending both
queries, unlike UDP, which honours RES_SNGLKUP and RES_SNGLKUPREOP
and sends the queries serially and waits for the result after each
sent query. This implemetnation should be corrected to honour these
options.
Please also note that for TCP we send both queries over the same
socket one after another. This technically violates best practice
since the server is allowed to read the first query, respond, and
then close the socket (to service another client). If the server
does this, then the remaining second query in the socket data buffer
will cause the server to send the client an RST which will arrive
asynchronously and the client's OS will likely tear down the socket
receive buffer resulting in a potentially short read and lost
response data. This will force the client to retry the query again,
and this process may repeat until all servers and connection resets
are exhausted and then the query will fail. It's not known if this
happens with any frequency in real DNS server implementations. This
implementation should be corrected to use two sockets by default for
parallel queries.
The query stored in BUF of BUFLEN length is sent first followed by
the query stored in BUF2 of BUFLEN2 length. Queries are sent
serially on the same socket.
Answers to the query are stored firstly in *ANSP up to a max of
*ANSSIZP bytes. If more than *ANSSIZP bytes are needed and ANSCP
is non-NULL (to indicate that modifying the answer buffer is allowed)
then malloc is used to allocate a new response buffer and ANSCP and
ANSP will both point to the new buffer. If more than *ANSSIZP bytes
are needed but ANSCP is NULL, then as much of the response as
possible is read into the buffer, but the results will be truncated.
When truncation happens because of a small answer buffer the DNS
packets header feild TC will bet set to 1, indicating a truncated
message and the rest of the socket data will be read and discarded.
Answers to the query are stored secondly in *ANSP2 up to a max of
*ANSSIZP2 bytes, with the actual response length stored in
*RESPLEN2. If more than *ANSSIZP bytes are needed and ANSP2
is non-NULL (required for a second query) then malloc is used to
allocate a new response buffer, *ANSSIZP2 is set to the new buffer
size and *ANSP2_MALLOCED is set to 1.
The ANSP2_MALLOCED argument will eventually be removed as the
change in buffer pointer can be used to detect the buffer has
changed and that the caller should use free on the new buffer.
Note that the answers may arrive in any order from the server and
therefore the first and second answer buffers may not correspond to
the first and second queries.
It is not supported to call this function with a non-NULL ANSP2
but a NULL ANSCP. Put another way, you can call send_vc with a
single unmodifiable buffer or two modifiable buffers, but no other
combination is supported.
It is the caller's responsibility to free the malloc allocated
buffers by detecting that the pointers have changed from their
original values i.e. *ANSCP or *ANSP2 has changed.
If errors are encountered then *TERRNO is set to an appropriate
errno value and a zero result is returned for a recoverable error,
and a less-than zero result is returned for a non-recoverable error.
If no errors are encountered then *TERRNO is left unmodified and
a the length of the first response in bytes is returned. */
static int
send_vc(res_state statp,
const u_char *buf, int buflen, const u_char *buf2, int buflen2,
u_char **ansp, int *anssizp,
int *terrno, int ns, u_char **anscp, u_char **ansp2, int *anssizp2,
int *resplen2)
int *resplen2, int *ansp2_malloced)
{
const HEADER *hp = (HEADER *) buf;
const HEADER *hp2 = (HEADER *) buf2;
u_char *ans = *ansp;
int orig_anssizp = *anssizp;
// XXX REMOVE
// int anssiz = *anssizp;
HEADER *anhp = (HEADER *) ans;
HEADER *anhp = (HEADER *) *ansp;
struct sockaddr_in6 *nsap = EXT(statp).nsaddrs[ns];
int truncating, connreset, resplen, n;
struct iovec iov[4];
@@ -741,6 +840,8 @@ send_vc(res_state statp,
* Receive length & response
*/
int recvresp1 = 0;
/* Skip the second response if there is no second query.
To do that we mark the second response as received. */
int recvresp2 = buf2 == NULL;
uint16_t rlen16;
read_len:
@@ -777,33 +878,14 @@ send_vc(res_state statp,
u_char **thisansp;
int *thisresplenp;
if ((recvresp1 | recvresp2) == 0 || buf2 == NULL) {
/* We have not received any responses
yet or we only have one response to
receive. */
thisanssizp = anssizp;
thisansp = anscp ?: ansp;
assert (anscp != NULL || ansp2 == NULL);
thisresplenp = &resplen;
} else {
if (*anssizp != MAXPACKET) {
/* No buffer allocated for the first
reply. We can try to use the rest
of the user-provided buffer. */
#ifdef _STRING_ARCH_unaligned
*anssizp2 = orig_anssizp - resplen;
*ansp2 = *ansp + resplen;
#else
int aligned_resplen
= ((resplen + __alignof__ (HEADER) - 1)
& ~(__alignof__ (HEADER) - 1));
*anssizp2 = orig_anssizp - aligned_resplen;
*ansp2 = *ansp + aligned_resplen;
#endif
} else {
/* The first reply did not fit into the
user-provided buffer. Maybe the second
answer will. */
*anssizp2 = orig_anssizp;
*ansp2 = *ansp;
}
thisanssizp = anssizp2;
thisansp = ansp2;
thisresplenp = resplen2;
@@ -811,10 +893,14 @@ send_vc(res_state statp,
anhp = (HEADER *) *thisansp;
*thisresplenp = rlen;
if (rlen > *thisanssizp) {
/* Yes, we test ANSCP here. If we have two buffers
both will be allocatable. */
if (__builtin_expect (anscp != NULL, 1)) {
/* Is the answer buffer too small? */
if (*thisanssizp < rlen) {
/* If the current buffer is non-NULL and it's not
pointing at the static user-supplied buffer then
we can reallocate it. */
if (thisansp != NULL && thisansp != ansp) {
/* Always allocate MAXPACKET, callers expect
this specific size. */
u_char *newp = malloc (MAXPACKET);
if (newp == NULL) {
*terrno = ENOMEM;
@@ -823,7 +909,12 @@ send_vc(res_state statp,
}
*thisanssizp = MAXPACKET;
*thisansp = newp;
if (thisansp == ansp2)
*ansp2_malloced = 1;
anhp = (HEADER *) newp;
/* A uint16_t can't be larger than MAXPACKET
thus it's safe to allocate MAXPACKET but
read RLEN bytes instead. */
len = rlen;
} else {
Dprint(statp->options & RES_DEBUG,
@@ -987,17 +1078,75 @@ reopen (res_state statp, int *terrno, int ns)
return 1;
}
/* The send_dg function is responsible for sending a DNS query over UDP
to the nameserver numbered NS from the res_state STATP i.e.
EXT(statp).nssocks[ns]. The function supports IPv4 and IPv6 queries
along with the ability to send the query in parallel for both stacks
(default) or serially (RES_SINGLKUP). It also supports serial lookup
with a close and reopen of the socket used to talk to the server
(RES_SNGLKUPREOP) to work around broken name servers.
The query stored in BUF of BUFLEN length is sent first followed by
the query stored in BUF2 of BUFLEN2 length. Queries are sent
in parallel (default) or serially (RES_SINGLKUP or RES_SNGLKUPREOP).
Answers to the query are stored firstly in *ANSP up to a max of
*ANSSIZP bytes. If more than *ANSSIZP bytes are needed and ANSCP
is non-NULL (to indicate that modifying the answer buffer is allowed)
then malloc is used to allocate a new response buffer and ANSCP and
ANSP will both point to the new buffer. If more than *ANSSIZP bytes
are needed but ANSCP is NULL, then as much of the response as
possible is read into the buffer, but the results will be truncated.
When truncation happens because of a small answer buffer the DNS
packets header feild TC will bet set to 1, indicating a truncated
message, while the rest of the UDP packet is discarded.
Answers to the query are stored secondly in *ANSP2 up to a max of
*ANSSIZP2 bytes, with the actual response length stored in
*RESPLEN2. If more than *ANSSIZP bytes are needed and ANSP2
is non-NULL (required for a second query) then malloc is used to
allocate a new response buffer, *ANSSIZP2 is set to the new buffer
size and *ANSP2_MALLOCED is set to 1.
The ANSP2_MALLOCED argument will eventually be removed as the
change in buffer pointer can be used to detect the buffer has
changed and that the caller should use free on the new buffer.
Note that the answers may arrive in any order from the server and
therefore the first and second answer buffers may not correspond to
the first and second queries.
It is not supported to call this function with a non-NULL ANSP2
but a NULL ANSCP. Put another way, you can call send_vc with a
single unmodifiable buffer or two modifiable buffers, but no other
combination is supported.
It is the caller's responsibility to free the malloc allocated
buffers by detecting that the pointers have changed from their
original values i.e. *ANSCP or *ANSP2 has changed.
If an answer is truncated because of UDP datagram DNS limits then
*V_CIRCUIT is set to 1 and the return value non-zero to indicate to
the caller to retry with TCP. The value *GOTSOMEWHERE is set to 1
if any progress was made reading a response from the nameserver and
is used by the caller to distinguish between ECONNREFUSED and
ETIMEDOUT (the latter if *GOTSOMEWHERE is 1).
If errors are encountered then *TERRNO is set to an appropriate
errno value and a zero result is returned for a recoverable error,
and a less-than zero result is returned for a non-recoverable error.
If no errors are encountered then *TERRNO is left unmodified and
a the length of the first response in bytes is returned. */
static int
send_dg(res_state statp,
const u_char *buf, int buflen, const u_char *buf2, int buflen2,
u_char **ansp, int *anssizp,
int *terrno, int ns, int *v_circuit, int *gotsomewhere, u_char **anscp,
u_char **ansp2, int *anssizp2, int *resplen2)
u_char **ansp2, int *anssizp2, int *resplen2, int *ansp2_malloced)
{
const HEADER *hp = (HEADER *) buf;
const HEADER *hp2 = (HEADER *) buf2;
u_char *ans = *ansp;
int orig_anssizp = *anssizp;
struct timespec now, timeout, finish;
struct pollfd pfd[1];
int ptimeout;
@@ -1022,7 +1171,11 @@ send_dg(res_state statp,
retry_reopen:
retval = reopen (statp, terrno, ns);
if (retval <= 0)
return retval;
{
if (resplen2 != NULL)
*resplen2 = 0;
return retval;
}
retry:
evNowTime(&now);
evConsTime(&timeout, seconds, 0);
@@ -1030,11 +1183,11 @@ send_dg(res_state statp,
int need_recompute = 0;
int nwritten = 0;
int recvresp1 = 0;
/* Skip the second response if there is no second query.
To do that we mark the second response as received. */
int recvresp2 = buf2 == NULL;
pfd[0].fd = EXT(statp).nssocks[ns];
pfd[0].events = POLLOUT;
if (resplen2 != NULL)
*resplen2 = 0;
wait:
if (need_recompute) {
recompute_resend:
@@ -1042,9 +1195,7 @@ send_dg(res_state statp,
if (evCmpTime(finish, now) <= 0) {
poll_err_out:
Perror(statp, stderr, "poll", errno);
err_out:
__res_iclose(statp, false);
return (0);
return close_and_return_error (statp, resplen2);
}
evSubTime(&timeout, &finish, &now);
need_recompute = 0;
@@ -1091,7 +1242,9 @@ send_dg(res_state statp,
}
*gotsomewhere = 1;
return (0);
if (resplen2 != NULL)
*resplen2 = 0;
return 0;
}
if (n < 0) {
if (errno == EINTR)
@@ -1159,7 +1312,7 @@ send_dg(res_state statp,
fail_sendmmsg:
Perror(statp, stderr, "sendmmsg", errno);
goto err_out;
return close_and_return_error (statp, resplen2);
}
}
else
@@ -1177,7 +1330,7 @@ send_dg(res_state statp,
if (errno == EINTR || errno == EAGAIN)
goto recompute_resend;
Perror(statp, stderr, "send", errno);
goto err_out;
return close_and_return_error (statp, resplen2);
}
just_one:
if (nwritten != 0 || buf2 == NULL || single_request)
@@ -1193,53 +1346,56 @@ send_dg(res_state statp,
int *thisresplenp;
if ((recvresp1 | recvresp2) == 0 || buf2 == NULL) {
/* We have not received any responses
yet or we only have one response to
receive. */
thisanssizp = anssizp;
thisansp = anscp ?: ansp;
assert (anscp != NULL || ansp2 == NULL);
thisresplenp = &resplen;
} else {
if (*anssizp != MAXPACKET) {
/* No buffer allocated for the first
reply. We can try to use the rest
of the user-provided buffer. */
#ifdef _STRING_ARCH_unaligned
*anssizp2 = orig_anssizp - resplen;
*ansp2 = *ansp + resplen;
#else
int aligned_resplen
= ((resplen + __alignof__ (HEADER) - 1)
& ~(__alignof__ (HEADER) - 1));
*anssizp2 = orig_anssizp - aligned_resplen;
*ansp2 = *ansp + aligned_resplen;
#endif
} else {
/* The first reply did not fit into the
user-provided buffer. Maybe the second
answer will. */
*anssizp2 = orig_anssizp;
*ansp2 = *ansp;
}
thisanssizp = anssizp2;
thisansp = ansp2;
thisresplenp = resplen2;
}
if (*thisanssizp < MAXPACKET
/* Yes, we test ANSCP here. If we have two buffers
both will be allocatable. */
&& anscp
/* If the current buffer is non-NULL and it's not
pointing at the static user-supplied buffer then
we can reallocate it. */
&& (thisansp != NULL && thisansp != ansp)
#ifdef FIONREAD
/* Is the size too small? */
&& (ioctl (pfd[0].fd, FIONREAD, thisresplenp) < 0
|| *thisanssizp < *thisresplenp)
#endif
) {
/* Always allocate MAXPACKET, callers expect
this specific size. */
u_char *newp = malloc (MAXPACKET);
if (newp != NULL) {
*anssizp = MAXPACKET;
*thisansp = ans = newp;
*thisanssizp = MAXPACKET;
*thisansp = newp;
if (thisansp == ansp2)
*ansp2_malloced = 1;
}
}
/* We could end up with truncation if anscp was NULL
(not allowed to change caller's buffer) and the
response buffer size is too small. This isn't a
reliable way to detect truncation because the ioctl
may be an inaccurate report of the UDP message size.
Therefore we use this only to issue debug output.
To do truncation accurately with UDP we need
MSG_TRUNC which is only available on Linux. We
can abstract out the Linux-specific feature in the
future to detect truncation. */
if (__glibc_unlikely (*thisanssizp < *thisresplenp)) {
Dprint(statp->options & RES_DEBUG,
(stdout, ";; response may be truncated (UDP)\n")
);
}
HEADER *anhp = (HEADER *) *thisansp;
socklen_t fromlen = sizeof(struct sockaddr_in6);
assert (sizeof(from) <= fromlen);
@@ -1252,7 +1408,7 @@ send_dg(res_state statp,
goto wait;
}
Perror(statp, stderr, "recvfrom", errno);
goto err_out;
return close_and_return_error (statp, resplen2);
}
*gotsomewhere = 1;
if (__builtin_expect (*thisresplenp < HFIXEDSZ, 0)) {
@@ -1263,7 +1419,7 @@ send_dg(res_state statp,
(stdout, ";; undersized: %d\n",
*thisresplenp));
*terrno = EMSGSIZE;
goto err_out;
return close_and_return_error (statp, resplen2);
}
if ((recvresp1 || hp->id != anhp->id)
&& (recvresp2 || hp2->id != anhp->id)) {
@@ -1312,7 +1468,7 @@ send_dg(res_state statp,
? *thisanssizp : *thisresplenp);
/* record the error */
statp->_flags |= RES_F_EDNS0ERR;
goto err_out;
return close_and_return_error (statp, resplen2);
}
#endif
if (!(statp->options & RES_INSECURE2)
@@ -1364,10 +1520,10 @@ send_dg(res_state statp,
}
next_ns:
__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) {
@@ -1389,6 +1545,8 @@ send_dg(res_state statp,
__res_iclose(statp, false);
// XXX if we have received one reply we could
// XXX use it and not repeat it over TCP...
if (resplen2 != NULL)
*resplen2 = 0;
return (1);
}
/* Mark which reply we received. */
@@ -1404,20 +1562,22 @@ send_dg(res_state statp,
__res_iclose (statp, false);
retval = reopen (statp, terrno, ns);
if (retval <= 0)
return retval;
{
if (resplen2 != NULL)
*resplen2 = 0;
return retval;
}
pfd[0].fd = EXT(statp).nssocks[ns];
}
}
goto wait;
}
/*
* All is well, or the error is fatal. Signal that the
* next nameserver ought not be tried.
*/
/* All is well. We have received both responses (if
two responses were requested). */
return (resplen);
} else if (pfd[0].revents & (POLLERR | POLLHUP | POLLNVAL)) {
/* Something went wrong. We can stop trying. */
goto err_out;
}
} else if (pfd[0].revents & (POLLERR | POLLHUP | POLLNVAL))
/* Something went wrong. We can stop trying. */
return close_and_return_error (statp, resplen2);
else {
/* poll should not have returned > 0 in this case. */
abort ();
+7 -5
View File
@@ -64,11 +64,11 @@ test-srcs := tst-fmtmsg
tests := tst-strtol tst-strtod testmb testrand testsort testdiv \
test-canon test-canon2 tst-strtoll tst-environ \
tst-xpg-basename tst-random tst-random2 tst-bsearch \
tst-limits tst-rand48 bug-strtod tst-setcontext \
test-a64l tst-qsort tst-system testmb2 bug-strtod2 \
tst-atof1 tst-atof2 tst-strtod2 tst-strtod3 tst-rand48-2 \
tst-makecontext tst-strtod4 tst-strtod5 tst-qsort2 \
tst-makecontext2 tst-strtod6 tst-unsetenv1 \
tst-limits tst-rand48 bug-strtod tst-setcontext \
tst-setcontext2 test-a64l tst-qsort tst-system testmb2 \
bug-strtod2 tst-atof1 tst-atof2 tst-strtod2 tst-strtod3 \
tst-rand48-2 tst-makecontext tst-strtod4 tst-strtod5 \
tst-qsort2 tst-makecontext2 tst-strtod6 tst-unsetenv1 \
tst-makecontext3 bug-getcontext bug-fmtmsg1 \
tst-secure-getenv tst-strtod-overflow tst-strtod-round \
tst-tininess tst-strtod-underflow tst-tls-atexit
@@ -164,3 +164,5 @@ tst-tls-atexit-lib.so-no-z-defs = yes
$(objpfx)tst-tls-atexit: $(common-objpfx)nptl/libpthread.so \
$(common-objpfx)dlfcn/libdl.so
$(objpfx)tst-tls-atexit.out: $(objpfx)tst-tls-atexit-lib.so
$(objpfx)tst-makecontext: $(libdl)
+10 -2
View File
@@ -42,6 +42,10 @@ static __thread struct link_map *lm_cache;
int
__cxa_thread_atexit_impl (dtor_func func, void *obj, void *dso_symbol)
{
#ifdef PTR_MANGLE
PTR_MANGLE (func);
#endif
/* Prepend. */
struct dtor_list *new = calloc (1, sizeof (struct dtor_list));
new->func = func;
@@ -83,9 +87,13 @@ __call_tls_dtors (void)
while (tls_dtor_list)
{
struct dtor_list *cur = tls_dtor_list;
tls_dtor_list = tls_dtor_list->next;
dtor_func func = cur->func;
#ifdef PTR_DEMANGLE
PTR_DEMANGLE (func);
#endif
cur->func (cur->obj);
tls_dtor_list = tls_dtor_list->next;
func (cur->obj);
__rtld_lock_lock_recursive (GL(dl_load_lock));
+40 -1
View File
@@ -19,23 +19,62 @@
#include <stdlib.h>
#include <stdio.h>
#include <ucontext.h>
#include <assert.h>
#include <unwind.h>
#include <dlfcn.h>
#include <gnu/lib-names.h>
ucontext_t ucp;
char st1[8192];
char st1[16384];
__thread int thr;
int somevar = -76;
long othervar = -78L;
struct trace_arg
{
int cnt, size;
};
static _Unwind_Reason_Code
backtrace_helper (struct _Unwind_Context *ctx, void *a)
{
struct trace_arg *arg = a;
if (++arg->cnt == arg->size)
return _URC_END_OF_STACK;
return _URC_NO_REASON;
}
void
cf (int i)
{
struct trace_arg arg = { .size = 100, .cnt = -1 };
void *handle;
_Unwind_Reason_Code (*unwind_backtrace) (_Unwind_Trace_Fn, void *);
if (i != othervar || thr != 94)
{
printf ("i %d thr %d\n", i, thr);
exit (1);
}
/* Test if callback function of _Unwind_Backtrace is not called infinitely
times. See Bug 18508 or gcc bug "Bug 66303 - runtime.Caller() returns
infinitely deep stack frames on s390x.".
The go runtime calls backtrace_full() in
<gcc-src>/libbacktrace/backtrace.c, which uses _Unwind_Backtrace(). */
handle = dlopen (LIBGCC_S_SO, RTLD_LAZY);
if (handle != NULL)
{
unwind_backtrace = dlsym (handle, "_Unwind_Backtrace");
if (unwind_backtrace != NULL)
{
unwind_backtrace (backtrace_helper, &arg);
assert (arg.cnt != -1 && arg.cnt < 100);
}
dlclose (handle);
}
/* Since uc_link below has been set to NULL, setcontext is supposed to
terminate the process normally after this function returns. */
}
+230
View File
@@ -0,0 +1,230 @@
/* Testcase checks, if setcontext(), swapcontext() restores signal-mask
and if pending signals are delivered after those calls.
Copyright (C) 2015 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <signal.h>
#include <ucontext.h>
#include <unistd.h>
volatile int global;
volatile sig_atomic_t handlerCalled;
static void
check (const char *funcName)
{
sigset_t set;
/* check if SIGUSR2 is unblocked after setcontext-call. */
sigprocmask (SIG_BLOCK, NULL, &set);
if (sigismember (&set, SIGUSR2) != 0)
{
printf ("FAIL: SIGUSR2 is blocked after %s.\n", funcName);
exit (1);
}
if (sigismember (&set, SIGUSR1) != 1)
{
printf ("FAIL: SIGUSR1 is not blocked after %s.\n", funcName);
exit (1);
}
}
static void
signalmask (int how, int signum)
{
sigset_t set;
sigemptyset (&set);
sigaddset (&set, signum);
if (sigprocmask (how, &set, NULL) != 0)
{
printf ("FAIL: sigprocmaks (%d, %d, NULL): %m\n", how, signum);
exit (1);
}
}
static void
signalpending (int signum, const char *msg)
{
sigset_t set;
sigemptyset (&set);
if (sigpending (&set) != 0)
{
printf ("FAIL: sigpending: %m\n");
exit (1);
}
if (sigismember (&set, SIGUSR2) != 1)
{
printf ("FAIL: Signal %d is not pending %s\n", signum, msg);
exit (1);
}
}
static void
handler (int __attribute__ ((unused)) signum)
{
handlerCalled ++;
}
static int
do_test (void)
{
ucontext_t ctx, oldctx;
struct sigaction action;
pid_t pid;
pid = getpid ();
/* unblock SIGUSR2 */
signalmask (SIG_UNBLOCK, SIGUSR2);
/* block SIGUSR1 */
signalmask (SIG_BLOCK, SIGUSR1);
/* register handler for SIGUSR2 */
action.sa_flags = 0;
action.sa_handler = handler;
sigemptyset (&action.sa_mask);
sigaction (SIGUSR2, &action, NULL);
if (getcontext (&ctx) != 0)
{
printf ("FAIL: getcontext: %m\n");
exit (1);
}
global++;
if (global == 1)
{
puts ("after getcontext");
/* block SIGUSR2 */
signalmask (SIG_BLOCK, SIGUSR2);
/* send SIGUSR2 to me */
handlerCalled = 0;
kill (pid, SIGUSR2);
/* was SIGUSR2 handler called? */
if (handlerCalled != 0)
{
puts ("FAIL: signal handler was called, but signal was blocked.");
exit (1);
}
/* is SIGUSR2 pending? */
signalpending (SIGUSR2, "before setcontext");
/* SIGUSR2 will be unblocked by setcontext-call. */
if (setcontext (&ctx) != 0)
{
printf ("FAIL: setcontext: %m\n");
exit (1);
}
}
else if (global == 2)
{
puts ("after setcontext");
/* check SIGUSR1/2 */
check ("setcontext");
/* was SIGUSR2 handler called? */
if (handlerCalled != 1)
{
puts ("FAIL: signal handler was not called after setcontext.");
exit (1);
}
/* block SIGUSR2 */
signalmask (SIG_BLOCK, SIGUSR2);
/* send SIGUSR2 to me */
handlerCalled = 0;
kill (pid, SIGUSR2);
/* was SIGUSR2 handler called? */
if (handlerCalled != 0)
{
puts ("FAIL: signal handler was called, but signal was blocked.");
exit (1);
}
/* is SIGUSR2 pending? */
signalpending (SIGUSR2, "before swapcontext");
if (swapcontext (&oldctx, &ctx) != 0)
{
printf ("FAIL: swapcontext: %m\n");
exit (1);
}
puts ("after returned from swapcontext");
if (global != 3)
{
puts ("FAIL: returned from swapcontext without ctx-context called.");
exit (1);
}
puts ("test succeeded");
return 0;
}
else if ( global != 3 )
{
puts ("FAIL: 'global' not incremented three times");
exit (1);
}
puts ("after swapcontext");
/* check SIGUSR1/2 */
check ("swapcontext");
/* was SIGUSR2 handler called? */
if (handlerCalled != 1)
{
puts ("FAIL: signal handler was not called after swapcontext.");
exit (1);
}
/* check sigmask in old context of swapcontext-call */
if (sigismember (&oldctx.uc_sigmask, SIGUSR2) != 1)
{
puts ("FAIL: SIGUSR2 is not blocked in oldctx.uc_sigmask.");
exit (1);
}
if (sigismember (&oldctx.uc_sigmask, SIGUSR1) != 1)
{
puts ("FAIL: SIGUSR1 is not blocked in oldctx.uc_sigmaks.");
exit (1);
}
/* change to old context, which was gathered by swapcontext() call. */
setcontext (&oldctx);
puts ("FAIL: returned from setcontext (&oldctx)");
exit (1);
}
#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"
+403 -96
View File
@@ -40,8 +40,23 @@
#define CONCAT(a,b) CONCAT1(a,b)
#define CONCAT1(a,b) a##b
/* Maximum string size that is calculated with cached indices. Right now this
is an arbitrary value open to optimizations. SMALL_STR_SIZE * 4 has to be
lower than __MAX_ALLOCA_CUTOFF. Keep localedata/xfrm-test.c in sync. */
#define SMALL_STR_SIZE 4095
#include "../locale/localeinfo.h"
/* Group locale data for shorter parameter lists. */
typedef struct
{
uint_fast32_t nrules;
unsigned char *rulesets;
USTRING_TYPE *weights;
int32_t *table;
USTRING_TYPE *extra;
int32_t *indirect;
} locale_data_t;
#ifndef WIDE_CHAR_VERSION
@@ -80,115 +95,330 @@ utf8_encode (char *buf, int val)
}
#endif
size_t
STRXFRM (STRING_TYPE *dest, const STRING_TYPE *src, size_t n, __locale_t l)
/* Find next weight and rule index. Inlined since called for every char. */
static __always_inline size_t
find_idx (const USTRING_TYPE **us, int32_t *weight_idx,
unsigned char *rule_idx, const locale_data_t *l_data, const int pass)
{
struct __locale_data *current = l->__locales[LC_COLLATE];
uint_fast32_t nrules = current->values[_NL_ITEM_INDEX (_NL_COLLATE_NRULES)].word;
/* We don't assign the following values right away since it might be
unnecessary in case there are no rules. */
const unsigned char *rulesets;
const int32_t *table;
const USTRING_TYPE *weights;
const USTRING_TYPE *extra;
const int32_t *indirect;
uint_fast32_t pass;
size_t needed;
size_t last_needed;
const USTRING_TYPE *usrc;
size_t srclen = STRLEN (src);
int32_t *idxarr;
unsigned char *rulearr;
size_t idxmax;
size_t idxcnt;
int use_malloc;
/* Prepare variables required by findidx(). */
int32_t *table = l_data->table;
int32_t *indirect = l_data->indirect;
USTRING_TYPE *extra = l_data->extra;
#include WEIGHT_H
int32_t tmp = findidx (us, -1);
*rule_idx = tmp >> 24;
int32_t idx = tmp & 0xffffff;
size_t len = l_data->weights[idx++];
if (nrules == 0)
/* Skip over indices of previous levels. */
for (int i = 0; i < pass; i++)
{
if (n != 0)
STPNCPY (dest, src, MIN (srclen + 1, n));
return srclen;
idx += len;
len = l_data->weights[idx++];
}
rulesets = (const unsigned char *)
current->values[_NL_ITEM_INDEX (_NL_COLLATE_RULESETS)].string;
table = (const int32_t *)
current->values[_NL_ITEM_INDEX (CONCAT(_NL_COLLATE_TABLE,SUFFIX))].string;
weights = (const USTRING_TYPE *)
current->values[_NL_ITEM_INDEX (CONCAT(_NL_COLLATE_WEIGHT,SUFFIX))].string;
extra = (const USTRING_TYPE *)
current->values[_NL_ITEM_INDEX (CONCAT(_NL_COLLATE_EXTRA,SUFFIX))].string;
indirect = (const int32_t *)
current->values[_NL_ITEM_INDEX (CONCAT(_NL_COLLATE_INDIRECT,SUFFIX))].string;
use_malloc = 0;
*weight_idx = idx;
return len;
}
assert (((uintptr_t) table) % __alignof__ (table[0]) == 0);
assert (((uintptr_t) weights) % __alignof__ (weights[0]) == 0);
assert (((uintptr_t) extra) % __alignof__ (extra[0]) == 0);
assert (((uintptr_t) indirect) % __alignof__ (indirect[0]) == 0);
static int
find_position (const USTRING_TYPE *us, const locale_data_t *l_data,
const int pass)
{
int32_t weight_idx;
unsigned char rule_idx;
const USTRING_TYPE *usrc = us;
/* Handle an empty string as a special case. */
if (srclen == 0)
find_idx (&usrc, &weight_idx, &rule_idx, l_data, pass);
return l_data->rulesets[rule_idx * l_data->nrules + pass] & sort_position;
}
/* Do the transformation. */
static size_t
do_xfrm (const USTRING_TYPE *usrc, STRING_TYPE *dest, size_t n,
const locale_data_t *l_data)
{
int32_t weight_idx;
unsigned char rule_idx;
uint_fast32_t pass;
size_t needed = 0;
size_t last_needed;
/* Now the passes over the weights. */
for (pass = 0; pass < l_data->nrules; ++pass)
{
if (n != 0)
*dest = L('\0');
return 0;
size_t backw_len = 0;
last_needed = needed;
const USTRING_TYPE *cur = usrc;
const USTRING_TYPE *backw_start = NULL;
/* We assume that if a rule has defined `position' in one section
this is true for all of them. */
int position = find_position (cur, l_data, pass);
if (position == 0)
{
while (*cur != L('\0'))
{
const USTRING_TYPE *pos = cur;
size_t len = find_idx (&cur, &weight_idx, &rule_idx, l_data,
pass);
int rule = l_data->rulesets[rule_idx * l_data->nrules + pass];
if ((rule & sort_forward) != 0)
{
/* Handle the pushed backward sequence. */
if (backw_start != NULL)
{
for (size_t i = backw_len; i > 0; )
{
int32_t weight_idx;
unsigned char rule_idx;
size_t len = find_idx (&backw_start, &weight_idx,
&rule_idx, l_data, pass);
if (needed + i < n)
for (size_t j = len; j > 0; j--)
dest[needed + i - j] =
l_data->weights[weight_idx++];
i -= len;
}
needed += backw_len;
backw_start = NULL;
backw_len = 0;
}
/* Now handle the forward element. */
if (needed + len < n)
while (len-- > 0)
dest[needed++] = l_data->weights[weight_idx++];
else
/* No more characters fit into the buffer. */
needed += len;
}
else
{
/* Remember start of the backward sequence & track length. */
if (backw_start == NULL)
backw_start = pos;
backw_len += len;
}
}
/* Handle the pushed backward sequence. */
if (backw_start != NULL)
{
for (size_t i = backw_len; i > 0; )
{
size_t len = find_idx (&backw_start, &weight_idx, &rule_idx,
l_data, pass);
if (needed + i < n)
for (size_t j = len; j > 0; j--)
dest[needed + i - j] =
l_data->weights[weight_idx++];
i -= len;
}
needed += backw_len;
}
}
else
{
int val = 1;
#ifndef WIDE_CHAR_VERSION
char buf[7];
size_t buflen;
#endif
size_t i;
while (*cur != L('\0'))
{
const USTRING_TYPE *pos = cur;
size_t len = find_idx (&cur, &weight_idx, &rule_idx, l_data,
pass);
int rule = l_data->rulesets[rule_idx * l_data->nrules + pass];
if ((rule & sort_forward) != 0)
{
/* Handle the pushed backward sequence. */
if (backw_start != NULL)
{
for (size_t p = backw_len; p > 0; p--)
{
size_t len;
int32_t weight_idx;
unsigned char rule_idx;
const USTRING_TYPE *backw_cur = backw_start;
/* To prevent a warning init the used vars. */
len = find_idx (&backw_cur, &weight_idx,
&rule_idx, l_data, pass);
for (i = 1; i < p; i++)
len = find_idx (&backw_cur, &weight_idx,
&rule_idx, l_data, pass);
if (len != 0)
{
#ifdef WIDE_CHAR_VERSION
if (needed + 1 + len < n)
{
dest[needed] = val;
for (i = 0; i < len; ++i)
dest[needed + 1 + i] =
l_data->weights[weight_idx + i];
}
needed += 1 + len;
#else
buflen = utf8_encode (buf, val);
if (needed + buflen + len < n)
{
for (i = 0; i < buflen; ++i)
dest[needed + i] = buf[i];
for (i = 0; i < len; ++i)
dest[needed + buflen + i] =
l_data->weights[weight_idx + i];
}
needed += buflen + len;
#endif
val = 1;
}
else
++val;
}
backw_start = NULL;
backw_len = 0;
}
/* Now handle the forward element. */
if (len != 0)
{
#ifdef WIDE_CHAR_VERSION
if (needed + 1 + len < n)
{
dest[needed] = val;
for (i = 0; i < len; ++i)
dest[needed + 1 + i] =
l_data->weights[weight_idx + i];
}
needed += 1 + len;
#else
buflen = utf8_encode (buf, val);
if (needed + buflen + len < n)
{
for (i = 0; i < buflen; ++i)
dest[needed + i] = buf[i];
for (i = 0; i < len; ++i)
dest[needed + buflen + i] =
l_data->weights[weight_idx + i];
}
needed += buflen + len;
#endif
val = 1;
}
else
++val;
}
else
{
/* Remember start of the backward sequence & track length. */
if (backw_start == NULL)
backw_start = pos;
backw_len++;
}
}
/* Handle the pushed backward sequence. */
if (backw_start != NULL)
{
for (size_t p = backw_len; p > 0; p--)
{
size_t len;
int32_t weight_idx;
unsigned char rule_idx;
const USTRING_TYPE *backw_cur = backw_start;
/* To prevent a warning init the used vars. */
len = find_idx (&backw_cur, &weight_idx,
&rule_idx, l_data, pass);
for (i = 1; i < p; i++)
len = find_idx (&backw_cur, &weight_idx,
&rule_idx, l_data, pass);
if (len != 0)
{
#ifdef WIDE_CHAR_VERSION
if (needed + 1 + len < n)
{
dest[needed] = val;
for (i = 0; i < len; ++i)
dest[needed + 1 + i] =
l_data->weights[weight_idx + i];
}
needed += 1 + len;
#else
buflen = utf8_encode (buf, val);
if (needed + buflen + len < n)
{
for (i = 0; i < buflen; ++i)
dest[needed + i] = buf[i];
for (i = 0; i < len; ++i)
dest[needed + buflen + i] =
l_data->weights[weight_idx + i];
}
needed += buflen + len;
#endif
val = 1;
}
else
++val;
}
}
}
/* Finally store the byte to separate the passes or terminate
the string. */
if (needed < n)
dest[needed] = pass + 1 < l_data->nrules ? L('\1') : L('\0');
++needed;
}
/* We need the elements of the string as unsigned values since they
are used as indeces. */
usrc = (const USTRING_TYPE *) src;
/* Perform the first pass over the string and while doing this find
and store the weights for each character. Since we want this to
be as fast as possible we are using `alloca' to store the temporary
values. But since there is no limit on the length of the string
we have to use `malloc' if the string is too long. We should be
very conservative here. */
if (! __libc_use_alloca ((srclen + 1) * (sizeof (int32_t) + 1)))
/* This is a little optimization: many collation specifications have
a `position' rule at the end and if no non-ignored character
is found the last \1 byte is immediately followed by a \0 byte
signalling this. We can avoid the \1 byte(s). */
if (needed > 2 && needed == last_needed + 1)
{
idxarr = (int32_t *) malloc ((srclen + 1) * (sizeof (int32_t) + 1));
rulearr = (unsigned char *) &idxarr[srclen];
if (idxarr == NULL)
/* No memory. Well, go with the stack then.
XXX Once this implementation is stable we will handle this
differently. Instead of precomputing the indeces we will
do this in time. This means, though, that this happens for
every pass again. */
goto try_stack;
use_malloc = 1;
}
else
{
try_stack:
idxarr = (int32_t *) alloca (srclen * sizeof (int32_t));
rulearr = (unsigned char *) alloca (srclen + 1);
/* Remove the \1 byte. */
if (--needed <= n)
dest[needed - 1] = L('\0');
}
idxmax = 0;
do
{
int32_t tmp = findidx (&usrc, -1);
rulearr[idxmax] = tmp >> 24;
idxarr[idxmax] = tmp & 0xffffff;
/* Return the number of bytes/words we need, but don't count the NUL
byte/word at the end. */
return needed - 1;
}
++idxmax;
}
while (*usrc != L('\0'));
/* Do the transformation using weight-index and rule cache. */
static size_t
do_xfrm_cached (STRING_TYPE *dest, size_t n, const locale_data_t *l_data,
size_t idxmax, int32_t *idxarr, const unsigned char *rulearr)
{
uint_fast32_t nrules = l_data->nrules;
unsigned char *rulesets = l_data->rulesets;
USTRING_TYPE *weights = l_data->weights;
uint_fast32_t pass;
size_t needed = 0;
size_t last_needed;
size_t idxcnt;
/* This element is only read, the value never used but to determine
another value which then is ignored. */
rulearr[idxmax] = '\0';
/* Now the passes over the weights. We now use the indeces we found
before. */
needed = 0;
/* Now the passes over the weights. */
for (pass = 0; pass < nrules; ++pass)
{
size_t backw_stop = ~0ul;
@@ -434,14 +664,91 @@ STRXFRM (STRING_TYPE *dest, const STRING_TYPE *src, size_t n, __locale_t l)
dest[needed - 1] = L('\0');
}
/* Free the memory if needed. */
if (use_malloc)
free (idxarr);
/* Return the number of bytes/words we need, but don't count the NUL
byte/word at the end. */
return needed - 1;
}
size_t
STRXFRM (STRING_TYPE *dest, const STRING_TYPE *src, size_t n, __locale_t l)
{
locale_data_t l_data;
struct __locale_data *current = l->__locales[LC_COLLATE];
l_data.nrules = current->values[_NL_ITEM_INDEX (_NL_COLLATE_NRULES)].word;
/* Handle byte comparison case. */
if (l_data.nrules == 0)
{
size_t srclen = STRLEN (src);
if (n != 0)
STPNCPY (dest, src, MIN (srclen + 1, n));
return srclen;
}
/* Handle an empty string, code hereafter relies on strlen (src) > 0. */
if (*src == L('\0'))
{
if (n != 0)
*dest = L('\0');
return 0;
}
/* Get the locale data. */
l_data.rulesets = (unsigned char *)
current->values[_NL_ITEM_INDEX (_NL_COLLATE_RULESETS)].string;
l_data.table = (int32_t *)
current->values[_NL_ITEM_INDEX (CONCAT(_NL_COLLATE_TABLE,SUFFIX))].string;
l_data.weights = (USTRING_TYPE *)
current->values[_NL_ITEM_INDEX (CONCAT(_NL_COLLATE_WEIGHT,SUFFIX))].string;
l_data.extra = (USTRING_TYPE *)
current->values[_NL_ITEM_INDEX (CONCAT(_NL_COLLATE_EXTRA,SUFFIX))].string;
l_data.indirect = (int32_t *)
current->values[_NL_ITEM_INDEX (CONCAT(_NL_COLLATE_INDIRECT,SUFFIX))].string;
assert (((uintptr_t) l_data.table) % __alignof__ (l_data.table[0]) == 0);
assert (((uintptr_t) l_data.weights) % __alignof__ (l_data.weights[0]) == 0);
assert (((uintptr_t) l_data.extra) % __alignof__ (l_data.extra[0]) == 0);
assert (((uintptr_t) l_data.indirect) % __alignof__ (l_data.indirect[0]) == 0);
/* We need the elements of the string as unsigned values since they
are used as indeces. */
const USTRING_TYPE *usrc = (const USTRING_TYPE *) src;
/* Allocate cache for small strings on the stack and fill it with weight and
rule indices. If the cache size is not sufficient, continue with the
uncached xfrm version. */
size_t idxmax = 0;
const USTRING_TYPE *cur = usrc;
int32_t *idxarr = alloca (SMALL_STR_SIZE * sizeof (int32_t));
unsigned char *rulearr = alloca (SMALL_STR_SIZE + 1);
/* Prepare variables required by findidx(). */
int32_t *table = l_data.table;
int32_t *indirect = l_data.indirect;
USTRING_TYPE *extra = l_data.extra;
#include WEIGHT_H
do
{
int32_t tmp = findidx (&cur, -1);
rulearr[idxmax] = tmp >> 24;
idxarr[idxmax] = tmp & 0xffffff;
++idxmax;
}
while (*cur != L('\0') && idxmax < SMALL_STR_SIZE);
/* This element is only read, the value never used but to determine
another value which then is ignored. */
rulearr[idxmax] = '\0';
/* Do the transformation. */
if (*cur == L('\0'))
return do_xfrm_cached (dest, n, &l_data, idxmax, idxarr, rulearr);
else
return do_xfrm (usrc, dest, n, &l_data);
}
libc_hidden_def (STRXFRM)
#ifndef WIDE_CHAR_VERSION
+28
View File
@@ -329,6 +329,34 @@ check (void)
FOR_EACH_IMPL (impl, 0)
check_result (impl, s1 + i1, s2 + i2, exp_result);
}
/* Test cases where there are multiple zero bytes after the first. */
for (size_t i = 0; i < 16 + 1; i++)
{
s1[i] = 0x00;
s2[i] = 0x00;
}
for (size_t i = 0; i < 16; i++)
{
int exp_result;
for (int val = 0x01; val < 0x100; val++)
{
for (size_t j = 0; j < i; j++)
{
s1[j] = val;
s2[j] = val;
}
s2[i] = val;
exp_result = SIMPLE_STRCMP (s1, s2);
FOR_EACH_IMPL (impl, 0)
check_result (impl, s1, s2, exp_result);
}
}
}
+9 -1
View File
@@ -420,9 +420,15 @@ send_again:
struct sock_extended_err *e;
struct sockaddr_in err_addr;
struct iovec iov;
char *cbuf = (char *) alloca (outlen + 256);
char *cbuf = malloc (outlen + 256);
int ret;
if (cbuf == NULL)
{
cu->cu_error.re_errno = errno;
return (cu->cu_error.re_status = RPC_CANTRECV);
}
iov.iov_base = cbuf + 256;
iov.iov_len = outlen;
msg.msg_name = (void *) &err_addr;
@@ -447,10 +453,12 @@ send_again:
cmsg = CMSG_NXTHDR (&msg, cmsg))
if (cmsg->cmsg_level == SOL_IP && cmsg->cmsg_type == IP_RECVERR)
{
free (cbuf);
e = (struct sock_extended_err *) CMSG_DATA(cmsg);
cu->cu_error.re_errno = e->ee_errno;
return (cu->cu_error.re_status = RPC_CANTRECV);
}
free (cbuf);
}
#endif
do
-3
View File
@@ -590,9 +590,6 @@ struct rtld_global_ro
/* List of auditing interfaces. */
struct audit_ifaces *_dl_audit;
unsigned int _dl_naudit;
/* 0 if internal pointer values should not be guarded, 1 if they should. */
EXTERN int _dl_pointer_guard;
};
# define __rtld_global_attribute__
# ifdef IS_IN_rtld
+10 -6
View File
@@ -447,19 +447,21 @@ __sin (double x)
}
else
{
double t;
if (a > 0)
{
m = 1;
t = a;
db = da;
}
else
{
m = 0;
a = -a;
t = -a;
db = -da;
}
u.x = big + a;
y = a - (u.x - big);
u.x = big + t;
y = t - (u.x - big);
res = do_sin (u, y, db, &cor);
cor = (cor > 0) ? 1.035 * cor + eps : 1.035 * cor - eps;
retval = ((res == res + cor) ? ((m) ? res : -res)
@@ -671,19 +673,21 @@ __cos (double x)
}
else
{
double t;
if (a > 0)
{
m = 1;
t = a;
db = da;
}
else
{
m = 0;
a = -a;
t = -a;
db = -da;
}
u.x = big + a;
y = a - (u.x - big);
u.x = big + t;
y = t - (u.x - big);
res = do_sin (u, y, db, &cor);
cor = (cor > 0) ? 1.035 * cor + eps : 1.035 * cor - eps;
retval = ((res == res + cor) ? ((m) ? res : -res)
+2 -2
View File
@@ -22,7 +22,7 @@
#include <hurd.h>
#include <hurd/fd.h>
/* Open FILE with access OFLAG. If OFLAG includes O_CREAT,
/* Open FILE with access OFLAG. If O_CREAT or O_TMPFILE is in OFLAG,
a third argument is the file protection. */
int
__libc_open (const char *file, int oflag, ...)
@@ -30,7 +30,7 @@ __libc_open (const char *file, int oflag, ...)
mode_t mode;
io_t port;
if (oflag & O_CREAT)
if (__OPEN_NEEDS_MODE (oflag))
{
va_list arg;
va_start (arg, oflag);
+2 -2
View File
@@ -26,7 +26,7 @@
#include <hurd/fd.h>
/* Open FILE with access OFLAG. Interpret relative paths relative to
the directory associated with FD. If OFLAG includes O_CREAT, a
the directory associated with FD. If O_CREAT or O_TMPFILE is in OFLAG, a
third argument is the file protection. */
int
__openat (fd, file, oflag)
@@ -37,7 +37,7 @@ __openat (fd, file, oflag)
mode_t mode;
io_t port;
if (oflag & O_CREAT)
if (__OPEN_NEEDS_MODE (oflag))
{
va_list arg;
va_start (arg, oflag);

Some files were not shown because too many files have changed in this diff Show More