mirror of
git://sourceware.org/git/glibc.git
synced 2026-09-09 05:59:27 +08:00
Compare commits
29
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
715e7fe032 | ||
|
|
04130e53ba | ||
|
|
c5ae7f9a3b | ||
|
|
b057b4813c | ||
|
|
3252416085 | ||
|
|
161a7ef860 | ||
|
|
f0cb70a254 | ||
|
|
80e44fad70 | ||
|
|
d4deb63367 | ||
|
|
f2b605ed88 | ||
|
|
d56700df46 | ||
|
|
3ce4555d43 | ||
|
|
25394eff67 | ||
|
|
bc273d38b1 | ||
|
|
d680656b61 | ||
|
|
c616775d2c | ||
|
|
2a8396b962 | ||
|
|
0553c6642b | ||
|
|
a244697f97 | ||
|
|
8b43a2274a | ||
|
|
ca0dd6386e | ||
|
|
6d153c48a1 | ||
|
|
2293d2b10a | ||
|
|
2216e48645 | ||
|
|
2770d15e7e | ||
|
|
f8a8e175b8 | ||
|
|
4f2bcda964 | ||
|
|
c7afb54706 | ||
|
|
b9435dcc93 |
@@ -1,3 +1,162 @@
|
||||
2016-04-22 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-04-22 Andreas Schwab <schwab@suse.de>
|
||||
|
||||
[BZ #15946]
|
||||
* resolv/res_send.c (send_dg): Reload file descriptor after
|
||||
calling reopen.
|
||||
|
||||
2016-04-22 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.
|
||||
|
||||
2015-12-31 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.
|
||||
|
||||
2015-12-30 Paul Pluzhnikov <ppluzhnikov@google.com>
|
||||
|
||||
[BZ #17269]
|
||||
* libio/wstrops.c (_IO_wstr_overflow): Guard against integer overflow
|
||||
(enlarge_userbuf): Likewise.
|
||||
|
||||
2015-12-30 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.
|
||||
* posix/tst-fnmatch3.c (do_test): Add test case.
|
||||
|
||||
2015-12-30 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.
|
||||
|
||||
2015-12-30 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.
|
||||
|
||||
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-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-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-01-29 H.J. Lu <hongjiu.lu@intel.com>
|
||||
|
||||
[BZ #16510]
|
||||
* sysdeps/x86/fpu/bits/mathinline.h: Check __SSE2_MATH__ instead
|
||||
of __x86_64__ when disabling x87 inline functions.
|
||||
|
||||
2014-01-20 H.J. Lu <hongjiu.lu@intel.com>
|
||||
|
||||
[BZ #15605]
|
||||
* sysdeps/x86_64/x32/symbol-hacks.h: Include generic symbol-hacks.h.
|
||||
|
||||
2014-01-04 Maxim Kuvyrkov <maxim@kugelworks.com>
|
||||
Ondřej Bílka <neleai@seznam.cz>
|
||||
|
||||
[BZ #15073]
|
||||
* malloc/malloc.c (_int_free): Perform sanity check only if we
|
||||
have_lock.
|
||||
|
||||
2013-11-11 David S. Miller <davem@davemloft.net>
|
||||
|
||||
[BZ #16150]
|
||||
* sysdeps/sparc/sparc64/multiarch/add_n.S: Resolve to the correct generic
|
||||
symbol in the non-vis3 case in static builds.
|
||||
* sysdeps/sparc/sparc64/multiarch/addmul_1.S: Likewise.
|
||||
* sysdeps/sparc/sparc64/multiarch/mul_1.S: Likewise.
|
||||
* sysdeps/sparc/sparc64/multiarch/sub_n.S: Likewise.
|
||||
* sysdeps/sparc/sparc64/multiarch/submul_1.S: Likewise.
|
||||
|
||||
2013-11-06 David S. Miller <davem@davemloft.net>
|
||||
|
||||
[BZ #15985]
|
||||
* sysdeps/sparc/sparc32/fpu/s_fdim.S (__fdim): Do not use fnegd
|
||||
on pre-v9 cpus, use a fnegs+fmovs sequence instead.
|
||||
|
||||
2013-09-06 David S. Miller <davem@davemloft.net>
|
||||
|
||||
* po/zh_TW.po: Update Chinese (traditional) translation from
|
||||
translation project.
|
||||
|
||||
2013-08-22 David S. Miller <davem@davemloft.net>
|
||||
|
||||
* po/ca.po: Update Catalan translation from translation project.
|
||||
* po/uk.po: Add Ukrainian translations from translation project.
|
||||
|
||||
2013-08-03 David S. Miller <davem@davemloft.net>
|
||||
|
||||
* po/ko.po: Update Korean translation from translation project.
|
||||
|
||||
@@ -5,6 +5,31 @@ 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.18.1
|
||||
|
||||
* The following bugs are resolved with this release:
|
||||
|
||||
15073, 15128, 15909, 15946, 15996, 16009, 16150, 16169, 16387, 16510,
|
||||
16885, 16916, 16943, 16958, 17269, 18032, 18665, 18928, 19018, 19791.
|
||||
|
||||
|
||||
* The LD_POINTER_GUARD environment variable can no longer be used to
|
||||
disable the pointer guard feature. It is always enabled.
|
||||
|
||||
* 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)
|
||||
|
||||
Version 2.18
|
||||
|
||||
* The following bugs are resolved with this release:
|
||||
@@ -22,7 +47,7 @@ Version 2.18
|
||||
15429, 15431, 15432, 15441, 15442, 15448, 15465, 15480, 15485, 15488,
|
||||
15490, 15492, 15493, 15497, 15506, 15529, 15536, 15553, 15577, 15583,
|
||||
15618, 15627, 15631, 15654, 15655, 15666, 15667, 15674, 15711, 15755,
|
||||
15759.
|
||||
15759, 15985, 16882.
|
||||
|
||||
* CVE-2013-2207 Incorrectly granting access to another user's pseudo-terminal
|
||||
has been fixed by disabling the use of pt_chown (Bugzilla #15755).
|
||||
|
||||
+4
-11
@@ -162,7 +162,6 @@ struct rtld_global_ro _rtld_global_ro attribute_relro =
|
||||
._dl_hwcap_mask = HWCAP_IMPORTANT,
|
||||
._dl_lazy = 1,
|
||||
._dl_fpu_control = _FPU_DEFAULT,
|
||||
._dl_pointer_guard = 1,
|
||||
._dl_pagesize = EXEC_PAGESIZE,
|
||||
._dl_inhibit_cache = 0,
|
||||
|
||||
@@ -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
|
||||
@@ -2606,9 +2602,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:
|
||||
|
||||
+7
-1
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
+46
-6
@@ -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;
|
||||
}
|
||||
|
||||
+12
-8
@@ -3809,25 +3809,29 @@ _int_free(mstate av, mchunkptr p, int have_lock)
|
||||
unsigned int idx = fastbin_index(size);
|
||||
fb = &fastbin (av, idx);
|
||||
|
||||
mchunkptr fd;
|
||||
mchunkptr old = *fb;
|
||||
/* Atomically link P to its fastbin: P->FD = *FB; *FB = P; */
|
||||
mchunkptr old = *fb, old2;
|
||||
unsigned int old_idx = ~0u;
|
||||
do
|
||||
{
|
||||
/* Another simple check: make sure the top of the bin is not the
|
||||
record we are going to add (i.e., double free). */
|
||||
/* Check that the top of the bin is not the record we are going to add
|
||||
(i.e., double free). */
|
||||
if (__builtin_expect (old == p, 0))
|
||||
{
|
||||
errstr = "double free or corruption (fasttop)";
|
||||
goto errout;
|
||||
}
|
||||
if (old != NULL)
|
||||
/* Check that size of fastbin chunk at the top is the same as
|
||||
size of the chunk that we are adding. We can dereference OLD
|
||||
only if we have the lock, otherwise it might have already been
|
||||
deallocated. See use of OLD_IDX below for the actual check. */
|
||||
if (have_lock && old != NULL)
|
||||
old_idx = fastbin_index(chunksize(old));
|
||||
p->fd = fd = old;
|
||||
p->fd = old2 = old;
|
||||
}
|
||||
while ((old = catomic_compare_and_exchange_val_rel (fb, p, fd)) != fd);
|
||||
while ((old = catomic_compare_and_exchange_val_rel (fb, p, old2)) != old2);
|
||||
|
||||
if (fd != NULL && __builtin_expect (old_idx != idx, 0))
|
||||
if (have_lock && old != NULL && __builtin_expect (old_idx != idx, 0))
|
||||
{
|
||||
errstr = "invalid fastbin entry (free)";
|
||||
goto errout;
|
||||
|
||||
@@ -1,3 +1,12 @@
|
||||
2013-10-03 Siddhesh Poyarekar <siddhesh@redhat.com>
|
||||
|
||||
[BZ #15996]
|
||||
* pthread_cond_broadcast.c (__pthread_cond_broadcast)
|
||||
[lll_futex_cmp_requeue_pi && __ASSUME_REQUEUE_PI]: Use
|
||||
USE_REQUEUE_PI.
|
||||
* pthread_cond_signal.c (__pthread_cond_signal)
|
||||
[lll_futex_cmd_requeue_pi && __ASSUME_REQUEUE_PI]: Likewise.
|
||||
|
||||
2013-07-23 David S. Miller <davem@davemloft.net>
|
||||
|
||||
* tst-cancel4.c (WRITE_BUFFER_SIZE): Adjust comment.
|
||||
|
||||
+1
-1
@@ -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 \
|
||||
|
||||
@@ -63,10 +63,7 @@ __pthread_cond_broadcast (cond)
|
||||
|
||||
#if (defined lll_futex_cmp_requeue_pi \
|
||||
&& defined __ASSUME_REQUEUE_PI)
|
||||
int pi_flag = PTHREAD_MUTEX_PRIO_INHERIT_NP | PTHREAD_MUTEX_ROBUST_NP;
|
||||
pi_flag &= mut->__data.__kind;
|
||||
|
||||
if (pi_flag == PTHREAD_MUTEX_PRIO_INHERIT_NP)
|
||||
if (USE_REQUEUE_PI (mut))
|
||||
{
|
||||
if (lll_futex_cmp_requeue_pi (&cond->__data.__futex, 1, INT_MAX,
|
||||
&mut->__data.__lock, futex_val,
|
||||
|
||||
@@ -49,14 +49,9 @@ __pthread_cond_signal (cond)
|
||||
|
||||
#if (defined lll_futex_cmp_requeue_pi \
|
||||
&& defined __ASSUME_REQUEUE_PI)
|
||||
int pi_flag = PTHREAD_MUTEX_PRIO_INHERIT_NP | PTHREAD_MUTEX_ROBUST_NP;
|
||||
pthread_mutex_t *mut = cond->__data.__mutex;
|
||||
|
||||
/* Do not use requeue for pshared condvars. */
|
||||
if (mut != (void *) ~0l)
|
||||
pi_flag &= mut->__data.__kind;
|
||||
|
||||
if (__builtin_expect (pi_flag == PTHREAD_MUTEX_PRIO_INHERIT_NP, 0)
|
||||
if (USE_REQUEUE_PI (mut)
|
||||
/* This can only really fail with a ENOSYS, since nobody can modify
|
||||
futex while we have the cond_lock. */
|
||||
&& lll_futex_cmp_requeue_pi (&cond->__data.__futex, 1, 0,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
+975
-941
File diff suppressed because it is too large
Load Diff
@@ -1,3 +1,27 @@
|
||||
2014-01-20 Tom Tromey <tromey@redhat.com>
|
||||
|
||||
[BZ #16169]
|
||||
* sysdeps/unix/sysv/linux/aarch64/clone.S (__clone): Add CFI
|
||||
directives; Zero x29.
|
||||
|
||||
2014-01-07 Marcus Shawcroft <marcus.shawcroft@linaro.org>
|
||||
|
||||
[BZ #16387]
|
||||
* sysdeps/aarch64/fpu/fpu_control.h (_FPU_FPCR_RM_MASK): Define.
|
||||
* sysdeps/aarch64/soft-fp/sfp-machine.h (FP_ROUNDMODE): Adjust
|
||||
rounding mode mask.
|
||||
|
||||
2014-01-07 Marcus Shawcroft <marcus.shawcroft@linaro.org>
|
||||
|
||||
* sysdeps/aarch64/dl-trampoline.S (_dl_runtime_resolve): Correct
|
||||
cfi_adjust_cfa_offset offset.
|
||||
|
||||
2013-12-18 Marcus Shawcroft <marcus.shawcroft@linaro.org>
|
||||
|
||||
[BZ #15128]
|
||||
* sysdeps/aarch64/dl-trampoline.S (_dl_runtime_resolve): Save and
|
||||
restore q0-q7.
|
||||
|
||||
2013-07-26 Marcus Shawcroft <marcus.shawcroft@linaro.org>
|
||||
|
||||
* sysdeps/aarch64/Versions: New file.
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
2013-11-16 Richard Henderson <rth@redhat.com>
|
||||
|
||||
* sysdeps/unix/sysv/linux/alpha/rt_sigaction.S: Include a nop
|
||||
before each signal thunk.
|
||||
|
||||
2013-07-02 Richard Henderson <rth@redhat.com>
|
||||
|
||||
* sysdeps/alpha/fpu/libm-test-ulps: Update.
|
||||
|
||||
@@ -1,3 +1,9 @@
|
||||
2013-08-30 Will Newton <will.newton@linaro.org>
|
||||
|
||||
[BZ #15909]
|
||||
* sysdeps/unix/sysv/linux/arm/clone.S (__clone): Use blx
|
||||
instead of mov lr, pc.
|
||||
|
||||
2013-07-03 Joseph Myers <joseph@codesourcery.com>
|
||||
|
||||
* sysdeps/arm/include/bits/setjmp.h [_ISOMAC] (JMP_BUF_REGLIST):
|
||||
|
||||
@@ -41,8 +41,8 @@ _dl_runtime_resolve:
|
||||
cfi_rel_offset (lr, 8)
|
||||
|
||||
/* Save arguments. */
|
||||
stp x8, x9, [sp, #-80]!
|
||||
cfi_adjust_cfa_offset (80)
|
||||
stp x8, x9, [sp, #-(80+8*16)]!
|
||||
cfi_adjust_cfa_offset (80+8*16)
|
||||
cfi_rel_offset (x8, 0)
|
||||
cfi_rel_offset (x9, 8)
|
||||
|
||||
@@ -62,11 +62,27 @@ _dl_runtime_resolve:
|
||||
cfi_rel_offset (x0, 64)
|
||||
cfi_rel_offset (x1, 72)
|
||||
|
||||
stp q0, q1, [sp, #(80+0*16)]
|
||||
cfi_rel_offset (q0, 80+0*16)
|
||||
cfi_rel_offset (q1, 80+1*16)
|
||||
|
||||
stp q2, q3, [sp, #(80+2*16)]
|
||||
cfi_rel_offset (q0, 80+2*16)
|
||||
cfi_rel_offset (q1, 80+3*16)
|
||||
|
||||
stp q4, q5, [sp, #(80+4*16)]
|
||||
cfi_rel_offset (q0, 80+4*16)
|
||||
cfi_rel_offset (q1, 80+5*16)
|
||||
|
||||
stp q6, q7, [sp, #(80+6*16)]
|
||||
cfi_rel_offset (q0, 80+6*16)
|
||||
cfi_rel_offset (q1, 80+7*16)
|
||||
|
||||
/* Get pointer to linker struct. */
|
||||
ldr x0, [ip0, #-8]
|
||||
|
||||
/* Prepare to call _dl_fixup(). */
|
||||
ldr x1, [sp, 80] /* Recover &PLTGOT[n] */
|
||||
ldr x1, [sp, 80+8*16] /* Recover &PLTGOT[n] */
|
||||
|
||||
sub x1, x1, ip0
|
||||
add x1, x1, x1, lsl #1
|
||||
@@ -81,12 +97,16 @@ _dl_runtime_resolve:
|
||||
mov ip0, x0
|
||||
|
||||
/* Get arguments and return address back. */
|
||||
ldp q0, q1, [sp, #(80+0*16)]
|
||||
ldp q2, q3, [sp, #(80+2*16)]
|
||||
ldp q4, q5, [sp, #(80+4*16)]
|
||||
ldp q6, q7, [sp, #(80+6*16)]
|
||||
ldp x0, x1, [sp, #64]
|
||||
ldp x2, x3, [sp, #48]
|
||||
ldp x4, x5, [sp, #32]
|
||||
ldp x6, x7, [sp, #16]
|
||||
ldp x8, x9, [sp], #80
|
||||
cfi_adjust_cfa_offset (-80)
|
||||
ldp x8, x9, [sp], #(80+8*16)
|
||||
cfi_adjust_cfa_offset (-(80+8*16))
|
||||
|
||||
ldp ip1, lr, [sp], #16
|
||||
cfi_adjust_cfa_offset (-16)
|
||||
|
||||
@@ -59,6 +59,9 @@
|
||||
E E D D
|
||||
E E
|
||||
*/
|
||||
|
||||
#define _FPU_FPCR_RM_MASK 0xc00000
|
||||
|
||||
#define _FPU_FPCR_MASK_IXE 0x1000
|
||||
#define _FPU_FPCR_MASK_UFE 0x0800
|
||||
#define _FPU_FPCR_MASK_OFE 0x0400
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
|
||||
#define _FP_DECL_EX fpu_control_t _fcw
|
||||
|
||||
#define FP_ROUNDMODE (_fcw & 0x3)
|
||||
#define FP_ROUNDMODE (_fcw & _FPU_FPCR_RM_MASK)
|
||||
|
||||
#define FP_RND_NEAREST FE_TONEAREST
|
||||
#define FP_RND_ZERO FE_TOWARDZERO
|
||||
|
||||
@@ -63,6 +63,7 @@ ENTRY(__clone)
|
||||
mov x8, #SYS_ify(clone)
|
||||
/* X0:flags, x1:newsp, x2:parenttidptr, x3:newtls, x4:childtid. */
|
||||
svc 0x0
|
||||
cfi_endproc
|
||||
cmp x0, #0
|
||||
beq 2f
|
||||
blt 3f
|
||||
@@ -72,6 +73,9 @@ ENTRY(__clone)
|
||||
b syscall_error
|
||||
|
||||
2:
|
||||
cfi_startproc
|
||||
cfi_undefined (x30)
|
||||
mov x29, 0
|
||||
#ifdef RESET_PID
|
||||
tbnz x5, #CLONE_THREAD_BIT, 3f
|
||||
mov x0, #-1
|
||||
@@ -93,7 +97,8 @@ ENTRY(__clone)
|
||||
|
||||
/* We are done, pass the return value through x0. */
|
||||
b HIDDEN_JUMPTARGET(_exit)
|
||||
|
||||
cfi_endproc
|
||||
cfi_startproc
|
||||
PSEUDO_END (__clone)
|
||||
|
||||
weak_alias (__clone, clone)
|
||||
|
||||
@@ -83,14 +83,21 @@ PSEUDO_END(__syscall_rt_sigaction)
|
||||
cfi_offset (64, \base + 2 * 8)
|
||||
.endm
|
||||
|
||||
.align 4
|
||||
|
||||
cfi_startproc
|
||||
cfi_return_column (64)
|
||||
.cfi_signal_frame
|
||||
SIGCONTEXT_REGS -648
|
||||
|
||||
cfi_def_cfa_offset (648)
|
||||
|
||||
/* While this frame is marked as a signal frame, that only applies
|
||||
to how this return address is handled for the outer frame.
|
||||
The return address that arrived here, from the inner frame, is
|
||||
not marked as a signal frame and so the unwinder still tries to
|
||||
subtract 1 to examine the presumed call insn. Thus we must
|
||||
extend the unwind info to a nop before the start. */
|
||||
nop
|
||||
.align 4
|
||||
|
||||
__syscall_sigreturn:
|
||||
mov sp, a0
|
||||
ldi v0, __NR_sigreturn
|
||||
@@ -98,8 +105,11 @@ __syscall_sigreturn:
|
||||
.size __syscall_sigreturn, .-__syscall_sigreturn
|
||||
.type __syscall_sigreturn, @function
|
||||
|
||||
.align 4
|
||||
/* See above wrt including the nop. */
|
||||
cfi_def_cfa_offset (176 + 648)
|
||||
nop
|
||||
.align 4
|
||||
|
||||
__syscall_rt_sigreturn:
|
||||
mov sp,a0
|
||||
ldi v0,__NR_rt_sigreturn
|
||||
|
||||
@@ -93,8 +93,8 @@ PSEUDO_END (__clone)
|
||||
mov lr, pc
|
||||
bx ip
|
||||
#else
|
||||
mov lr, pc
|
||||
ldr pc, [sp], #8
|
||||
ldr lr, [sp], #8
|
||||
blx lr
|
||||
#endif
|
||||
|
||||
@ and we are done, passing the return value through r0
|
||||
|
||||
@@ -951,14 +951,13 @@ FCT (pattern, string, string_end, no_leading_period, flags, ends, alloca_used)
|
||||
}
|
||||
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;
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
/* Test for fnmatch not reading past the end of the pattern.
|
||||
Copyright (C) 2014-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 <fnmatch.h>
|
||||
|
||||
int
|
||||
do_test (void)
|
||||
{
|
||||
if (fnmatch ("[[:alpha:]'[:alpha:]\0]", "a", 0) != FNM_NOMATCH)
|
||||
return 1;
|
||||
if (fnmatch ("[a[.\0.]]", "a", 0) != FNM_NOMATCH)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define TEST_FUNCTION do_test ()
|
||||
#include "../test-skeleton.c"
|
||||
+109
-2
@@ -1049,7 +1049,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 +1229,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 +1250,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 +1360,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;
|
||||
|
||||
@@ -391,6 +391,7 @@ __libc_res_nsearch(res_state statp,
|
||||
{
|
||||
free (*answerp2);
|
||||
*answerp2 = NULL;
|
||||
*nanswerp2 = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -431,6 +432,7 @@ __libc_res_nsearch(res_state statp,
|
||||
{
|
||||
free (*answerp2);
|
||||
*answerp2 = NULL;
|
||||
*nanswerp2 = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -502,6 +504,7 @@ __libc_res_nsearch(res_state statp,
|
||||
{
|
||||
free (*answerp2);
|
||||
*answerp2 = NULL;
|
||||
*nanswerp2 = 0;
|
||||
}
|
||||
if (saved_herrno != -1)
|
||||
RES_SET_H_ERRNO(statp, saved_herrno);
|
||||
|
||||
+242
-84
@@ -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.
|
||||
@@ -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);
|
||||
@@ -652,6 +671,89 @@ 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 field TC will bet set to 1, indicating a truncated
|
||||
message and the rest of the socket data will be read and discarded.
|
||||
|
||||
Answers to the query are stored secondly in *ANSP2 up to a max of
|
||||
*ANSSIZP2 bytes, with the actual response length stored in
|
||||
*RESPLEN2. If more than *ANSSIZP bytes are needed and ANSP2
|
||||
is non-NULL (required for a second query) then malloc is used to
|
||||
allocate a new response buffer, *ANSSIZP2 is set to the new buffer
|
||||
size and *ANSP2_MALLOCED is set to 1.
|
||||
|
||||
The ANSP2_MALLOCED argument will eventually be removed as the
|
||||
change in buffer pointer can be used to detect the buffer has
|
||||
changed and that the caller should use free on the new buffer.
|
||||
|
||||
Note that the answers may arrive in any order from the server and
|
||||
therefore the first and second answer buffers may not correspond to
|
||||
the first and second queries.
|
||||
|
||||
It is not supported to call this function with a non-NULL ANSP2
|
||||
but a NULL ANSCP. Put another way, you can call send_vc with a
|
||||
single unmodifiable buffer or two modifiable buffers, but no other
|
||||
combination is supported.
|
||||
|
||||
It is the caller's responsibility to free the malloc allocated
|
||||
buffers by detecting that the pointers have changed from their
|
||||
original values i.e. *ANSCP or *ANSP2 has changed.
|
||||
|
||||
If errors are encountered then *TERRNO is set to an appropriate
|
||||
errno value and a zero result is returned for a recoverable error,
|
||||
and a less-than zero result is returned for a non-recoverable error.
|
||||
|
||||
If no errors are encountered then *TERRNO is left unmodified and
|
||||
a the length of the first response in bytes is returned. */
|
||||
static int
|
||||
send_vc(res_state statp,
|
||||
const u_char *buf, int buflen, const u_char *buf2, int buflen2,
|
||||
@@ -661,11 +763,7 @@ send_vc(res_state statp,
|
||||
{
|
||||
const HEADER *hp = (HEADER *) buf;
|
||||
const HEADER *hp2 = (HEADER *) buf2;
|
||||
u_char *ans = *ansp;
|
||||
int orig_anssizp = *anssizp;
|
||||
// XXX REMOVE
|
||||
// int anssiz = *anssizp;
|
||||
HEADER *anhp = (HEADER *) ans;
|
||||
HEADER *anhp = (HEADER *) *ansp;
|
||||
struct sockaddr_in6 *nsap = EXT(statp).nsaddrs[ns];
|
||||
int truncating, connreset, resplen, n;
|
||||
struct iovec iov[4];
|
||||
@@ -741,6 +839,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 +877,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 +892,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 not the the static
|
||||
user-supplied buffer then we can reallocate
|
||||
it. */
|
||||
if (thisansp != NULL && thisansp != ansp) {
|
||||
/* Always allocate MAXPACKET, callers expect
|
||||
this specific size. */
|
||||
u_char *newp = malloc (MAXPACKET);
|
||||
if (newp == NULL) {
|
||||
*terrno = ENOMEM;
|
||||
@@ -824,6 +909,9 @@ send_vc(res_state statp,
|
||||
*thisanssizp = MAXPACKET;
|
||||
*thisansp = newp;
|
||||
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,6 +1075,66 @@ reopen (res_state statp, int *terrno, int ns)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* The send_dg function is responsible for sending a DNS query over UDP
|
||||
to the nameserver numbered NS from the res_state STATP i.e.
|
||||
EXT(statp).nssocks[ns]. The function supports IPv4 and IPv6 queries
|
||||
along with the ability to send the query in parallel for both stacks
|
||||
(default) or serially (RES_SINGLKUP). It also supports serial lookup
|
||||
with a close and reopen of the socket used to talk to the server
|
||||
(RES_SNGLKUPREOP) to work around broken name servers.
|
||||
|
||||
The query stored in BUF of BUFLEN length is sent first followed by
|
||||
the query stored in BUF2 of BUFLEN2 length. Queries are sent
|
||||
in parallel (default) or serially (RES_SINGLKUP or RES_SNGLKUPREOP).
|
||||
|
||||
Answers to the query are stored firstly in *ANSP up to a max of
|
||||
*ANSSIZP bytes. If more than *ANSSIZP bytes are needed and ANSCP
|
||||
is non-NULL (to indicate that modifying the answer buffer is allowed)
|
||||
then malloc is used to allocate a new response buffer and ANSCP and
|
||||
ANSP will both point to the new buffer. If more than *ANSSIZP bytes
|
||||
are needed but ANSCP is NULL, then as much of the response as
|
||||
possible is read into the buffer, but the results will be truncated.
|
||||
When truncation happens because of a small answer buffer the DNS
|
||||
packets header field TC will bet set to 1, indicating a truncated
|
||||
message, while the rest of the UDP packet is discarded.
|
||||
|
||||
Answers to the query are stored secondly in *ANSP2 up to a max of
|
||||
*ANSSIZP2 bytes, with the actual response length stored in
|
||||
*RESPLEN2. If more than *ANSSIZP bytes are needed and ANSP2
|
||||
is non-NULL (required for a second query) then malloc is used to
|
||||
allocate a new response buffer, *ANSSIZP2 is set to the new buffer
|
||||
size and *ANSP2_MALLOCED is set to 1.
|
||||
|
||||
The ANSP2_MALLOCED argument will eventually be removed as the
|
||||
change in buffer pointer can be used to detect the buffer has
|
||||
changed and that the caller should use free on the new buffer.
|
||||
|
||||
Note that the answers may arrive in any order from the server and
|
||||
therefore the first and second answer buffers may not correspond to
|
||||
the first and second queries.
|
||||
|
||||
It is not supported to call this function with a non-NULL ANSP2
|
||||
but a NULL ANSCP. Put another way, you can call send_vc with a
|
||||
single unmodifiable buffer or two modifiable buffers, but no other
|
||||
combination is supported.
|
||||
|
||||
It is the caller's responsibility to free the malloc allocated
|
||||
buffers by detecting that the pointers have changed from their
|
||||
original values i.e. *ANSCP or *ANSP2 has changed.
|
||||
|
||||
If an answer is truncated because of UDP datagram DNS limits then
|
||||
*V_CIRCUIT is set to 1 and the return value non-zero to indicate to
|
||||
the caller to retry with TCP. The value *GOTSOMEWHERE is set to 1
|
||||
if any progress was made reading a response from the nameserver and
|
||||
is used by the caller to distinguish between ECONNREFUSED and
|
||||
ETIMEDOUT (the latter if *GOTSOMEWHERE is 1).
|
||||
|
||||
If errors are encountered then *TERRNO is set to an appropriate
|
||||
errno value and a zero result is returned for a recoverable error,
|
||||
and a less-than zero result is returned for a non-recoverable error.
|
||||
|
||||
If no errors are encountered then *TERRNO is left unmodified and
|
||||
a the length of the first response in bytes is returned. */
|
||||
static int
|
||||
send_dg(res_state statp,
|
||||
const u_char *buf, int buflen, const u_char *buf2, int buflen2,
|
||||
@@ -996,8 +1144,6 @@ send_dg(res_state statp,
|
||||
{
|
||||
const HEADER *hp = (HEADER *) buf;
|
||||
const HEADER *hp2 = (HEADER *) buf2;
|
||||
u_char *ans = *ansp;
|
||||
int orig_anssizp = *anssizp;
|
||||
struct timespec now, timeout, finish;
|
||||
struct pollfd pfd[1];
|
||||
int ptimeout;
|
||||
@@ -1022,7 +1168,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 +1180,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 +1192,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 +1239,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 +1309,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 +1327,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,50 +1343,54 @@ 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 not the the static
|
||||
user-supplied buffer then we can reallocate
|
||||
it. */
|
||||
&& (thisansp != NULL && thisansp != ansp)
|
||||
#ifdef FIONREAD
|
||||
/* Is the size too small? */
|
||||
&& (ioctl (pfd[0].fd, FIONREAD, thisresplenp) < 0
|
||||
|| *thisanssizp < *thisresplenp)) {
|
||||
|| *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;
|
||||
}
|
||||
}
|
||||
/* 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);
|
||||
@@ -1249,7 +1403,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)) {
|
||||
@@ -1260,7 +1414,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)) {
|
||||
@@ -1309,7 +1463,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)
|
||||
@@ -1361,10 +1515,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) {
|
||||
@@ -1386,6 +1540,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. */
|
||||
@@ -1401,20 +1557,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 ();
|
||||
|
||||
@@ -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));
|
||||
|
||||
|
||||
+403
-96
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -589,9 +589,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
|
||||
|
||||
@@ -30,7 +30,8 @@ ENTRY(__fdim)
|
||||
fbug 1f
|
||||
st %g0, [%sp + 76]
|
||||
ldd [%sp + 72], %f0
|
||||
fnegd %f0, %f2
|
||||
fnegs %f0, %f2
|
||||
fmovs %f1, %f3
|
||||
1: retl
|
||||
fsubd %f0, %f2, %f0
|
||||
END(__fdim)
|
||||
|
||||
@@ -42,7 +42,7 @@ ENTRY(__mpn_add_n)
|
||||
sethi %gdop_hix22(__mpn_add_n_generic), %o1
|
||||
xor %o1, %gdop_lox10(__mpn_add_n_generic), %o1
|
||||
# else
|
||||
set __mpn_add_n_vis3, %o1
|
||||
set __mpn_add_n_generic, %o1
|
||||
# endif
|
||||
10:
|
||||
# ifdef SHARED
|
||||
|
||||
@@ -42,7 +42,7 @@ ENTRY(__mpn_addmul_1)
|
||||
sethi %gdop_hix22(__mpn_addmul_1_generic), %o1
|
||||
xor %o1, %gdop_lox10(__mpn_addmul_1_generic), %o1
|
||||
# else
|
||||
set __mpn_addmul_1_vis3, %o1
|
||||
set __mpn_addmul_1_generic, %o1
|
||||
# endif
|
||||
10:
|
||||
# ifdef SHARED
|
||||
|
||||
@@ -211,6 +211,7 @@ ENTRY(__memcpy_niagara2)
|
||||
*/
|
||||
VISEntryHalf
|
||||
|
||||
membar #Sync
|
||||
alignaddr %o1, %g0, %g0
|
||||
|
||||
add %o1, (64 - 1), %o4
|
||||
|
||||
@@ -42,7 +42,7 @@ ENTRY(__mpn_mul_1)
|
||||
sethi %gdop_hix22(__mpn_mul_1_generic), %o1
|
||||
xor %o1, %gdop_lox10(__mpn_mul_1_generic), %o1
|
||||
# else
|
||||
set __mpn_mul_1_vis3, %o1
|
||||
set __mpn_mul_1_generic, %o1
|
||||
# endif
|
||||
10:
|
||||
# ifdef SHARED
|
||||
|
||||
@@ -42,7 +42,7 @@ ENTRY(__mpn_sub_n)
|
||||
sethi %gdop_hix22(__mpn_sub_n_generic), %o1
|
||||
xor %o1, %gdop_lox10(__mpn_sub_n_generic), %o1
|
||||
# else
|
||||
set __mpn_sub_n_vis3, %o1
|
||||
set __mpn_sub_n_generic, %o1
|
||||
# endif
|
||||
10:
|
||||
# ifdef SHARED
|
||||
|
||||
@@ -42,7 +42,7 @@ ENTRY(__mpn_submul_1)
|
||||
sethi %gdop_hix22(__mpn_submul_1_generic), %o1
|
||||
xor %o1, %gdop_lox10(__mpn_submul_1_generic), %o1
|
||||
# else
|
||||
set __mpn_submul_1_vis3, %o1
|
||||
set __mpn_submul_1_generic, %o1
|
||||
# endif
|
||||
10:
|
||||
# ifdef SHARED
|
||||
|
||||
@@ -121,6 +121,37 @@ ENTRY(strcmp)
|
||||
movleu %xcc, -1, %o0
|
||||
srlx rTMP1, 7, rTMP1
|
||||
|
||||
/* In order not to be influenced by bytes after the zero byte, we
|
||||
* have to retain only the highest bit in the mask for the comparison
|
||||
* with rSTRXOR to work properly.
|
||||
*/
|
||||
mov 0, rTMP2
|
||||
andcc rTMP1, 0x0100, %g0
|
||||
|
||||
movne %xcc, 8, rTMP2
|
||||
sllx rTMP1, 63 - 16, %o1
|
||||
|
||||
movrlz %o1, 16, rTMP2
|
||||
sllx rTMP1, 63 - 24, %o1
|
||||
|
||||
movrlz %o1, 24, rTMP2
|
||||
sllx rTMP1, 63 - 32, %o1
|
||||
|
||||
movrlz %o1, 32, rTMP2
|
||||
sllx rTMP1, 63 - 40, %o1
|
||||
|
||||
movrlz %o1, 40, rTMP2
|
||||
sllx rTMP1, 63 - 48, %o1
|
||||
|
||||
movrlz %o1, 48, rTMP2
|
||||
sllx rTMP1, 63 - 56, %o1
|
||||
|
||||
movrlz %o1, 56, rTMP2
|
||||
|
||||
srlx rTMP1, rTMP2, rTMP1
|
||||
|
||||
sllx rTMP1, rTMP2, rTMP1
|
||||
|
||||
cmp rTMP1, rSTRXOR
|
||||
retl
|
||||
movgu %xcc, 0, %o0
|
||||
|
||||
@@ -22,6 +22,8 @@
|
||||
/* Flags for eventfd. */
|
||||
enum
|
||||
{
|
||||
EFD_SEMAPHORE = 0x000001,
|
||||
#define EFD_SEMAPHORE EFD_SEMAPHORE
|
||||
EFD_CLOEXEC = 0x400000,
|
||||
#define EFD_CLOEXEC EFD_CLOEXEC
|
||||
EFD_NONBLOCK = 0x004000
|
||||
|
||||
@@ -252,3 +252,30 @@ enum __priority_which
|
||||
PRIO_USER = 2 /* WHO is a user ID. */
|
||||
#define PRIO_USER PRIO_USER
|
||||
};
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
#ifdef __USE_GNU
|
||||
/* Modify and return resource limits of a process atomically. */
|
||||
# ifndef __USE_FILE_OFFSET64
|
||||
extern int prlimit (__pid_t __pid, enum __rlimit_resource __resource,
|
||||
const struct rlimit *__new_limit,
|
||||
struct rlimit *__old_limit) __THROW;
|
||||
# else
|
||||
# ifdef __REDIRECT_NTH
|
||||
extern int __REDIRECT_NTH (prlimit, (__pid_t __pid,
|
||||
enum __rlimit_resource __resource,
|
||||
const struct rlimit *__new_limit,
|
||||
struct rlimit *__old_limit), prlimit64);
|
||||
# else
|
||||
# define prlimit prlimit64
|
||||
# endif
|
||||
# endif
|
||||
# ifdef __USE_LARGEFILE64
|
||||
extern int prlimit64 (__pid_t __pid, enum __rlimit_resource __resource,
|
||||
const struct rlimit64 *__new_limit,
|
||||
struct rlimit64 *__old_limit) __THROW;
|
||||
# endif
|
||||
#endif
|
||||
|
||||
__END_DECLS
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Inline math functions for i387 and SSE.
|
||||
Copyright (C) 1995-2013 Free Software Foundation, Inc.
|
||||
Copyright (C) 1995-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
|
||||
@@ -384,7 +384,7 @@ __END_NAMESPACE_C99
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef __x86_64__
|
||||
#ifndef __SSE2_MATH__
|
||||
# if ((!defined __NO_MATH_INLINES || defined __LIBC_INTERNAL_MATH_INLINES) \
|
||||
&& defined __OPTIMIZE__)
|
||||
|
||||
@@ -970,4 +970,4 @@ __inline_mathcode2 (__ieee754_atan2, __y, __x,
|
||||
return __value;)
|
||||
# endif
|
||||
|
||||
#endif /* !__x86_64__ */
|
||||
#endif /* !__SSE2_MATH__ */
|
||||
|
||||
@@ -1 +1 @@
|
||||
/* Fortunately nothing to do. */
|
||||
#include <sysdeps/generic/symbol-hacks.h>
|
||||
|
||||
Reference in New Issue
Block a user