mirror of
git://sourceware.org/git/glibc.git
synced 2026-09-10 12:05:30 +08:00
Compare commits
41
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
916ef0f696 | ||
|
|
afc4daae04 | ||
|
|
c5bbc09ccc | ||
|
|
902072efdb | ||
|
|
03e3ee42d6 | ||
|
|
3822125d1c | ||
|
|
75cf90eb20 | ||
|
|
1029487ab3 | ||
|
|
edbab2450a | ||
|
|
ee35f1cb54 | ||
|
|
57d1664a03 | ||
|
|
4cf2b4e80a | ||
|
|
4b7ba5b8c4 | ||
|
|
3058f7487e | ||
|
|
66cdb5b20d | ||
|
|
7af8c37714 | ||
|
|
adba20cf74 | ||
|
|
d5a4840c6b | ||
|
|
eda498975d | ||
|
|
6ef92b982a | ||
|
|
d5ef25a8d8 | ||
|
|
9f108bbbeb | ||
|
|
ed99e5f9cc | ||
|
|
4d54424420 | ||
|
|
1bf9d48aec | ||
|
|
f9e0f439b7 | ||
|
|
b0694b9e98 | ||
|
|
f80af76648 | ||
|
|
a3a1f4163c | ||
|
|
d73ac1bb43 | ||
|
|
33ceaf6187 | ||
|
|
e42643491c | ||
|
|
c14e752fc7 | ||
|
|
1b198b7fc7 | ||
|
|
2930c79afa | ||
|
|
4adf2992ac | ||
|
|
d2c37d028d | ||
|
|
979add9f87 | ||
|
|
ea55092372 | ||
|
|
3b01690892 | ||
|
|
b735a759ef |
@@ -1,3 +1,417 @@
|
||||
2016-05-24 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-05-24 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.
|
||||
|
||||
2016-05-24 Florian Weimer <fweimer@redhat.com>
|
||||
|
||||
* misc/bug18240.c (do_test): Set RLIMIT_AS.
|
||||
|
||||
2016-05-24 Paul Eggert <eggert@cs.ucla.edu>
|
||||
|
||||
[BZ #18240]
|
||||
* misc/hsearch_r.c (isprime, __hcreate_r): Protect against
|
||||
unsigned int wraparound.
|
||||
|
||||
2016-05-24 Florian Weimer <fweimer@redhat.com>
|
||||
|
||||
[BZ #18240]
|
||||
* misc/bug18240.c: New test.
|
||||
* misc/Makefile (tests): Add it.
|
||||
|
||||
2016-05-24 Ondřej Bílka <neleai@seznam.cz>
|
||||
|
||||
* debug/strcpy_chk.c: Improve performance.
|
||||
* debug/stpcpy_chk.c: Likewise.
|
||||
* sysdeps/x86_64/strcpy_chk.S: Remove.
|
||||
* sysdeps/x86_64/stpcpy_chk.S: Remove.
|
||||
|
||||
[BZ #18240]
|
||||
* misc/hsearch_r.c (__hcreate_r): Handle overflow.
|
||||
|
||||
2016-05-24 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-05-24 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-05-24 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-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-09 Mike Frysinger <vapier@gentoo.org>
|
||||
|
||||
* sysdeps/x86_64/configure.ac: Change == to = when calling test.
|
||||
* sysdeps/x86_64/configure: Likewise.
|
||||
|
||||
2016-04-04 Stefan Liebler <stli@linux.vnet.ibm.com>
|
||||
|
||||
* sysdeps/s390/bits/link.h: (La_s390_vr) New typedef.
|
||||
(La_s390_32_regs): Append vector register lr_v24-lr_v31.
|
||||
(La_s390_64_regs): Likewise.
|
||||
(La_s390_32_retval): Append vector register lrv_v24.
|
||||
(La_s390_64_retval): Likeweise.
|
||||
* sysdeps/s390/s390-32/dl-trampoline.h (_dl_runtime_profile):
|
||||
Handle extended structs La_s390_32_regs and La_s390_32_retval.
|
||||
* sysdeps/s390/s390-64/dl-trampoline.h (_dl_runtime_profile):
|
||||
Handle extended structs La_s390_64_regs and La_s390_64_retval.
|
||||
|
||||
2016-04-04 Stefan Liebler <stli@linux.vnet.ibm.com>
|
||||
|
||||
* sysdeps/s390/s390-32/dl-trampoline.S: Include dl-trampoline.h twice
|
||||
to create a non-vector/vector version for _dl_runtime_resolve and
|
||||
_dl_runtime_profile. Move implementation to ...
|
||||
* sysdeps/s390/s390-32/dl-trampoline.h: ... here.
|
||||
(_dl_runtime_resolve) Save and restore fpr/vrs.
|
||||
(_dl_runtime_profile) Save and restore vrs and fix some issues
|
||||
if _dl_call_pltexit is called.
|
||||
* sysdeps/s390/s390-32/dl-machine.h (elf_machine_runtime_setup):
|
||||
Choose the correct resolver function if running on a machine with vx.
|
||||
* sysdeps/s390/s390-64/dl-trampoline.S: Include dl-trampoline.h twice
|
||||
to create a non-vector/vector version for _dl_runtime_resolve and
|
||||
_dl_runtime_profile. Move implementation to ...
|
||||
* sysdeps/s390/s390-64/dl-trampoline.h: ... here.
|
||||
(_dl_runtime_resolve) Save and restore fpr/vrs.
|
||||
(_dl_runtime_profile) Save and restore vrs and fix some issues
|
||||
* sysdeps/s390/s390-64/dl-machine.h: (elf_machine_runtime_setup):
|
||||
Choose the correct resolver function if running on a machine with vx.
|
||||
|
||||
2016-04-04 Stefan Liebler <stli@linux.vnet.ibm.com>
|
||||
|
||||
* config.h.in (HAVE_S390_VX_ASM_SUPPORT): New macro undefine.
|
||||
* sysdeps/s390/configure.ac: Add test for S390 vector instruction
|
||||
assembler support.
|
||||
* sysdeps/s390/configure: Regenerated.
|
||||
|
||||
2016-04-04 Stefan Liebler <stli@linux.vnet.ibm.com>
|
||||
|
||||
* sysdeps/s390/dl-procinfo.c (_dl_s390_cap_flags): Add z13.
|
||||
* sysdeps/s390/dl-procinfo.h (_DL_PLATFORMS_COUNT): Increased.
|
||||
|
||||
2016-04-04 Stefan Liebler <stli@linux.vnet.ibm.com>
|
||||
|
||||
* sysdeps/s390/dl-procinfo.c (_dl_s390_platforms): Add vector flag.
|
||||
* sysdeps/s390/dl-procinfo.h: Add vector capability.
|
||||
* sysdeps/unix/sysv/linux/s390/bits/hwcap.h (HWCAP_S390_VX): Define.
|
||||
|
||||
2016-03-02 Stefan Liebler <stli@linux.vnet.ibm.com>
|
||||
|
||||
[BZ #19682]
|
||||
* sysdeps/unix/sysv/linux/s390/s390-64/syscalls.list:
|
||||
Remove socketcall syscalls.
|
||||
|
||||
2016-02-25 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-02-25 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.
|
||||
|
||||
2016-02-25 Paul Pluzhnikov <ppluzhnikov@google.com>
|
||||
|
||||
[BZ #17269]
|
||||
* libio/wstrops.c (_IO_wstr_overflow): Guard against integer overflow
|
||||
(enlarge_userbuf): Likewise.
|
||||
|
||||
2016-02-25 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-02-25 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.
|
||||
|
||||
2015-07-21 Mike Frysinger <vapier@gentoo.org>
|
||||
|
||||
[BZ #18694]
|
||||
* sysdeps/unix/sysv/linux/sparc/bits/sigaction.h: Include
|
||||
bits/wordsize.h.
|
||||
(sigaction): Declare __glibc_reserved0 only when __WORDSIZE is 64.
|
||||
|
||||
2015-02-16 Paul Pluzhnikov <ppluzhnikov@google.com>
|
||||
|
||||
[BZ #16618]
|
||||
* stdio-common/tst-sscanf.c (main): Test for buffer overflow.
|
||||
* stdio-common/vfscanf.c (_IO_vfscanf_internal): Compute needed
|
||||
size in bytes. Store needed elements in wpmax. Use needed size
|
||||
in bytes for extend_alloca.
|
||||
|
||||
2015-02-16 H.J. Lu <hongjiu.lu@intel.com>
|
||||
|
||||
[BZ #17801]
|
||||
* sysdeps/x86_64/multiarch/init-arch.c (__init_cpu_features):
|
||||
Set the bit_AVX_Fast_Unaligned_Load bit for AVX2.
|
||||
* sysdeps/x86_64/multiarch/init-arch.h (bit_AVX_Fast_Unaligned_Load):
|
||||
New.
|
||||
(index_AVX_Fast_Unaligned_Load): Likewise.
|
||||
(HAS_AVX_FAST_UNALIGNED_LOAD): Likewise.
|
||||
* sysdeps/x86_64/multiarch/memcpy.S (__new_memcpy): Check the
|
||||
bit_AVX_Fast_Unaligned_Load bit instead of the bit_AVX_Usable bit.
|
||||
* sysdeps/x86_64/multiarch/memcpy_chk.S (__memcpy_chk): Likewise.
|
||||
* sysdeps/x86_64/multiarch/mempcpy.S (__mempcpy): Likewise.
|
||||
* sysdeps/x86_64/multiarch/mempcpy_chk.S (__mempcpy_chk): Likewise.
|
||||
* sysdeps/x86_64/multiarch/memmove.c (__libc_memmove): Replace
|
||||
HAS_AVX with HAS_AVX_FAST_UNALIGNED_LOAD.
|
||||
* sysdeps/x86_64/multiarch/memmove_chk.c (__memmove_chk): Likewise.
|
||||
|
||||
2015-02-16 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-02-16 Kostya Serebryany <konstantin.s.serebryany@gmail.com>
|
||||
Roland McGrath <roland@hack.frob.com>
|
||||
|
||||
* locale/weight.h: Add include guard.
|
||||
(findidx): Make static rather than auto; take new parameters
|
||||
TABLE, INDIRECT, and EXTRA instead of getting them as outer locals.
|
||||
* locale/weightwc.h: Likewise.
|
||||
* posix/fnmatch_loop.c
|
||||
(FCT): Change type of EXTRA from int32_t to wint_t.
|
||||
Don't include either header inside the function.
|
||||
Call FINDIDX rather than findidx, and pass new arguments.
|
||||
#undef FINDIDX at the end of the file.
|
||||
* posix/fnmatch.c [_LIBC]: #include <locale/weight.h> and define
|
||||
FINDIDX before including fnmatch_loop.c for the non-wide version.
|
||||
[_LIBC] [HANDLE_MULTIBYTE]: #define findidx to findidxwc around
|
||||
#include <locale/weightwc.h>, and define FINDIDX to findidxwc
|
||||
for the wide version.
|
||||
* posix/regcomp.c [_LIBC]: #include <locale/weight.h>.
|
||||
(build_equiv_class) [_LIBC]: Don't #include it inside the function.
|
||||
Pass new arguments to findidx.
|
||||
* posix/regexec.c [RE_ENABLE_I18N] [_LIBC]: #include <locale/weight.h>.
|
||||
[RE_ENABLE_I18N] (check_node_accept_bytes) [_LIBC]:
|
||||
Don't #include it inside the function. Pass new arguments to findidx.
|
||||
* posix/regex_internal.h
|
||||
[!NOT_IN_libc] [_LIBC]: #include <locale/weight.h>.
|
||||
(re_string_elem_size_at): Don't #include it inside the function.
|
||||
Pass new arguments to findidx.
|
||||
* string/strcoll_l.c: #include WEIGHT_H at top level.
|
||||
(get_next_seq): Don't #include it inside the function.
|
||||
Pass new arguments to findidx.
|
||||
(get_next_seq_nocache): Likewise.
|
||||
* string/strxfrm_l.c: #include WEIGHT_H at top level.
|
||||
(STRXFRM): Don't #include it inside the function.
|
||||
Pass new arguments to findidx.
|
||||
|
||||
2014-12-16 Florian Weimer <fweimer@redhat.com>
|
||||
|
||||
[BZ #17630]
|
||||
* resolv/nss_dns/dns-network.c (getanswer_r): Iterate over alias
|
||||
names.
|
||||
|
||||
2014-12-15 Jeff Law <law@redhat.com>
|
||||
|
||||
[BZ #16617]
|
||||
* stdio-common/vfprintf.c (vfprintf): Allocate large specs array
|
||||
on the heap. (CVE-2012-3406)
|
||||
* stdio-common/bug23-2.c, stdio-common/bug23-3.c: New file.
|
||||
* stdio-common/bug23-4.c: New file. Test case by Joseph Myers.
|
||||
* stdio-common/Makefile (tests): Add bug23-2, bug23-3, bug23-4.
|
||||
|
||||
2014-11-24 Siddhesh Poyarekar <siddhesh@redhat.com>
|
||||
|
||||
[BZ #17266]
|
||||
* misc/sys/cdefs.h: Define __extern_always_inline for clang
|
||||
4.2 and newer.
|
||||
|
||||
2014-11-19 Carlos O'Donell <carlos@redhat.com>
|
||||
Florian Weimer <fweimer@redhat.com>
|
||||
Joseph Myers <joseph@codesourcery.com>
|
||||
Adam Conrad <adconrad@0c3.net>
|
||||
Andreas Schwab <schwab@suse.de>
|
||||
Brooks <bmoses@google.com>
|
||||
|
||||
[BZ #17625]
|
||||
* wordexp-test.c (__dso_handle): Add prototype.
|
||||
(__register_atfork): Likewise.
|
||||
(__app_register_atfork): New function.
|
||||
(registered_forks): New global.
|
||||
(register_fork): New function.
|
||||
(test_case): Add 3 new tests for WRDE_CMDSUB.
|
||||
(main): Call __app_register_atfork.
|
||||
(testit): If WRDE_NOCMD set registered_forks to zero, run test, and if
|
||||
fork count is non-zero fail the test.
|
||||
* posix/wordexp.c (exec_comm): Return WRDE_CMDSUB if WRDE_NOCMD flag
|
||||
is set.
|
||||
(parse_dollars): Remove check for WRDE_NOCMD.
|
||||
(parse_dquote): Likewise.
|
||||
|
||||
2014-11-10 Renlin Li <Renlin.Li@arm.com>
|
||||
|
||||
[BZ #17555]
|
||||
* sysdeps/aarch64/start.S (_start): Delete x29 overwritten assignment.
|
||||
|
||||
2014-10-22 Maciej W. Rozycki <macro@codesourcery.com>
|
||||
|
||||
[BZ #17485]
|
||||
* sysdeps/unix/sysv/linux/mips/vfork.S (__libc_vfork): Define.
|
||||
|
||||
2014-10-08 Roland McGrath <roland@hack.frob.com>
|
||||
|
||||
[BZ #17460]
|
||||
* nscd/nscd.c (more_help): Rewrite list of tables collection
|
||||
using xstrdup and asprintf.
|
||||
|
||||
* nscd/nscd_conf.c: Remove local xstrdup declaration.
|
||||
|
||||
2014-10-09 Allan McRae <allan@archlinux.org>
|
||||
|
||||
* po/fr.po: Update French translation from translation project.
|
||||
|
||||
2014-09-16 Siddhesh Poyarekar <siddhesh@redhat.com>
|
||||
|
||||
[BZ #17370]
|
||||
* libio/wfileops.c (do_ftell_wide): Free OUT on error path.
|
||||
|
||||
2014-09-11 Tim Lammens <tim.lammens@gmail.com>
|
||||
|
||||
[BZ #17370]
|
||||
* libio/wfileops (do_ftell_wide): Free OUT.
|
||||
|
||||
2014-09-16 Siddhesh Poyarekar <siddhesh@redhat.com>
|
||||
Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
[BZ #17266]
|
||||
* libio/stdio.h: Check definition of __fortify_function
|
||||
instead of __extern_always_inline to include bits/stdio2.h.
|
||||
* math/bits/math-finite.h [__USE_XOPEN || __USE_ISOC99]: Also
|
||||
check if __extern_always_inline is defined.
|
||||
[__USE_MISC || __USE_XOPEN]: Likewise.
|
||||
[__USE_ISOC99] Likewise.
|
||||
* misc/sys/cdefs.h (__fortify_function): Define only if
|
||||
__extern_always_inline is defined.
|
||||
[!__cplusplus || __GNUC_PREREQ (4,3)]: Revert to defining
|
||||
__extern_always_inline and __extern_inline only for g++-4.3
|
||||
and newer or a compatible gcc.
|
||||
|
||||
2014-09-15 Andreas Schwab <schwab@linux-m68k.org>
|
||||
|
||||
[BZ #17371]
|
||||
* sysdeps/unix/sysv/linux/ifaddrs.c (getifaddrs_internal): Fix
|
||||
last change to handle zero prefix length.
|
||||
|
||||
2014-09-12 Joseph Myers <joseph@codesourcery.com>
|
||||
|
||||
* sysdeps/gnu/netinet/udp.h (UDP_NO_CHECK6_TX): New macro.
|
||||
(UDP_NO_CHECK6_RX): Likewise.
|
||||
|
||||
2014-09-13 Allan McRae <allan@archlinux.org>
|
||||
|
||||
* po/ru.po: Update Russian translation from translation project.
|
||||
|
||||
2014-09-07 Allan McRae <allan@archlinux.org
|
||||
|
||||
* version.h (RELEASE): Set to "stable".
|
||||
|
||||
@@ -5,6 +5,66 @@ 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.20.1
|
||||
|
||||
* The following bugs are resolved with this release:
|
||||
|
||||
16009, 16617, 16618, 17266, 17269, 17370, 17371, 17460, 17485, 17555,
|
||||
17625, 17630, 17801, 17905, 18032, 18080, 18240, 18508, 18665, 18694,
|
||||
18928, 19018, 19682.
|
||||
|
||||
* 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)
|
||||
|
||||
* An unnecessary stack copy in _nss_dns_getnetbyname_r was removed. It
|
||||
could result in a stack overflow when getnetbyname was called with an
|
||||
overly long name. (CVE-2016-3075)
|
||||
|
||||
* 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 LD_POINTER_GUARD environment variable can no longer be used to
|
||||
disable the pointer guard feature. It is always enabled.
|
||||
|
||||
* CVE-2015-1472 Under certain conditions wscanf can allocate too little
|
||||
memory for the to-be-scanned arguments and overflow the allocated
|
||||
buffer. The implementation now correctly computes the required buffer
|
||||
size when using malloc.
|
||||
|
||||
* CVE-2104-7817 The wordexp function could ignore the WRDE_NOCMD flag
|
||||
under certain input conditions resulting in the execution of a shell for
|
||||
command substitution when the applicaiton did not request it. The
|
||||
implementation now checks WRDE_NOCMD immediately before executing the
|
||||
shell and returns the error WRDE_CMDSUB as expected.
|
||||
|
||||
* CVE-2012-3406 printf-style functions could run into a stack overflow when
|
||||
processing format strings with a large number of format specifiers.
|
||||
|
||||
* CVE-2014-9402 The nss_dns implementation of getnetbyname could run into an
|
||||
infinite loopif the DNS response contained a PTR record of an unexpected
|
||||
format.
|
||||
|
||||
* The 32-bit sparc sigaction ABI was inadvertently broken in the 2.20 release.
|
||||
It has been fixed to match 2.19 and older, but binaries built against 2.20
|
||||
might need to be recompiled. See BZ#18694.
|
||||
|
||||
Version 2.20
|
||||
|
||||
* The following bugs are resolved with this release:
|
||||
|
||||
+8
-1
@@ -34,6 +34,7 @@ test-srcs = test-gencat
|
||||
ifeq ($(run-built-tests),yes)
|
||||
tests-special += $(objpfx)de/libc.cat $(objpfx)test1.cat $(objpfx)test2.cat \
|
||||
$(objpfx)sample.SJIS.cat $(objpfx)test-gencat.out
|
||||
tests-special += $(objpfx)tst-catgets-mem.out
|
||||
endif
|
||||
|
||||
gencat-modules = xmalloc
|
||||
@@ -50,9 +51,11 @@ catgets-CPPFLAGS := -DNLSPATH='"$(msgcatdir)/%L/%N:$(msgcatdir)/%L/LC_MESSAGES/%
|
||||
|
||||
generated += de.msg test1.cat test1.h test2.cat test2.h sample.SJIS.cat \
|
||||
test-gencat.h
|
||||
generated += tst-catgets.mtrace tst-catgets-mem.out
|
||||
|
||||
generated-dirs += de
|
||||
|
||||
tst-catgets-ENV = NLSPATH="$(objpfx)%l/%N.cat" LANG=de
|
||||
tst-catgets-ENV = NLSPATH="$(objpfx)%l/%N.cat" LANG=de MALLOC_TRACE=$(objpfx)tst-catgets.mtrace
|
||||
|
||||
ifeq ($(run-built-tests),yes)
|
||||
# This test just checks whether the program produces any error or not.
|
||||
@@ -86,4 +89,8 @@ $(objpfx)test-gencat.out: test-gencat.sh $(objpfx)test-gencat \
|
||||
$(objpfx)sample.SJIS.cat: sample.SJIS $(objpfx)gencat
|
||||
$(built-program-cmd) -H $(objpfx)test-gencat.h < $(word 1,$^) > $@; \
|
||||
$(evaluate-test)
|
||||
|
||||
$(objpfx)tst-catgets-mem.out: $(objpfx)tst-catgets.out
|
||||
$(common-objpfx)malloc/mtrace $(objpfx)tst-catgets.mtrace > $@; \
|
||||
$(evaluate-test)
|
||||
endif
|
||||
|
||||
+12
-7
@@ -16,7 +16,6 @@
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <alloca.h>
|
||||
#include <errno.h>
|
||||
#include <locale.h>
|
||||
#include <nl_types.h>
|
||||
@@ -35,6 +34,7 @@ catopen (const char *cat_name, int flag)
|
||||
__nl_catd result;
|
||||
const char *env_var = NULL;
|
||||
const char *nlspath = NULL;
|
||||
char *tmp = NULL;
|
||||
|
||||
if (strchr (cat_name, '/') == NULL)
|
||||
{
|
||||
@@ -54,7 +54,10 @@ catopen (const char *cat_name, int flag)
|
||||
{
|
||||
/* Append the system dependent directory. */
|
||||
size_t len = strlen (nlspath) + 1 + sizeof NLSPATH;
|
||||
char *tmp = alloca (len);
|
||||
tmp = malloc (len);
|
||||
|
||||
if (__glibc_unlikely (tmp == NULL))
|
||||
return (nl_catd) -1;
|
||||
|
||||
__stpcpy (__stpcpy (__stpcpy (tmp, nlspath), ":"), NLSPATH);
|
||||
nlspath = tmp;
|
||||
@@ -65,16 +68,18 @@ catopen (const char *cat_name, int flag)
|
||||
|
||||
result = (__nl_catd) malloc (sizeof (*result));
|
||||
if (result == NULL)
|
||||
/* We cannot get enough memory. */
|
||||
return (nl_catd) -1;
|
||||
|
||||
if (__open_catalog (cat_name, nlspath, env_var, result) != 0)
|
||||
{
|
||||
/* We cannot get enough memory. */
|
||||
result = (nl_catd) -1;
|
||||
}
|
||||
else if (__open_catalog (cat_name, nlspath, env_var, result) != 0)
|
||||
{
|
||||
/* Couldn't open the file. */
|
||||
free ((void *) result);
|
||||
return (nl_catd) -1;
|
||||
result = (nl_catd) -1;
|
||||
}
|
||||
|
||||
free (tmp);
|
||||
return (nl_catd) result;
|
||||
}
|
||||
|
||||
|
||||
+14
-9
@@ -47,6 +47,7 @@ __open_catalog (const char *cat_name, const char *nlspath, const char *env_var,
|
||||
size_t tab_size;
|
||||
const char *lastp;
|
||||
int result = -1;
|
||||
char *buf = NULL;
|
||||
|
||||
if (strchr (cat_name, '/') != NULL || nlspath == NULL)
|
||||
fd = open_not_cancel_2 (cat_name, O_RDONLY);
|
||||
@@ -57,23 +58,23 @@ __open_catalog (const char *cat_name, const char *nlspath, const char *env_var,
|
||||
if (__glibc_unlikely (bufact + (n) >= bufmax)) \
|
||||
{ \
|
||||
char *old_buf = buf; \
|
||||
bufmax += 256 + (n); \
|
||||
buf = (char *) alloca (bufmax); \
|
||||
memcpy (buf, old_buf, bufact); \
|
||||
bufmax += (bufmax < 256 + (n)) ? 256 + (n) : bufmax; \
|
||||
buf = realloc (buf, bufmax); \
|
||||
if (__glibc_unlikely (buf == NULL)) \
|
||||
{ \
|
||||
free (old_buf); \
|
||||
return -1; \
|
||||
} \
|
||||
}
|
||||
|
||||
/* The RUN_NLSPATH variable contains a colon separated list of
|
||||
descriptions where we expect to find catalogs. We have to
|
||||
recognize certain % substitutions and stop when we found the
|
||||
first existing file. */
|
||||
char *buf;
|
||||
size_t bufact;
|
||||
size_t bufmax;
|
||||
size_t bufmax = 0;
|
||||
size_t len;
|
||||
|
||||
buf = NULL;
|
||||
bufmax = 0;
|
||||
|
||||
fd = -1;
|
||||
while (*run_nlspath != '\0')
|
||||
{
|
||||
@@ -188,7 +189,10 @@ __open_catalog (const char *cat_name, const char *nlspath, const char *env_var,
|
||||
|
||||
/* Avoid dealing with directories and block devices */
|
||||
if (__builtin_expect (fd, 0) < 0)
|
||||
return -1;
|
||||
{
|
||||
free (buf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (__builtin_expect (__fxstat64 (_STAT_VER, fd, &st), 0) < 0)
|
||||
goto close_unlock_return;
|
||||
@@ -325,6 +329,7 @@ __open_catalog (const char *cat_name, const char *nlspath, const char *env_var,
|
||||
/* Release the lock again. */
|
||||
close_unlock_return:
|
||||
close_not_cancel_no_status (fd);
|
||||
free (buf);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
#include <assert.h>
|
||||
#include <mcheck.h>
|
||||
#include <nl_types.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/resource.h>
|
||||
|
||||
|
||||
static const char *msgs[] =
|
||||
@@ -12,6 +15,33 @@ static const char *msgs[] =
|
||||
};
|
||||
#define nmsgs (sizeof (msgs) / sizeof (msgs[0]))
|
||||
|
||||
|
||||
/* Test for unbounded alloca. */
|
||||
static int
|
||||
do_bz17905 (void)
|
||||
{
|
||||
char *buf;
|
||||
struct rlimit rl;
|
||||
nl_catd result;
|
||||
|
||||
const int sz = 1024 * 1024;
|
||||
|
||||
getrlimit (RLIMIT_STACK, &rl);
|
||||
rl.rlim_cur = sz;
|
||||
setrlimit (RLIMIT_STACK, &rl);
|
||||
|
||||
buf = malloc (sz + 1);
|
||||
memset (buf, 'A', sz);
|
||||
buf[sz] = '\0';
|
||||
setenv ("NLSPATH", buf, 1);
|
||||
|
||||
result = catopen (buf, NL_CAT_LOCALE);
|
||||
assert (result == (nl_catd) -1);
|
||||
|
||||
free (buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define ROUNDS 5
|
||||
|
||||
int
|
||||
@@ -62,5 +92,6 @@ main (void)
|
||||
}
|
||||
}
|
||||
|
||||
result += do_bz17905 ();
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -97,6 +97,9 @@
|
||||
/* Define if assembler supports AVX512. */
|
||||
#undef HAVE_AVX512_ASM_SUPPORT
|
||||
|
||||
/* Define if assembler supports vector instructions on S390. */
|
||||
#undef HAVE_S390_VX_ASM_SUPPORT
|
||||
|
||||
/* Define if assembler supports Intel MPX. */
|
||||
#undef HAVE_MPX_SUPPORT
|
||||
|
||||
|
||||
+4
-11
@@ -162,7 +162,6 @@ struct rtld_global_ro _rtld_global_ro attribute_relro =
|
||||
._dl_hwcap_mask = HWCAP_IMPORTANT,
|
||||
._dl_lazy = 1,
|
||||
._dl_fpu_control = _FPU_DEFAULT,
|
||||
._dl_pointer_guard = 1,
|
||||
._dl_pagesize = EXEC_PAGESIZE,
|
||||
._dl_inhibit_cache = 0,
|
||||
|
||||
@@ -709,15 +708,12 @@ security_init (void)
|
||||
#endif
|
||||
|
||||
/* Set up the pointer guard as well, if necessary. */
|
||||
if (GLRO(dl_pointer_guard))
|
||||
{
|
||||
uintptr_t pointer_chk_guard = _dl_setup_pointer_guard (_dl_random,
|
||||
stack_chk_guard);
|
||||
uintptr_t pointer_chk_guard
|
||||
= _dl_setup_pointer_guard (_dl_random, stack_chk_guard);
|
||||
#ifdef THREAD_SET_POINTER_GUARD
|
||||
THREAD_SET_POINTER_GUARD (pointer_chk_guard);
|
||||
THREAD_SET_POINTER_GUARD (pointer_chk_guard);
|
||||
#endif
|
||||
__pointer_chk_guard_local = pointer_chk_guard;
|
||||
}
|
||||
__pointer_chk_guard_local = pointer_chk_guard;
|
||||
|
||||
/* We do not need the _dl_random value anymore. The less
|
||||
information we leave behind, the better, so clear the
|
||||
@@ -2471,9 +2467,6 @@ process_envvars (enum mode *modep)
|
||||
GLRO(dl_use_load_bias) = envline[14] == '1' ? -1 : 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (memcmp (envline, "POINTER_GUARD", 13) == 0)
|
||||
GLRO(dl_pointer_guard) = envline[14] != '0';
|
||||
break;
|
||||
|
||||
case 14:
|
||||
|
||||
+1
-1
@@ -932,7 +932,7 @@ extern void funlockfile (FILE *__stream) __THROW;
|
||||
#ifdef __USE_EXTERN_INLINES
|
||||
# include <bits/stdio.h>
|
||||
#endif
|
||||
#if __USE_FORTIFY_LEVEL > 0 && defined __extern_always_inline
|
||||
#if __USE_FORTIFY_LEVEL > 0 && defined __fortify_function
|
||||
# include <bits/stdio2.h>
|
||||
#endif
|
||||
#ifdef __LDBL_COMPAT
|
||||
|
||||
+5
-1
@@ -708,9 +708,13 @@ do_ftell_wide (_IO_FILE *fp)
|
||||
sequences must be complete since they are accepted as
|
||||
wchar_t; if not, then that is an error. */
|
||||
if (__glibc_unlikely (status != __codecvt_ok))
|
||||
return WEOF;
|
||||
{
|
||||
free (out);
|
||||
return WEOF;
|
||||
}
|
||||
|
||||
offset += outstop - out;
|
||||
free (out);
|
||||
}
|
||||
|
||||
/* We don't trust _IO_read_end to represent the current file offset
|
||||
|
||||
+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
|
||||
|
||||
+10
-3
@@ -16,10 +16,15 @@
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef _WEIGHT_H_
|
||||
#define _WEIGHT_H_ 1
|
||||
|
||||
/* Find index of weight. */
|
||||
auto inline int32_t
|
||||
__attribute ((always_inline))
|
||||
findidx (const unsigned char **cpp, size_t len)
|
||||
static inline int32_t __attribute__ ((always_inline))
|
||||
findidx (const int32_t *table,
|
||||
const int32_t *indirect,
|
||||
const unsigned char *extra,
|
||||
const unsigned char **cpp, size_t len)
|
||||
{
|
||||
int_fast32_t i = table[*(*cpp)++];
|
||||
const unsigned char *cp;
|
||||
@@ -130,3 +135,5 @@ findidx (const unsigned char **cpp, size_t len)
|
||||
/* NOTREACHED */
|
||||
return 0x43219876;
|
||||
}
|
||||
|
||||
#endif /* weight.h */
|
||||
|
||||
+10
-3
@@ -16,10 +16,15 @@
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef _WEIGHTWC_H_
|
||||
#define _WEIGHTWC_H_ 1
|
||||
|
||||
/* Find index of weight. */
|
||||
auto inline int32_t
|
||||
__attribute ((always_inline))
|
||||
findidx (const wint_t **cpp, size_t len)
|
||||
static inline int32_t __attribute__ ((always_inline))
|
||||
findidx (const int32_t *table,
|
||||
const int32_t *indirect,
|
||||
const wint_t *extra,
|
||||
const wint_t **cpp, size_t len)
|
||||
{
|
||||
wint_t ch = *(*cpp)++;
|
||||
int32_t i = __collidx_table_lookup ((const char *) table, ch);
|
||||
@@ -109,3 +114,5 @@ findidx (const wint_t **cpp, size_t len)
|
||||
/* NOTREACHED */
|
||||
return 0x43219876;
|
||||
}
|
||||
|
||||
#endif /* weightwc.h */
|
||||
|
||||
@@ -53,11 +53,18 @@ 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
|
||||
${test_program_prefix_before_env} \
|
||||
${run_program_env} \
|
||||
LC_ALL=$l ${test_program_prefix_after_env} \
|
||||
${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;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
/* Example for creating a struct dirent object for use with glob.
|
||||
Copyright (C) 2016 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
struct dirent *
|
||||
mkdirent (const char *name)
|
||||
{
|
||||
size_t dirent_size = offsetof (struct dirent, d_name) + 1;
|
||||
size_t name_length = strlen (name);
|
||||
size_t total_size = dirent_size + name_length;
|
||||
if (total_size < dirent_size)
|
||||
{
|
||||
errno = ENOMEM;
|
||||
return NULL;
|
||||
}
|
||||
struct dirent *result = malloc (total_size);
|
||||
if (result == NULL)
|
||||
return NULL;
|
||||
result->d_type = DT_UNKNOWN;
|
||||
result->d_ino = 1; /* Do not skip this entry. */
|
||||
memcpy (result->d_name, name, name_length + 1);
|
||||
return result;
|
||||
}
|
||||
+38
-1
@@ -237,7 +237,44 @@ function used to read the contents of a directory. It is used if the
|
||||
@code{GLOB_ALTDIRFUNC} bit is set in the flag parameter. The type of
|
||||
this field is @w{@code{struct dirent *(*) (void *)}}.
|
||||
|
||||
This is a GNU extension.
|
||||
An implementation of @code{gl_readdir} needs to initialize the following
|
||||
members of the @code{struct dirent} object:
|
||||
|
||||
@table @code
|
||||
@item d_type
|
||||
This member should be set to the file type of the entry if it is known.
|
||||
Otherwise, the value @code{DT_UNKNOWN} can be used. The @code{glob}
|
||||
function may use the specified file type to avoid callbacks in cases
|
||||
where the file type indicates that the data is not required.
|
||||
|
||||
@item d_ino
|
||||
This member needs to be non-zero, otherwise @code{glob} may skip the
|
||||
current entry and call the @code{gl_readdir} callback function again to
|
||||
retrieve another entry.
|
||||
|
||||
@item d_name
|
||||
This member must be set to the name of the entry. It must be
|
||||
null-terminated.
|
||||
@end table
|
||||
|
||||
The example below shows how to allocate a @code{struct dirent} object
|
||||
containing a given name.
|
||||
|
||||
@smallexample
|
||||
@include mkdirent.c.texi
|
||||
@end smallexample
|
||||
|
||||
The @code{glob} function reads the @code{struct dirent} members listed
|
||||
above and makes a copy of the file name in the @code{d_name} member
|
||||
immediately after the @code{gl_readdir} callback function returns.
|
||||
Future invocations of any of the callback functions may dealloacte or
|
||||
reuse the buffer. It is the responsibility of the caller of the
|
||||
@code{glob} function to allocate and deallocate the buffer, around the
|
||||
call to @code{glob} or using the callback functions. For example, an
|
||||
application could allocate the buffer in the @code{gl_readdir} callback
|
||||
function, and deallocate it in the @code{gl_closedir} callback function.
|
||||
|
||||
The @code{gl_readdir} member is a GNU extension.
|
||||
|
||||
@item gl_opendir
|
||||
The address of an alternative implementation of the @code{opendir}
|
||||
|
||||
@@ -251,7 +251,8 @@ extern long double __REDIRECT_NTH (lgammal_r, (long double, int *),
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined __USE_XOPEN || defined __USE_ISOC99
|
||||
#if ((defined __USE_XOPEN || defined __USE_ISOC99) \
|
||||
&& defined __extern_always_inline)
|
||||
/* lgamma. */
|
||||
__extern_always_inline double __NTH (lgamma (double __d))
|
||||
{
|
||||
@@ -284,7 +285,8 @@ __extern_always_inline long double __NTH (lgammal (long double __d))
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined __USE_MISC || defined __USE_XOPEN
|
||||
#if ((defined __USE_MISC || defined __USE_XOPEN) \
|
||||
&& defined __extern_always_inline)
|
||||
/* gamma. */
|
||||
__extern_always_inline double __NTH (gamma (double __d))
|
||||
{
|
||||
@@ -422,7 +424,7 @@ extern long double __REDIRECT_NTH (sqrtl, (long double), __sqrtl_finite);
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef __USE_ISOC99
|
||||
#if defined __USE_ISOC99 && defined __extern_always_inline
|
||||
/* tgamma. */
|
||||
extern double __gamma_r_finite (double, int *);
|
||||
__extern_always_inline double __NTH (tgamma (double __d))
|
||||
|
||||
+2
-1
@@ -76,7 +76,8 @@ install-lib := libg.a
|
||||
gpl2lgpl := error.c error.h
|
||||
|
||||
tests := tst-dirname tst-tsearch tst-fdset tst-efgcvt tst-mntent tst-hsearch \
|
||||
tst-error1 tst-pselect tst-insremque tst-mntent2 bug-hsearch1
|
||||
tst-error1 tst-pselect tst-insremque tst-mntent2 bug-hsearch1 \
|
||||
bug18240
|
||||
ifeq ($(run-built-tests),yes)
|
||||
tests-special += $(objpfx)tst-error1-mem.out
|
||||
endif
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
/* Test integer wraparound in hcreate.
|
||||
Copyright (C) 2016 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <search.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/resource.h>
|
||||
|
||||
static void
|
||||
test_size (size_t size)
|
||||
{
|
||||
int res = hcreate (size);
|
||||
if (res == 0)
|
||||
{
|
||||
if (errno == ENOMEM)
|
||||
return;
|
||||
printf ("error: hcreate (%zu): %m\n", size);
|
||||
exit (1);
|
||||
}
|
||||
char *keys[100];
|
||||
for (int i = 0; i < 100; ++i)
|
||||
{
|
||||
if (asprintf (keys + i, "%d", i) < 0)
|
||||
{
|
||||
printf ("error: asprintf: %m\n");
|
||||
exit (1);
|
||||
}
|
||||
ENTRY e = { keys[i], (char *) "value" };
|
||||
if (hsearch (e, ENTER) == NULL)
|
||||
{
|
||||
printf ("error: hsearch (\"%s\"): %m\n", keys[i]);
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
hdestroy ();
|
||||
|
||||
for (int i = 0; i < 100; ++i)
|
||||
free (keys[i]);
|
||||
}
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
/* Limit the size of the process, so that memory allocation will
|
||||
fail without impacting the entire system. */
|
||||
{
|
||||
struct rlimit limit;
|
||||
if (getrlimit (RLIMIT_AS, &limit) != 0)
|
||||
{
|
||||
printf ("getrlimit (RLIMIT_AS) failed: %m\n");
|
||||
return 1;
|
||||
}
|
||||
long target = 100 * 1024 * 1024;
|
||||
if (limit.rlim_cur == RLIM_INFINITY || limit.rlim_cur > target)
|
||||
{
|
||||
limit.rlim_cur = target;
|
||||
if (setrlimit (RLIMIT_AS, &limit) != 0)
|
||||
{
|
||||
printf ("setrlimit (RLIMIT_AS) failed: %m\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
test_size (500);
|
||||
test_size (-1);
|
||||
test_size (-3);
|
||||
test_size (INT_MAX - 2);
|
||||
test_size (INT_MAX - 1);
|
||||
test_size (INT_MAX);
|
||||
test_size (((unsigned) INT_MAX) + 1);
|
||||
test_size (UINT_MAX - 2);
|
||||
test_size (UINT_MAX - 1);
|
||||
test_size (UINT_MAX);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define TEST_FUNCTION do_test ()
|
||||
#include "../test-skeleton.c"
|
||||
+18
-12
@@ -19,7 +19,7 @@
|
||||
#include <errno.h>
|
||||
#include <malloc.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <search.h>
|
||||
|
||||
/* [Aho,Sethi,Ullman] Compilers: Principles, Techniques and Tools, 1986
|
||||
@@ -46,15 +46,12 @@ static int
|
||||
isprime (unsigned int number)
|
||||
{
|
||||
/* no even number will be passed */
|
||||
unsigned int div = 3;
|
||||
|
||||
while (div * div < number && number % div != 0)
|
||||
div += 2;
|
||||
|
||||
return number % div != 0;
|
||||
for (unsigned int div = 3; div <= number / div; div += 2)
|
||||
if (number % div == 0)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* Before using the hash table we must allocate memory for it.
|
||||
Test for an existing table are done. We allocate one element
|
||||
more as the found prime number says. This is done for more effective
|
||||
@@ -81,10 +78,19 @@ hcreate_r (nel, htab)
|
||||
use will not work. */
|
||||
if (nel < 3)
|
||||
nel = 3;
|
||||
/* Change nel to the first prime number not smaller as nel. */
|
||||
nel |= 1; /* make odd */
|
||||
while (!isprime (nel))
|
||||
nel += 2;
|
||||
|
||||
/* Change nel to the first prime number in the range [nel, UINT_MAX - 2],
|
||||
The '- 2' means 'nel += 2' cannot overflow. */
|
||||
for (nel |= 1; ; nel += 2)
|
||||
{
|
||||
if (UINT_MAX - 2 < nel)
|
||||
{
|
||||
__set_errno (ENOMEM);
|
||||
return 0;
|
||||
}
|
||||
if (isprime (nel))
|
||||
break;
|
||||
}
|
||||
|
||||
htab->size = nel;
|
||||
htab->filled = 0;
|
||||
|
||||
+17
-10
@@ -131,7 +131,6 @@
|
||||
/* Fortify support. */
|
||||
#define __bos(ptr) __builtin_object_size (ptr, __USE_FORTIFY_LEVEL > 1)
|
||||
#define __bos0(ptr) __builtin_object_size (ptr, 0)
|
||||
#define __fortify_function __extern_always_inline __attribute_artificial__
|
||||
|
||||
#if __GNUC_PREREQ (4,3)
|
||||
# define __warndecl(name, msg) \
|
||||
@@ -318,12 +317,19 @@
|
||||
# define __attribute_artificial__ /* Ignore */
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
/* One of these will be defined if the __gnu_inline__ attribute is
|
||||
available. In C++, __GNUC_GNU_INLINE__ will be defined even though
|
||||
__inline does not use the GNU inlining rules. If neither macro is
|
||||
defined, this version of GCC only supports GNU inline semantics. */
|
||||
# if defined __GNUC_STDC_INLINE__ || defined __GNUC_GNU_INLINE__
|
||||
/* GCC 4.3 and above with -std=c99 or -std=gnu99 implements ISO C99
|
||||
inline semantics, unless -fgnu89-inline is used. Using __GNUC_STDC_INLINE__
|
||||
or __GNUC_GNU_INLINE is not a good enough check for gcc because gcc versions
|
||||
older than 4.3 may define these macros and still not guarantee GNU inlining
|
||||
semantics.
|
||||
|
||||
clang++ identifies itself as gcc-4.2, but has support for GNU inlining
|
||||
semantics, that can be checked fot by using the __GNUC_STDC_INLINE_ and
|
||||
__GNUC_GNU_INLINE__ macro definitions. */
|
||||
#if (!defined __cplusplus || __GNUC_PREREQ (4,3) \
|
||||
|| (defined __clang__ && (defined __GNUC_STDC_INLINE__ \
|
||||
|| defined __GNUC_GNU_INLINE__)))
|
||||
# if defined __GNUC_STDC_INLINE__ || defined __cplusplus
|
||||
# define __extern_inline extern __inline __attribute__ ((__gnu_inline__))
|
||||
# define __extern_always_inline \
|
||||
extern __always_inline __attribute__ ((__gnu_inline__))
|
||||
@@ -331,9 +337,10 @@
|
||||
# define __extern_inline extern __inline
|
||||
# define __extern_always_inline extern __always_inline
|
||||
# endif
|
||||
#else /* Not GCC. */
|
||||
# define __extern_inline /* Ignore */
|
||||
# define __extern_always_inline /* Ignore */
|
||||
#endif
|
||||
|
||||
#ifdef __extern_always_inline
|
||||
# define __fortify_function __extern_always_inline __attribute_artificial__
|
||||
#endif
|
||||
|
||||
/* GCC 4.3 and above allow passing all anonymous arguments of an
|
||||
|
||||
+24
-21
@@ -451,33 +451,36 @@ parse_opt (int key, char *arg, struct argp_state *state)
|
||||
static char *
|
||||
more_help (int key, const char *text, void *input)
|
||||
{
|
||||
char *tables, *tp = NULL;
|
||||
|
||||
switch (key)
|
||||
{
|
||||
case ARGP_KEY_HELP_EXTRA:
|
||||
{
|
||||
dbtype cnt;
|
||||
/* We print some extra information. */
|
||||
|
||||
tables = xmalloc (sizeof (dbnames) + 1);
|
||||
for (cnt = 0; cnt < lastdb; cnt++)
|
||||
char *tables = xstrdup (dbnames[0]);
|
||||
for (dbtype i = 1; i < lastdb; ++i)
|
||||
{
|
||||
strcat (tables, dbnames[cnt]);
|
||||
strcat (tables, " ");
|
||||
char *more_tables;
|
||||
if (asprintf (&more_tables, "%s %s", tables, dbnames[i]) < 0)
|
||||
more_tables = NULL;
|
||||
free (tables);
|
||||
if (more_tables == NULL)
|
||||
return NULL;
|
||||
tables = more_tables;
|
||||
}
|
||||
}
|
||||
|
||||
/* We print some extra information. */
|
||||
if (asprintf (&tp, gettext ("\
|
||||
char *tp;
|
||||
if (asprintf (&tp, gettext ("\
|
||||
Supported tables:\n\
|
||||
%s\n\
|
||||
\n\
|
||||
For bug reporting instructions, please see:\n\
|
||||
%s.\n\
|
||||
"), tables, REPORT_BUGS_TO) < 0)
|
||||
tp = NULL;
|
||||
free (tables);
|
||||
return tp;
|
||||
tp = NULL;
|
||||
free (tables);
|
||||
return tp;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
@@ -622,15 +625,15 @@ monitor_child (int fd)
|
||||
}
|
||||
|
||||
if (WIFEXITED (status))
|
||||
{
|
||||
child_ret = WEXITSTATUS (status);
|
||||
fprintf (stderr, _("child exited with status %d\n"), child_ret);
|
||||
}
|
||||
{
|
||||
child_ret = WEXITSTATUS (status);
|
||||
fprintf (stderr, _("child exited with status %d\n"), child_ret);
|
||||
}
|
||||
if (WIFSIGNALED (status))
|
||||
{
|
||||
child_ret = WTERMSIG (status);
|
||||
fprintf (stderr, _("child terminated by signal %d\n"), child_ret);
|
||||
}
|
||||
{
|
||||
child_ret = WTERMSIG (status);
|
||||
fprintf (stderr, _("child terminated by signal %d\n"), child_ret);
|
||||
}
|
||||
}
|
||||
|
||||
/* We have the child status, so exit with that code. */
|
||||
|
||||
@@ -32,9 +32,6 @@
|
||||
#include "dbg_log.h"
|
||||
#include "nscd.h"
|
||||
|
||||
/* Wrapper functions with error checking for standard functions. */
|
||||
extern char *xstrdup (const char *s);
|
||||
|
||||
|
||||
/* Names of the databases. */
|
||||
const char *const dbnames[lastdb] =
|
||||
|
||||
@@ -6673,11 +6673,11 @@ msgstr "Erreur d'entrée/sortie sur l'hôte cible"
|
||||
|
||||
#: sysdeps/gnu/errlist.c:1399
|
||||
msgid "No medium found"
|
||||
msgstr "Aucun medium trouvé"
|
||||
msgstr "Aucun médium trouvé"
|
||||
|
||||
#: sysdeps/gnu/errlist.c:1407
|
||||
msgid "Wrong medium type"
|
||||
msgstr "Mauvais type de medium"
|
||||
msgstr "Mauvais type de médium"
|
||||
|
||||
#: sysdeps/gnu/errlist.c:1415
|
||||
msgid "Required key not available"
|
||||
|
||||
@@ -13,7 +13,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: libc 2.19.90\n"
|
||||
"POT-Creation-Date: 2014-08-09 17:06+1000\n"
|
||||
"PO-Revision-Date: 2014-08-21 14:55+0400\n"
|
||||
"PO-Revision-Date: 2014-09-10 16:38+0400\n"
|
||||
"Last-Translator: Yuri Kozlov <yuray@komyakino.ru>\n"
|
||||
"Language-Team: Russian <gnu@mx.ru>\n"
|
||||
"Language: ru\n"
|
||||
@@ -76,7 +76,7 @@ msgstr "Выдает краткую информацию об использов
|
||||
#: iconv/iconv_prog.c:60 iconv/iconv_prog.c:61 nscd/nscd.c:105
|
||||
#: nss/makedb.c:120
|
||||
msgid "NAME"
|
||||
msgstr "ФАЙЛ"
|
||||
msgstr "ИМЯ"
|
||||
|
||||
#: argp/argp-parse.c:104
|
||||
msgid "Set the program name"
|
||||
@@ -123,7 +123,7 @@ msgstr ""
|
||||
|
||||
#: catgets/gencat.c:110
|
||||
msgid "Create C header file NAME containing symbol definitions"
|
||||
msgstr "Создает заголовочный ФАЙЛ на Си, содержащий определения символов."
|
||||
msgstr "Создает заголовочный файл с ИМЕНЕМ на Си, содержащий определения символов."
|
||||
|
||||
#: catgets/gencat.c:112
|
||||
msgid "Do not use existing catalog, force new output file"
|
||||
@@ -131,7 +131,7 @@ msgstr "Не использовать существующий каталог,
|
||||
|
||||
#: catgets/gencat.c:113 nss/makedb.c:120
|
||||
msgid "Write output to file NAME"
|
||||
msgstr "Записать вывод в ФАЙЛ"
|
||||
msgstr "Записать вывод в файл с ИМЕНЕМ"
|
||||
|
||||
#: catgets/gencat.c:118
|
||||
msgid ""
|
||||
@@ -4098,7 +4098,7 @@ msgstr "Перезагрузка «%s (%s,%s,%s)» в кэше netgroup!"
|
||||
|
||||
#: nscd/nscd.c:106
|
||||
msgid "Read configuration data from NAME"
|
||||
msgstr "Читать конфигурационные данные из ФАЙЛА"
|
||||
msgstr "Читать конфигурационные данные из файла с ИМЕНЕМ"
|
||||
|
||||
#: nscd/nscd.c:108
|
||||
msgid "Do not fork and display messages on the current tty"
|
||||
|
||||
+14
-2
@@ -40,6 +40,17 @@
|
||||
# define PRINTF(fmt, args...)
|
||||
#endif
|
||||
|
||||
#define LONG_NAME \
|
||||
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
|
||||
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
|
||||
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
|
||||
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
|
||||
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
|
||||
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
|
||||
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
|
||||
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
|
||||
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
|
||||
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
||||
|
||||
static struct
|
||||
{
|
||||
@@ -58,6 +69,7 @@ static struct
|
||||
{ ".", 3, DT_DIR, 0755 },
|
||||
{ "..", 3, DT_DIR, 0755 },
|
||||
{ "a", 3, DT_REG, 0644 },
|
||||
{ LONG_NAME, 3, DT_REG, 0644 },
|
||||
{ "unreadable", 2, DT_DIR, 0111 },
|
||||
{ ".", 3, DT_DIR, 0111 },
|
||||
{ "..", 3, DT_DIR, 0755 },
|
||||
@@ -75,7 +87,7 @@ typedef struct
|
||||
int level;
|
||||
int idx;
|
||||
struct dirent d;
|
||||
char room_for_dirent[NAME_MAX];
|
||||
char room_for_dirent[sizeof (LONG_NAME)];
|
||||
} my_DIR;
|
||||
|
||||
|
||||
@@ -193,7 +205,7 @@ my_readdir (void *gdir)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dir->d.d_ino = dir->idx;
|
||||
dir->d.d_ino = 1; /* glob should not skip this entry. */
|
||||
|
||||
#ifdef _DIRENT_HAVE_D_TYPE
|
||||
dir->d.d_type = filesystem[dir->idx].type;
|
||||
|
||||
@@ -221,6 +221,8 @@ __wcschrnul (s, c)
|
||||
# define MEMCHR(S, C, N) memchr (S, C, N)
|
||||
# define STRCOLL(S1, S2) strcoll (S1, S2)
|
||||
# define WIDE_CHAR_VERSION 0
|
||||
# include <locale/weight.h>
|
||||
# define FINDIDX findidx
|
||||
# include "fnmatch_loop.c"
|
||||
|
||||
|
||||
@@ -246,6 +248,12 @@ __wcschrnul (s, c)
|
||||
# define MEMCHR(S, C, N) wmemchr (S, C, N)
|
||||
# define STRCOLL(S1, S2) wcscoll (S1, S2)
|
||||
# define WIDE_CHAR_VERSION 1
|
||||
/* Change the name the header defines so it doesn't conflict with
|
||||
the <locale/weight.h> version included above. */
|
||||
# define findidx findidxwc
|
||||
# include <locale/weightwc.h>
|
||||
# undef findidx
|
||||
# define FINDIDX findidxwc
|
||||
|
||||
# undef IS_CHAR_CLASS
|
||||
/* We have to convert the wide character string in a multibyte string. But
|
||||
|
||||
+8
-14
@@ -376,7 +376,7 @@ FCT (pattern, string, string_end, no_leading_period, flags, ends, alloca_used)
|
||||
const int32_t *table;
|
||||
# if WIDE_CHAR_VERSION
|
||||
const int32_t *weights;
|
||||
const int32_t *extra;
|
||||
const wint_t *extra;
|
||||
# else
|
||||
const unsigned char *weights;
|
||||
const unsigned char *extra;
|
||||
@@ -385,19 +385,12 @@ FCT (pattern, string, string_end, no_leading_period, flags, ends, alloca_used)
|
||||
int32_t idx;
|
||||
const UCHAR *cp = (const UCHAR *) str;
|
||||
|
||||
/* This #include defines a local function! */
|
||||
# if WIDE_CHAR_VERSION
|
||||
# include <locale/weightwc.h>
|
||||
# else
|
||||
# include <locale/weight.h>
|
||||
# endif
|
||||
|
||||
# if WIDE_CHAR_VERSION
|
||||
table = (const int32_t *)
|
||||
_NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEWC);
|
||||
weights = (const int32_t *)
|
||||
_NL_CURRENT (LC_COLLATE, _NL_COLLATE_WEIGHTWC);
|
||||
extra = (const int32_t *)
|
||||
extra = (const wint_t *)
|
||||
_NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAWC);
|
||||
indirect = (const int32_t *)
|
||||
_NL_CURRENT (LC_COLLATE, _NL_COLLATE_INDIRECTWC);
|
||||
@@ -412,7 +405,7 @@ FCT (pattern, string, string_end, no_leading_period, flags, ends, alloca_used)
|
||||
_NL_CURRENT (LC_COLLATE, _NL_COLLATE_INDIRECTMB);
|
||||
# endif
|
||||
|
||||
idx = findidx (&cp, 1);
|
||||
idx = FINDIDX (table, indirect, extra, &cp, 1);
|
||||
if (idx != 0)
|
||||
{
|
||||
/* We found a table entry. Now see whether the
|
||||
@@ -422,7 +415,8 @@ FCT (pattern, string, string_end, no_leading_period, flags, ends, alloca_used)
|
||||
int32_t idx2;
|
||||
const UCHAR *np = (const UCHAR *) n;
|
||||
|
||||
idx2 = findidx (&np, string_end - n);
|
||||
idx2 = FINDIDX (table, indirect, extra,
|
||||
&np, string_end - n);
|
||||
if (idx2 != 0
|
||||
&& (idx >> 24) == (idx2 >> 24)
|
||||
&& len == weights[idx2 & 0xffffff])
|
||||
@@ -946,14 +940,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;
|
||||
@@ -1277,3 +1270,4 @@ EXT (INT opt, const CHAR *pattern, const CHAR *string, const CHAR *string_end,
|
||||
#undef L
|
||||
#undef BTOWC
|
||||
#undef WIDE_CHAR_VERSION
|
||||
#undef FINDIDX
|
||||
|
||||
+125
-118
@@ -24,7 +24,9 @@
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/* Outcomment the following line for production quality code. */
|
||||
/* #define NDEBUG 1 */
|
||||
@@ -57,10 +59,8 @@
|
||||
|
||||
#if defined HAVE_DIRENT_H || defined __GNU_LIBRARY__
|
||||
# include <dirent.h>
|
||||
# define NAMLEN(dirent) strlen((dirent)->d_name)
|
||||
#else
|
||||
# define dirent direct
|
||||
# define NAMLEN(dirent) (dirent)->d_namlen
|
||||
# ifdef HAVE_SYS_NDIR_H
|
||||
# include <sys/ndir.h>
|
||||
# endif
|
||||
@@ -75,82 +75,8 @@
|
||||
# endif /* HAVE_VMSDIR_H */
|
||||
#endif
|
||||
|
||||
|
||||
/* In GNU systems, <dirent.h> defines this macro for us. */
|
||||
#ifdef _D_NAMLEN
|
||||
# undef NAMLEN
|
||||
# define NAMLEN(d) _D_NAMLEN(d)
|
||||
#endif
|
||||
|
||||
/* When used in the GNU libc the symbol _DIRENT_HAVE_D_TYPE is available
|
||||
if the `d_type' member for `struct dirent' is available.
|
||||
HAVE_STRUCT_DIRENT_D_TYPE plays the same role in GNULIB. */
|
||||
#if defined _DIRENT_HAVE_D_TYPE || defined HAVE_STRUCT_DIRENT_D_TYPE
|
||||
/* True if the directory entry D must be of type T. */
|
||||
# define DIRENT_MUST_BE(d, t) ((d)->d_type == (t))
|
||||
|
||||
/* True if the directory entry D might be a symbolic link. */
|
||||
# define DIRENT_MIGHT_BE_SYMLINK(d) \
|
||||
((d)->d_type == DT_UNKNOWN || (d)->d_type == DT_LNK)
|
||||
|
||||
/* True if the directory entry D might be a directory. */
|
||||
# define DIRENT_MIGHT_BE_DIR(d) \
|
||||
((d)->d_type == DT_DIR || DIRENT_MIGHT_BE_SYMLINK (d))
|
||||
|
||||
#else /* !HAVE_D_TYPE */
|
||||
# define DIRENT_MUST_BE(d, t) false
|
||||
# define DIRENT_MIGHT_BE_SYMLINK(d) true
|
||||
# define DIRENT_MIGHT_BE_DIR(d) true
|
||||
#endif /* HAVE_D_TYPE */
|
||||
|
||||
/* If the system has the `struct dirent64' type we use it internally. */
|
||||
#if defined _LIBC && !defined COMPILE_GLOB64
|
||||
# if defined HAVE_DIRENT_H || defined __GNU_LIBRARY__
|
||||
# define CONVERT_D_NAMLEN(d64, d32)
|
||||
# else
|
||||
# define CONVERT_D_NAMLEN(d64, d32) \
|
||||
(d64)->d_namlen = (d32)->d_namlen;
|
||||
# endif
|
||||
|
||||
# if (defined POSIX || defined WINDOWS32) && !defined __GNU_LIBRARY__
|
||||
# define CONVERT_D_INO(d64, d32)
|
||||
# else
|
||||
# define CONVERT_D_INO(d64, d32) \
|
||||
(d64)->d_ino = (d32)->d_ino;
|
||||
# endif
|
||||
|
||||
# ifdef _DIRENT_HAVE_D_TYPE
|
||||
# define CONVERT_D_TYPE(d64, d32) \
|
||||
(d64)->d_type = (d32)->d_type;
|
||||
# else
|
||||
# define CONVERT_D_TYPE(d64, d32)
|
||||
# endif
|
||||
|
||||
# define CONVERT_DIRENT_DIRENT64(d64, d32) \
|
||||
memcpy ((d64)->d_name, (d32)->d_name, NAMLEN (d32) + 1); \
|
||||
CONVERT_D_NAMLEN (d64, d32) \
|
||||
CONVERT_D_INO (d64, d32) \
|
||||
CONVERT_D_TYPE (d64, d32)
|
||||
#endif
|
||||
|
||||
|
||||
#if (defined POSIX || defined WINDOWS32) && !defined __GNU_LIBRARY__
|
||||
/* Posix does not require that the d_ino field be present, and some
|
||||
systems do not provide it. */
|
||||
# define REAL_DIR_ENTRY(dp) 1
|
||||
#else
|
||||
# define REAL_DIR_ENTRY(dp) (dp->d_ino != 0)
|
||||
#endif /* POSIX */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/* NAME_MAX is usually defined in <dirent.h> or <limits.h>. */
|
||||
#include <limits.h>
|
||||
#ifndef NAME_MAX
|
||||
# define NAME_MAX (sizeof (((struct dirent *) 0)->d_name))
|
||||
#endif
|
||||
|
||||
#include <alloca.h>
|
||||
|
||||
#ifdef _LIBC
|
||||
@@ -195,8 +121,111 @@
|
||||
|
||||
static const char *next_brace_sub (const char *begin, int flags) __THROWNL;
|
||||
|
||||
/* A representation of a directory entry which does not depend on the
|
||||
layout of struct dirent, or the size of ino_t. */
|
||||
struct readdir_result
|
||||
{
|
||||
const char *name;
|
||||
# if defined _DIRENT_HAVE_D_TYPE || defined HAVE_STRUCT_DIRENT_D_TYPE
|
||||
uint8_t type;
|
||||
# endif
|
||||
bool skip_entry;
|
||||
};
|
||||
|
||||
# if defined _DIRENT_HAVE_D_TYPE || defined HAVE_STRUCT_DIRENT_D_TYPE
|
||||
/* Initializer based on the d_type member of struct dirent. */
|
||||
# define D_TYPE_TO_RESULT(source) (source)->d_type,
|
||||
|
||||
/* True if the directory entry D might be a symbolic link. */
|
||||
static bool
|
||||
readdir_result_might_be_symlink (struct readdir_result d)
|
||||
{
|
||||
return d.type == DT_UNKNOWN || d.type == DT_LNK;
|
||||
}
|
||||
|
||||
/* True if the directory entry D might be a directory. */
|
||||
static bool
|
||||
readdir_result_might_be_dir (struct readdir_result d)
|
||||
{
|
||||
return d.type == DT_DIR || readdir_result_might_be_symlink (d);
|
||||
}
|
||||
# else /* defined _DIRENT_HAVE_D_TYPE || defined HAVE_STRUCT_DIRENT_D_TYPE */
|
||||
# define D_TYPE_TO_RESULT(source)
|
||||
|
||||
/* If we do not have type information, symbolic links and directories
|
||||
are always a possibility. */
|
||||
|
||||
static bool
|
||||
readdir_result_might_be_symlink (struct readdir_result d)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
readdir_result_might_be_dir (struct readdir_result d)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
# endif /* defined _DIRENT_HAVE_D_TYPE || defined HAVE_STRUCT_DIRENT_D_TYPE */
|
||||
|
||||
# if (defined POSIX || defined WINDOWS32) && !defined __GNU_LIBRARY__
|
||||
/* Initializer for skip_entry. POSIX does not require that the d_ino
|
||||
field be present, and some systems do not provide it. */
|
||||
# define D_INO_TO_RESULT(source) false,
|
||||
# else
|
||||
# define D_INO_TO_RESULT(source) (source)->d_ino == 0,
|
||||
# endif
|
||||
|
||||
/* Construct an initializer for a struct readdir_result object from a
|
||||
struct dirent *. No copy of the name is made. */
|
||||
#define READDIR_RESULT_INITIALIZER(source) \
|
||||
{ \
|
||||
source->d_name, \
|
||||
D_TYPE_TO_RESULT (source) \
|
||||
D_INO_TO_RESULT (source) \
|
||||
}
|
||||
|
||||
#endif /* !defined _LIBC || !defined GLOB_ONLY_P */
|
||||
|
||||
/* Call gl_readdir on STREAM. This macro can be overridden to reduce
|
||||
type safety if an old interface version needs to be supported. */
|
||||
#ifndef GL_READDIR
|
||||
# define GL_READDIR(pglob, stream) ((pglob)->gl_readdir (stream))
|
||||
#endif
|
||||
|
||||
/* Extract name and type from directory entry. No copy of the name is
|
||||
made. If SOURCE is NULL, result name is NULL. Keep in sync with
|
||||
convert_dirent64 below. */
|
||||
static struct readdir_result
|
||||
convert_dirent (const struct dirent *source)
|
||||
{
|
||||
if (source == NULL)
|
||||
{
|
||||
struct readdir_result result = { NULL, };
|
||||
return result;
|
||||
}
|
||||
struct readdir_result result = READDIR_RESULT_INITIALIZER (source);
|
||||
return result;
|
||||
}
|
||||
|
||||
#ifndef COMPILE_GLOB64
|
||||
/* Like convert_dirent, but works on struct dirent64 instead. Keep in
|
||||
sync with convert_dirent above. */
|
||||
static struct readdir_result
|
||||
convert_dirent64 (const struct dirent64 *source)
|
||||
{
|
||||
if (source == NULL)
|
||||
{
|
||||
struct readdir_result result = { NULL, };
|
||||
return result;
|
||||
}
|
||||
struct readdir_result result = READDIR_RESULT_INITIALIZER (source);
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef attribute_hidden
|
||||
# define attribute_hidden
|
||||
#endif
|
||||
@@ -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 (__glibc_unlikely (flags & GLOB_ALTDIRFUNC))
|
||||
{
|
||||
struct dirent *d32 = (*pglob->gl_readdir) (stream);
|
||||
if (d32 != NULL)
|
||||
{
|
||||
CONVERT_DIRENT_DIRENT64 (&d64buf.d64, d32);
|
||||
d = &d64buf.d64;
|
||||
}
|
||||
else
|
||||
d = NULL;
|
||||
}
|
||||
else
|
||||
d = __readdir64 (stream);
|
||||
struct readdir_result d;
|
||||
{
|
||||
if (__builtin_expect (flags & GLOB_ALTDIRFUNC, 0))
|
||||
d = convert_dirent (GL_READDIR (pglob, stream));
|
||||
else
|
||||
{
|
||||
#ifdef COMPILE_GLOB64
|
||||
d = convert_dirent (__readdir (stream));
|
||||
#else
|
||||
struct dirent *d = (__builtin_expect (flags & GLOB_ALTDIRFUNC, 0)
|
||||
? ((struct dirent *)
|
||||
(*pglob->gl_readdir) (stream))
|
||||
: __readdir (stream));
|
||||
d = convert_dirent64 (__readdir64 (stream));
|
||||
#endif
|
||||
if (d == NULL)
|
||||
}
|
||||
}
|
||||
if (d.name == NULL)
|
||||
break;
|
||||
if (! REAL_DIR_ENTRY (d))
|
||||
if (d.skip_entry)
|
||||
continue;
|
||||
|
||||
/* If we shall match only directories use the information
|
||||
provided by the dirent call if possible. */
|
||||
if ((flags & GLOB_ONLYDIR) && !DIRENT_MIGHT_BE_DIR (d))
|
||||
if ((flags & GLOB_ONLYDIR) && !readdir_result_might_be_dir (d))
|
||||
continue;
|
||||
|
||||
name = d->d_name;
|
||||
|
||||
if (fnmatch (pattern, name, fnm_flags) == 0)
|
||||
if (fnmatch (pattern, d.name, fnm_flags) == 0)
|
||||
{
|
||||
/* If the file we found is a symlink we have to
|
||||
make sure the target file exists. */
|
||||
if (!DIRENT_MIGHT_BE_SYMLINK (d)
|
||||
|| link_exists_p (dfd, directory, dirlen, name, pglob,
|
||||
flags))
|
||||
if (!readdir_result_might_be_symlink (d)
|
||||
|| link_exists_p (dfd, directory, dirlen, d.name,
|
||||
pglob, flags))
|
||||
{
|
||||
if (cur == names->count)
|
||||
{
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
+6
-4
@@ -19,6 +19,10 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef _LIBC
|
||||
# include <locale/weight.h>
|
||||
#endif
|
||||
|
||||
static reg_errcode_t re_compile_internal (regex_t *preg, const char * pattern,
|
||||
size_t length, reg_syntax_t syntax);
|
||||
static void re_compile_fastmap_iter (regex_t *bufp,
|
||||
@@ -3426,8 +3430,6 @@ build_equiv_class (bitset_t sbcset, const unsigned char *name)
|
||||
int32_t idx1, idx2;
|
||||
unsigned int ch;
|
||||
size_t len;
|
||||
/* This #include defines a local function! */
|
||||
# include <locale/weight.h>
|
||||
/* Calculate the index for equivalence class. */
|
||||
cp = name;
|
||||
table = (const int32_t *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB);
|
||||
@@ -3437,7 +3439,7 @@ build_equiv_class (bitset_t sbcset, const unsigned char *name)
|
||||
_NL_COLLATE_EXTRAMB);
|
||||
indirect = (const int32_t *) _NL_CURRENT (LC_COLLATE,
|
||||
_NL_COLLATE_INDIRECTMB);
|
||||
idx1 = findidx (&cp, -1);
|
||||
idx1 = findidx (table, indirect, extra, &cp, -1);
|
||||
if (BE (idx1 == 0 || *cp != '\0', 0))
|
||||
/* This isn't a valid character. */
|
||||
return REG_ECOLLATE;
|
||||
@@ -3448,7 +3450,7 @@ build_equiv_class (bitset_t sbcset, const unsigned char *name)
|
||||
{
|
||||
char_buf[0] = ch;
|
||||
cp = char_buf;
|
||||
idx2 = findidx (&cp, 1);
|
||||
idx2 = findidx (table, indirect, extra, &cp, 1);
|
||||
/*
|
||||
idx2 = table[ch];
|
||||
*/
|
||||
|
||||
@@ -733,6 +733,10 @@ re_string_wchar_at (const re_string_t *pstr, int idx)
|
||||
}
|
||||
|
||||
# ifndef NOT_IN_libc
|
||||
# ifdef _LIBC
|
||||
# include <locale/weight.h>
|
||||
# endif
|
||||
|
||||
static int
|
||||
internal_function __attribute__ ((pure, unused))
|
||||
re_string_elem_size_at (const re_string_t *pstr, int idx)
|
||||
@@ -740,7 +744,6 @@ re_string_elem_size_at (const re_string_t *pstr, int idx)
|
||||
# ifdef _LIBC
|
||||
const unsigned char *p, *extra;
|
||||
const int32_t *table, *indirect;
|
||||
# include <locale/weight.h>
|
||||
uint_fast32_t nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
|
||||
|
||||
if (nrules != 0)
|
||||
@@ -751,7 +754,7 @@ re_string_elem_size_at (const re_string_t *pstr, int idx)
|
||||
indirect = (const int32_t *) _NL_CURRENT (LC_COLLATE,
|
||||
_NL_COLLATE_INDIRECTMB);
|
||||
p = pstr->mbs + idx;
|
||||
findidx (&p, pstr->len - idx);
|
||||
findidx (table, indirect, extra, &p, pstr->len - idx);
|
||||
return p - pstr->mbs - idx;
|
||||
}
|
||||
else
|
||||
|
||||
+5
-3
@@ -3749,6 +3749,10 @@ group_nodes_into_DFAstates (const re_dfa_t *dfa, const re_dfastate_t *state,
|
||||
one collating element like '.', '[a-z]', opposite to the other nodes
|
||||
can only accept one byte. */
|
||||
|
||||
# ifdef _LIBC
|
||||
# include <locale/weight.h>
|
||||
# endif
|
||||
|
||||
static int
|
||||
internal_function
|
||||
check_node_accept_bytes (const re_dfa_t *dfa, int node_idx,
|
||||
@@ -3868,8 +3872,6 @@ check_node_accept_bytes (const re_dfa_t *dfa, int node_idx,
|
||||
const int32_t *table, *indirect;
|
||||
const unsigned char *weights, *extra;
|
||||
const char *collseqwc;
|
||||
/* This #include defines a local function! */
|
||||
# include <locale/weight.h>
|
||||
|
||||
/* match with collating_symbol? */
|
||||
if (cset->ncoll_syms)
|
||||
@@ -3925,7 +3927,7 @@ check_node_accept_bytes (const re_dfa_t *dfa, int node_idx,
|
||||
_NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAMB);
|
||||
indirect = (const int32_t *)
|
||||
_NL_CURRENT (LC_COLLATE, _NL_COLLATE_INDIRECTMB);
|
||||
int32_t idx = findidx (&cp, elem_len);
|
||||
int32_t idx = findidx (table, indirect, extra, &cp, elem_len);
|
||||
if (idx > 0)
|
||||
for (i = 0; i < cset->nequiv_classes; ++i)
|
||||
{
|
||||
|
||||
@@ -21,9 +21,11 @@
|
||||
int
|
||||
do_test (void)
|
||||
{
|
||||
const char *pattern = "[[:alpha:]'[:alpha:]\0]";
|
||||
|
||||
return fnmatch (pattern, "a", 0) != FNM_NOMATCH;
|
||||
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 ()
|
||||
|
||||
+1
-1
@@ -211,7 +211,7 @@ my_readdir (void *gdir)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dir->d.d_ino = dir->idx;
|
||||
dir->d.d_ino = 1; /* glob should not skip this entry. */
|
||||
|
||||
#ifdef _DIRENT_HAVE_D_TYPE
|
||||
dir->d.d_type = filesystem[dir->idx].type;
|
||||
|
||||
@@ -27,6 +27,25 @@
|
||||
|
||||
#define IFS " \n\t"
|
||||
|
||||
extern void *__dso_handle __attribute__ ((__weak__, __visibility__ ("hidden")));
|
||||
extern int __register_atfork (void (*) (void), void (*) (void), void (*) (void), void *);
|
||||
|
||||
static int __app_register_atfork (void (*prepare) (void), void (*parent) (void), void (*child) (void))
|
||||
{
|
||||
return __register_atfork (prepare, parent, child,
|
||||
&__dso_handle == NULL ? NULL : __dso_handle);
|
||||
}
|
||||
|
||||
/* Number of forks seen. */
|
||||
static int registered_forks;
|
||||
|
||||
/* For each fork increment the fork count. */
|
||||
static void
|
||||
register_fork (void)
|
||||
{
|
||||
registered_forks++;
|
||||
}
|
||||
|
||||
struct test_case_struct
|
||||
{
|
||||
int retval;
|
||||
@@ -206,6 +225,12 @@ struct test_case_struct
|
||||
{ WRDE_SYNTAX, NULL, "$((2+))", 0, 0, { NULL, }, IFS },
|
||||
{ WRDE_SYNTAX, NULL, "`", 0, 0, { NULL, }, IFS },
|
||||
{ WRDE_SYNTAX, NULL, "$((010+4+))", 0, 0, { NULL }, IFS },
|
||||
/* Test for CVE-2014-7817. We test 3 combinations of command
|
||||
substitution inside an arithmetic expression to make sure that
|
||||
no commands are executed and error is returned. */
|
||||
{ WRDE_CMDSUB, NULL, "$((`echo 1`))", WRDE_NOCMD, 0, { NULL, }, IFS },
|
||||
{ WRDE_CMDSUB, NULL, "$((1+`echo 1`))", WRDE_NOCMD, 0, { NULL, }, IFS },
|
||||
{ WRDE_CMDSUB, NULL, "$((1+$((`echo 1`))))", WRDE_NOCMD, 0, { NULL, }, IFS },
|
||||
|
||||
{ -1, NULL, NULL, 0, 0, { NULL, }, IFS },
|
||||
};
|
||||
@@ -258,6 +283,15 @@ main (int argc, char *argv[])
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* If we are not allowed to do command substitution, we install
|
||||
fork handlers to verify that no forks happened. No forks should
|
||||
happen at all if command substitution is disabled. */
|
||||
if (__app_register_atfork (register_fork, NULL, NULL) != 0)
|
||||
{
|
||||
printf ("Failed to register fork handler.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (test = 0; test_case[test].retval != -1; test++)
|
||||
if (testit (&test_case[test]))
|
||||
++fail;
|
||||
@@ -367,6 +401,9 @@ testit (struct test_case_struct *tc)
|
||||
|
||||
printf ("Test %d (%s): ", ++tests, tc->words);
|
||||
|
||||
if (tc->flags & WRDE_NOCMD)
|
||||
registered_forks = 0;
|
||||
|
||||
if (tc->flags & WRDE_APPEND)
|
||||
{
|
||||
/* initial wordexp() call, to be appended to */
|
||||
@@ -378,6 +415,13 @@ testit (struct test_case_struct *tc)
|
||||
}
|
||||
retval = wordexp (tc->words, &we, tc->flags);
|
||||
|
||||
if ((tc->flags & WRDE_NOCMD)
|
||||
&& (registered_forks > 0))
|
||||
{
|
||||
printf ("FAILED fork called for WRDE_NOCMD\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (tc->flags & WRDE_DOOFFS)
|
||||
start_offs = sav_we.we_offs;
|
||||
|
||||
|
||||
+4
-12
@@ -893,6 +893,10 @@ exec_comm (char *comm, char **word, size_t *word_length, size_t *max_length,
|
||||
pid_t pid;
|
||||
int noexec = 0;
|
||||
|
||||
/* Do nothing if command substitution should not succeed. */
|
||||
if (flags & WRDE_NOCMD)
|
||||
return WRDE_CMDSUB;
|
||||
|
||||
/* Don't fork() unless necessary */
|
||||
if (!comm || !*comm)
|
||||
return 0;
|
||||
@@ -2082,9 +2086,6 @@ parse_dollars (char **word, size_t *word_length, size_t *max_length,
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & WRDE_NOCMD)
|
||||
return WRDE_CMDSUB;
|
||||
|
||||
(*offset) += 2;
|
||||
return parse_comm (word, word_length, max_length, words, offset, flags,
|
||||
quoted? NULL : pwordexp, ifs, ifs_white);
|
||||
@@ -2196,9 +2197,6 @@ parse_dquote (char **word, size_t *word_length, size_t *max_length,
|
||||
break;
|
||||
|
||||
case '`':
|
||||
if (flags & WRDE_NOCMD)
|
||||
return WRDE_CMDSUB;
|
||||
|
||||
++(*offset);
|
||||
error = parse_backtick (word, word_length, max_length, words,
|
||||
offset, flags, NULL, NULL, NULL);
|
||||
@@ -2357,12 +2355,6 @@ wordexp (const char *words, wordexp_t *pwordexp, int flags)
|
||||
break;
|
||||
|
||||
case '`':
|
||||
if (flags & WRDE_NOCMD)
|
||||
{
|
||||
error = WRDE_CMDSUB;
|
||||
goto do_error;
|
||||
}
|
||||
|
||||
++words_offset;
|
||||
error = parse_backtick (&word, &word_length, &max_length, words,
|
||||
&words_offset, flags, pwordexp, ifs,
|
||||
|
||||
+109
-2
@@ -1031,7 +1031,10 @@ gaih_getanswer_slice (const querybuf *answer, int anslen, const char *qname,
|
||||
int h_namelen = 0;
|
||||
|
||||
if (ancount == 0)
|
||||
return NSS_STATUS_NOTFOUND;
|
||||
{
|
||||
*h_errnop = HOST_NOT_FOUND;
|
||||
return NSS_STATUS_NOTFOUND;
|
||||
}
|
||||
|
||||
while (ancount-- > 0 && cp < end_of_message && had_error == 0)
|
||||
{
|
||||
@@ -1208,7 +1211,14 @@ gaih_getanswer_slice (const querybuf *answer, int anslen, const char *qname,
|
||||
/* Special case here: if the resolver sent a result but it only
|
||||
contains a CNAME while we are looking for a T_A or T_AAAA record,
|
||||
we fail with NOTFOUND instead of TRYAGAIN. */
|
||||
return canon == NULL ? NSS_STATUS_TRYAGAIN : NSS_STATUS_NOTFOUND;
|
||||
if (canon != NULL)
|
||||
{
|
||||
*h_errnop = HOST_NOT_FOUND;
|
||||
return NSS_STATUS_NOTFOUND;
|
||||
}
|
||||
|
||||
*h_errnop = NETDB_INTERNAL;
|
||||
return NSS_STATUS_TRYAGAIN;
|
||||
}
|
||||
|
||||
|
||||
@@ -1222,11 +1232,101 @@ gaih_getanswer (const querybuf *answer1, int anslen1, const querybuf *answer2,
|
||||
|
||||
enum nss_status status = NSS_STATUS_NOTFOUND;
|
||||
|
||||
/* Combining the NSS status of two distinct queries requires some
|
||||
compromise and attention to symmetry (A or AAAA queries can be
|
||||
returned in any order). What follows is a breakdown of how this
|
||||
code is expected to work and why. We discuss only SUCCESS,
|
||||
TRYAGAIN, NOTFOUND and UNAVAIL, since they are the only returns
|
||||
that apply (though RETURN and MERGE exist). We make a distinction
|
||||
between TRYAGAIN (recoverable) and TRYAGAIN' (not-recoverable).
|
||||
A recoverable TRYAGAIN is almost always due to buffer size issues
|
||||
and returns ERANGE in errno and the caller is expected to retry
|
||||
with a larger buffer.
|
||||
|
||||
Lastly, you may be tempted to make significant changes to the
|
||||
conditions in this code to bring about symmetry between responses.
|
||||
Please don't change anything without due consideration for
|
||||
expected application behaviour. Some of the synthesized responses
|
||||
aren't very well thought out and sometimes appear to imply that
|
||||
IPv4 responses are always answer 1, and IPv6 responses are always
|
||||
answer 2, but that's not true (see the implementation of send_dg
|
||||
and send_vc to see response can arrive in any order, particularly
|
||||
for UDP). However, we expect it holds roughly enough of the time
|
||||
that this code works, but certainly needs to be fixed to make this
|
||||
a more robust implementation.
|
||||
|
||||
----------------------------------------------
|
||||
| Answer 1 Status / | Synthesized | Reason |
|
||||
| Answer 2 Status | Status | |
|
||||
|--------------------------------------------|
|
||||
| SUCCESS/SUCCESS | SUCCESS | [1] |
|
||||
| SUCCESS/TRYAGAIN | TRYAGAIN | [5] |
|
||||
| SUCCESS/TRYAGAIN' | SUCCESS | [1] |
|
||||
| SUCCESS/NOTFOUND | SUCCESS | [1] |
|
||||
| SUCCESS/UNAVAIL | SUCCESS | [1] |
|
||||
| TRYAGAIN/SUCCESS | TRYAGAIN | [2] |
|
||||
| TRYAGAIN/TRYAGAIN | TRYAGAIN | [2] |
|
||||
| TRYAGAIN/TRYAGAIN' | TRYAGAIN | [2] |
|
||||
| TRYAGAIN/NOTFOUND | TRYAGAIN | [2] |
|
||||
| TRYAGAIN/UNAVAIL | TRYAGAIN | [2] |
|
||||
| TRYAGAIN'/SUCCESS | SUCCESS | [3] |
|
||||
| TRYAGAIN'/TRYAGAIN | TRYAGAIN | [3] |
|
||||
| TRYAGAIN'/TRYAGAIN' | TRYAGAIN' | [3] |
|
||||
| TRYAGAIN'/NOTFOUND | TRYAGAIN' | [3] |
|
||||
| TRYAGAIN'/UNAVAIL | UNAVAIL | [3] |
|
||||
| NOTFOUND/SUCCESS | SUCCESS | [3] |
|
||||
| NOTFOUND/TRYAGAIN | TRYAGAIN | [3] |
|
||||
| NOTFOUND/TRYAGAIN' | TRYAGAIN' | [3] |
|
||||
| NOTFOUND/NOTFOUND | NOTFOUND | [3] |
|
||||
| NOTFOUND/UNAVAIL | UNAVAIL | [3] |
|
||||
| UNAVAIL/SUCCESS | UNAVAIL | [4] |
|
||||
| UNAVAIL/TRYAGAIN | UNAVAIL | [4] |
|
||||
| UNAVAIL/TRYAGAIN' | UNAVAIL | [4] |
|
||||
| UNAVAIL/NOTFOUND | UNAVAIL | [4] |
|
||||
| UNAVAIL/UNAVAIL | UNAVAIL | [4] |
|
||||
----------------------------------------------
|
||||
|
||||
[1] If the first response is a success we return success.
|
||||
This ignores the state of the second answer and in fact
|
||||
incorrectly sets errno and h_errno to that of the second
|
||||
answer. However because the response is a success we ignore
|
||||
*errnop and *h_errnop (though that means you touched errno on
|
||||
success). We are being conservative here and returning the
|
||||
likely IPv4 response in the first answer as a success.
|
||||
|
||||
[2] If the first response is a recoverable TRYAGAIN we return
|
||||
that instead of looking at the second response. The
|
||||
expectation here is that we have failed to get an IPv4 response
|
||||
and should retry both queries.
|
||||
|
||||
[3] If the first response was not a SUCCESS and the second
|
||||
response is not NOTFOUND (had a SUCCESS, need to TRYAGAIN,
|
||||
or failed entirely e.g. TRYAGAIN' and UNAVAIL) then use the
|
||||
result from the second response, otherwise the first responses
|
||||
status is used. Again we have some odd side-effects when the
|
||||
second response is NOTFOUND because we overwrite *errnop and
|
||||
*h_errnop that means that a first answer of NOTFOUND might see
|
||||
its *errnop and *h_errnop values altered. Whether it matters
|
||||
in practice that a first response NOTFOUND has the wrong
|
||||
*errnop and *h_errnop is undecided.
|
||||
|
||||
[4] If the first response is UNAVAIL we return that instead of
|
||||
looking at the second response. The expectation here is that
|
||||
it will have failed similarly e.g. configuration failure.
|
||||
|
||||
[5] Testing this code is complicated by the fact that truncated
|
||||
second response buffers might be returned as SUCCESS if the
|
||||
first answer is a SUCCESS. To fix this we add symmetry to
|
||||
TRYAGAIN with the second response. If the second response
|
||||
is a recoverable error we now return TRYAGIN even if the first
|
||||
response was SUCCESS. */
|
||||
|
||||
if (anslen1 > 0)
|
||||
status = gaih_getanswer_slice(answer1, anslen1, qname,
|
||||
&pat, &buffer, &buflen,
|
||||
errnop, h_errnop, ttlp,
|
||||
&first);
|
||||
|
||||
if ((status == NSS_STATUS_SUCCESS || status == NSS_STATUS_NOTFOUND
|
||||
|| (status == NSS_STATUS_TRYAGAIN
|
||||
/* We want to look at the second answer in case of an
|
||||
@@ -1242,8 +1342,15 @@ gaih_getanswer (const querybuf *answer1, int anslen1, const querybuf *answer2,
|
||||
&pat, &buffer, &buflen,
|
||||
errnop, h_errnop, ttlp,
|
||||
&first);
|
||||
/* Use the second response status in some cases. */
|
||||
if (status != NSS_STATUS_SUCCESS && status2 != NSS_STATUS_NOTFOUND)
|
||||
status = status2;
|
||||
/* Do not return a truncated second response (unless it was
|
||||
unavoidable e.g. unrecoverable TRYAGAIN). */
|
||||
if (status == NSS_STATUS_SUCCESS
|
||||
&& (status2 == NSS_STATUS_TRYAGAIN
|
||||
&& *errnop == ERANGE && *h_errnop != NO_RECOVERY))
|
||||
status = NSS_STATUS_TRYAGAIN;
|
||||
}
|
||||
|
||||
return status;
|
||||
|
||||
@@ -118,17 +118,14 @@ _nss_dns_getnetbyname_r (const char *name, struct netent *result,
|
||||
} net_buffer;
|
||||
querybuf *orig_net_buffer;
|
||||
int anslen;
|
||||
char *qbuf;
|
||||
enum nss_status status;
|
||||
|
||||
if (__res_maybe_init (&_res, 0) == -1)
|
||||
return NSS_STATUS_UNAVAIL;
|
||||
|
||||
qbuf = strdupa (name);
|
||||
|
||||
net_buffer.buf = orig_net_buffer = (querybuf *) alloca (1024);
|
||||
|
||||
anslen = __libc_res_nsearch (&_res, qbuf, C_IN, T_PTR, net_buffer.buf->buf,
|
||||
anslen = __libc_res_nsearch (&_res, name, C_IN, T_PTR, net_buffer.buf->buf,
|
||||
1024, &net_buffer.ptr, NULL, NULL, NULL, NULL);
|
||||
if (anslen < 0)
|
||||
{
|
||||
@@ -398,8 +395,8 @@ getanswer_r (const querybuf *answer, int anslen, struct netent *result,
|
||||
|
||||
case BYNAME:
|
||||
{
|
||||
char **ap = result->n_aliases++;
|
||||
while (*ap != NULL)
|
||||
char **ap;
|
||||
for (ap = result->n_aliases; *ap != NULL; ++ap)
|
||||
{
|
||||
/* Check each alias name for being of the forms:
|
||||
4.3.2.1.in-addr.arpa = net 1.2.3.4
|
||||
|
||||
@@ -396,6 +396,7 @@ __libc_res_nsearch(res_state statp,
|
||||
{
|
||||
free (*answerp2);
|
||||
*answerp2 = NULL;
|
||||
*nanswerp2 = 0;
|
||||
*answerp2_malloced = 0;
|
||||
}
|
||||
}
|
||||
@@ -436,6 +437,7 @@ __libc_res_nsearch(res_state statp,
|
||||
{
|
||||
free (*answerp2);
|
||||
*answerp2 = NULL;
|
||||
*nanswerp2 = 0;
|
||||
*answerp2_malloced = 0;
|
||||
}
|
||||
|
||||
@@ -510,6 +512,7 @@ __libc_res_nsearch(res_state statp,
|
||||
{
|
||||
free (*answerp2);
|
||||
*answerp2 = NULL;
|
||||
*nanswerp2 = 0;
|
||||
*answerp2_malloced = 0;
|
||||
}
|
||||
if (saved_herrno != -1)
|
||||
|
||||
+197
-60
@@ -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 (__glibc_unlikely (statp->qhook || statp->rhook)) {
|
||||
if (anssiz < MAXPACKET && ansp) {
|
||||
/* Always allocate MAXPACKET, callers expect
|
||||
this specific size. */
|
||||
u_char *buf = malloc (MAXPACKET);
|
||||
if (buf == NULL)
|
||||
return (-1);
|
||||
@@ -653,6 +672,77 @@ libresolv_hidden_def (res_nsend)
|
||||
|
||||
/* Private */
|
||||
|
||||
/* 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,
|
||||
@@ -662,11 +752,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];
|
||||
@@ -742,6 +828,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:
|
||||
@@ -778,33 +866,14 @@ send_vc(res_state statp,
|
||||
u_char **thisansp;
|
||||
int *thisresplenp;
|
||||
if ((recvresp1 | recvresp2) == 0 || buf2 == NULL) {
|
||||
/* We have not received any responses
|
||||
yet or we only have one response to
|
||||
receive. */
|
||||
thisanssizp = anssizp;
|
||||
thisansp = anscp ?: ansp;
|
||||
assert (anscp != NULL || ansp2 == NULL);
|
||||
thisresplenp = &resplen;
|
||||
} else {
|
||||
if (*anssizp != MAXPACKET) {
|
||||
/* No buffer allocated for the first
|
||||
reply. We can try to use the rest
|
||||
of the user-provided buffer. */
|
||||
#if _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;
|
||||
@@ -812,10 +881,14 @@ send_vc(res_state statp,
|
||||
anhp = (HEADER *) *thisansp;
|
||||
|
||||
*thisresplenp = rlen;
|
||||
if (rlen > *thisanssizp) {
|
||||
/* Yes, we test ANSCP here. If we have two buffers
|
||||
both will be allocatable. */
|
||||
if (__glibc_likely (anscp != NULL)) {
|
||||
/* Is the answer buffer too small? */
|
||||
if (*thisanssizp < rlen) {
|
||||
/* If the current buffer is not the the static
|
||||
user-supplied buffer then we can reallocate
|
||||
it. */
|
||||
if (thisansp != NULL && thisansp != ansp) {
|
||||
/* Always allocate MAXPACKET, callers expect
|
||||
this specific size. */
|
||||
u_char *newp = malloc (MAXPACKET);
|
||||
if (newp == NULL) {
|
||||
*terrno = ENOMEM;
|
||||
@@ -827,6 +900,9 @@ send_vc(res_state statp,
|
||||
if (thisansp == ansp2)
|
||||
*ansp2_malloced = 1;
|
||||
anhp = (HEADER *) newp;
|
||||
/* A uint16_t can't be larger than MAXPACKET
|
||||
thus it's safe to allocate MAXPACKET but
|
||||
read RLEN bytes instead. */
|
||||
len = rlen;
|
||||
} else {
|
||||
Dprint(statp->options & RES_DEBUG,
|
||||
@@ -990,6 +1066,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,
|
||||
@@ -999,8 +1135,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;
|
||||
@@ -1033,6 +1167,8 @@ 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;
|
||||
@@ -1196,55 +1332,56 @@ send_dg(res_state statp,
|
||||
int *thisresplenp;
|
||||
|
||||
if ((recvresp1 | recvresp2) == 0 || buf2 == NULL) {
|
||||
/* We have not received any responses
|
||||
yet or we only have one response to
|
||||
receive. */
|
||||
thisanssizp = anssizp;
|
||||
thisansp = anscp ?: ansp;
|
||||
assert (anscp != NULL || ansp2 == NULL);
|
||||
thisresplenp = &resplen;
|
||||
} else {
|
||||
if (*anssizp != MAXPACKET) {
|
||||
/* No buffer allocated for the first
|
||||
reply. We can try to use the rest
|
||||
of the user-provided buffer. */
|
||||
#if _STRING_ARCH_unaligned
|
||||
*anssizp2 = orig_anssizp - resplen;
|
||||
*ansp2 = *ansp + resplen;
|
||||
#else
|
||||
int aligned_resplen
|
||||
= ((resplen + __alignof__ (HEADER) - 1)
|
||||
& ~(__alignof__ (HEADER) - 1));
|
||||
*anssizp2 = orig_anssizp - aligned_resplen;
|
||||
*ansp2 = *ansp + aligned_resplen;
|
||||
#endif
|
||||
} else {
|
||||
/* The first reply did not fit into the
|
||||
user-provided buffer. Maybe the second
|
||||
answer will. */
|
||||
*anssizp2 = orig_anssizp;
|
||||
*ansp2 = *ansp;
|
||||
}
|
||||
|
||||
thisanssizp = anssizp2;
|
||||
thisansp = ansp2;
|
||||
thisresplenp = resplen2;
|
||||
}
|
||||
|
||||
if (*thisanssizp < MAXPACKET
|
||||
/* Yes, we test ANSCP here. If we have two buffers
|
||||
both will be allocatable. */
|
||||
&& anscp
|
||||
/* If the current buffer is not the the static
|
||||
user-supplied buffer then we can reallocate
|
||||
it. */
|
||||
&& (thisansp != NULL && thisansp != ansp)
|
||||
#ifdef FIONREAD
|
||||
/* Is the size too small? */
|
||||
&& (ioctl (pfd[0].fd, FIONREAD, thisresplenp) < 0
|
||||
|| *thisanssizp < *thisresplenp)
|
||||
#endif
|
||||
) {
|
||||
/* Always allocate MAXPACKET, callers expect
|
||||
this specific size. */
|
||||
u_char *newp = malloc (MAXPACKET);
|
||||
if (newp != NULL) {
|
||||
*anssizp = MAXPACKET;
|
||||
*thisansp = ans = newp;
|
||||
*thisanssizp = MAXPACKET;
|
||||
*thisansp = newp;
|
||||
if (thisansp == ansp2)
|
||||
*ansp2_malloced = 1;
|
||||
}
|
||||
}
|
||||
/* We could end up with truncation if anscp was NULL
|
||||
(not allowed to change caller's buffer) and the
|
||||
response buffer size is too small. This isn't a
|
||||
reliable way to detect truncation because the ioctl
|
||||
may be an inaccurate report of the UDP message size.
|
||||
Therefore we use this only to issue debug output.
|
||||
To do truncation accurately with UDP we need
|
||||
MSG_TRUNC which is only available on Linux. We
|
||||
can abstract out the Linux-specific feature in the
|
||||
future to detect truncation. */
|
||||
if (__glibc_unlikely (*thisanssizp < *thisresplenp)) {
|
||||
Dprint(statp->options & RES_DEBUG,
|
||||
(stdout, ";; response may be truncated (UDP)\n")
|
||||
);
|
||||
}
|
||||
|
||||
HEADER *anhp = (HEADER *) *thisansp;
|
||||
socklen_t fromlen = sizeof(struct sockaddr_in6);
|
||||
assert (sizeof(from) <= fromlen);
|
||||
|
||||
@@ -57,7 +57,7 @@ tests := tstscanf test_rdwr test-popen tstgetln test-fseek \
|
||||
bug19 bug19a tst-popen2 scanf13 scanf14 scanf15 bug20 bug21 bug22 \
|
||||
scanf16 scanf17 tst-setvbuf1 tst-grouping bug23 bug24 \
|
||||
bug-vfprintf-nargs tst-long-dbl-fphex tst-fphex-wide tst-sprintf3 \
|
||||
bug25 tst-printf-round bug26
|
||||
bug25 tst-printf-round bug23-2 bug23-3 bug23-4 bug26
|
||||
|
||||
test-srcs = tst-unbputc tst-printf
|
||||
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
static const char expected[] = "\
|
||||
\n\
|
||||
a\n\
|
||||
abbcd55\
|
||||
\n\
|
||||
a\n\
|
||||
abbcd55\
|
||||
\n\
|
||||
a\n\
|
||||
abbcd55\
|
||||
\n\
|
||||
a\n\
|
||||
abbcd55\
|
||||
\n\
|
||||
a\n\
|
||||
abbcd55\
|
||||
\n\
|
||||
a\n\
|
||||
abbcd55\
|
||||
\n\
|
||||
a\n\
|
||||
abbcd55\
|
||||
\n\
|
||||
a\n\
|
||||
abbcd55\
|
||||
\n\
|
||||
a\n\
|
||||
abbcd55\
|
||||
\n\
|
||||
a\n\
|
||||
abbcd55\
|
||||
\n\
|
||||
a\n\
|
||||
abbcd55\
|
||||
\n\
|
||||
a\n\
|
||||
abbcd55\
|
||||
\n\
|
||||
a\n\
|
||||
abbcd55%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
char *buf = malloc (strlen (expected) + 1);
|
||||
snprintf (buf, strlen (expected) + 1,
|
||||
"\n%1$s\n" "%1$s" "%2$s" "%2$s" "%3$s" "%4$s" "%5$d" "%5$d"
|
||||
"\n%1$s\n" "%1$s" "%2$s" "%2$s" "%3$s" "%4$s" "%5$d" "%5$d"
|
||||
"\n%1$s\n" "%1$s" "%2$s" "%2$s" "%3$s" "%4$s" "%5$d" "%5$d"
|
||||
"\n%1$s\n" "%1$s" "%2$s" "%2$s" "%3$s" "%4$s" "%5$d" "%5$d"
|
||||
"\n%1$s\n" "%1$s" "%2$s" "%2$s" "%3$s" "%4$s" "%5$d" "%5$d"
|
||||
"\n%1$s\n" "%1$s" "%2$s" "%2$s" "%3$s" "%4$s" "%5$d" "%5$d"
|
||||
"\n%1$s\n" "%1$s" "%2$s" "%2$s" "%3$s" "%4$s" "%5$d" "%5$d"
|
||||
"\n%1$s\n" "%1$s" "%2$s" "%2$s" "%3$s" "%4$s" "%5$d" "%5$d"
|
||||
"\n%1$s\n" "%1$s" "%2$s" "%2$s" "%3$s" "%4$s" "%5$d" "%5$d"
|
||||
"\n%1$s\n" "%1$s" "%2$s" "%2$s" "%3$s" "%4$s" "%5$d" "%5$d"
|
||||
"\n%1$s\n" "%1$s" "%2$s" "%2$s" "%3$s" "%4$s" "%5$d" "%5$d"
|
||||
"\n%1$s\n" "%1$s" "%2$s" "%2$s" "%3$s" "%4$s" "%5$d" "%5$d"
|
||||
"\n%1$s\n" "%1$s" "%2$s" "%2$s" "%3$s" "%4$s" "%5$d" "%5$d"
|
||||
"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n",
|
||||
"a", "b", "c", "d", 5);
|
||||
return strcmp (buf, expected) != 0;
|
||||
}
|
||||
|
||||
#define TEST_FUNCTION do_test ()
|
||||
#include "../test-skeleton.c"
|
||||
@@ -0,0 +1,50 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int
|
||||
do_test (void)
|
||||
{
|
||||
size_t instances = 16384;
|
||||
#define X0 "\n%1$s\n" "%1$s" "%2$s" "%2$s" "%3$s" "%4$s" "%5$d" "%5$d"
|
||||
const char *item = "\na\nabbcd55";
|
||||
#define X3 X0 X0 X0 X0 X0 X0 X0 X0
|
||||
#define X6 X3 X3 X3 X3 X3 X3 X3 X3
|
||||
#define X9 X6 X6 X6 X6 X6 X6 X6 X6
|
||||
#define X12 X9 X9 X9 X9 X9 X9 X9 X9
|
||||
#define X14 X12 X12 X12 X12
|
||||
#define TRAILER "%%%%%%%%%%%%%%%%%%%%%%%%%%"
|
||||
#define TRAILER2 TRAILER TRAILER
|
||||
size_t length = instances * strlen (item) + strlen (TRAILER) + 1;
|
||||
|
||||
char *buf = malloc (length + 1);
|
||||
snprintf (buf, length + 1,
|
||||
X14 TRAILER2 "\n",
|
||||
"a", "b", "c", "d", 5);
|
||||
|
||||
const char *p = buf;
|
||||
size_t i;
|
||||
for (i = 0; i < instances; ++i)
|
||||
{
|
||||
const char *expected;
|
||||
for (expected = item; *expected; ++expected)
|
||||
{
|
||||
if (*p != *expected)
|
||||
{
|
||||
printf ("mismatch at offset %zu (%zu): expected %d, got %d\n",
|
||||
(size_t) (p - buf), i, *expected & 0xFF, *p & 0xFF);
|
||||
return 1;
|
||||
}
|
||||
++p;
|
||||
}
|
||||
}
|
||||
if (strcmp (p, TRAILER "\n") != 0)
|
||||
{
|
||||
printf ("mismatch at trailer: [%s]\n", p);
|
||||
return 1;
|
||||
}
|
||||
free (buf);
|
||||
return 0;
|
||||
}
|
||||
#define TEST_FUNCTION do_test ()
|
||||
#include "../test-skeleton.c"
|
||||
@@ -0,0 +1,31 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/resource.h>
|
||||
|
||||
#define LIMIT 1000000
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
struct rlimit lim;
|
||||
getrlimit (RLIMIT_STACK, &lim);
|
||||
lim.rlim_cur = 1048576;
|
||||
setrlimit (RLIMIT_STACK, &lim);
|
||||
char *fmtstr = malloc (4 * LIMIT + 1);
|
||||
if (fmtstr == NULL)
|
||||
abort ();
|
||||
char *output = malloc (LIMIT + 1);
|
||||
if (output == NULL)
|
||||
abort ();
|
||||
for (size_t i = 0; i < LIMIT; i++)
|
||||
memcpy (fmtstr + 4 * i, "%1$d", 4);
|
||||
fmtstr[4 * LIMIT] = '\0';
|
||||
int ret = snprintf (output, LIMIT + 1, fmtstr, 0);
|
||||
if (ret != LIMIT)
|
||||
abort ();
|
||||
for (size_t i = 0; i < LIMIT; i++)
|
||||
if (output[i] != '0')
|
||||
abort ();
|
||||
return 0;
|
||||
}
|
||||
@@ -233,5 +233,38 @@ main (void)
|
||||
}
|
||||
}
|
||||
|
||||
/* BZ #16618
|
||||
The test will segfault during SSCANF if the buffer overflow
|
||||
is not fixed. The size of `s` is such that it forces the use
|
||||
of malloc internally and this triggers the incorrect computation.
|
||||
Thus the value for SIZE is arbitrariy high enough that malloc
|
||||
is used. */
|
||||
{
|
||||
#define SIZE 131072
|
||||
CHAR *s = malloc ((SIZE + 1) * sizeof (*s));
|
||||
if (s == NULL)
|
||||
abort ();
|
||||
for (size_t i = 0; i < SIZE; i++)
|
||||
s[i] = L('0');
|
||||
s[SIZE] = L('\0');
|
||||
int i = 42;
|
||||
/* Scan multi-digit zero into `i`. */
|
||||
if (SSCANF (s, L("%d"), &i) != 1)
|
||||
{
|
||||
printf ("FAIL: bug16618: SSCANF did not read one input item.\n");
|
||||
result = 1;
|
||||
}
|
||||
if (i != 0)
|
||||
{
|
||||
printf ("FAIL: bug16618: Value of `i` was not zero as expected.\n");
|
||||
result = 1;
|
||||
}
|
||||
free (s);
|
||||
if (result != 1)
|
||||
printf ("PASS: bug16618: Did not crash.\n");
|
||||
#undef SIZE
|
||||
}
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
+38
-2
@@ -263,6 +263,12 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
|
||||
/* For the argument descriptions, which may be allocated on the heap. */
|
||||
void *args_malloced = NULL;
|
||||
|
||||
/* For positional argument handling. */
|
||||
struct printf_spec *specs;
|
||||
|
||||
/* Track if we malloced the SPECS array and thus must free it. */
|
||||
bool specs_malloced = false;
|
||||
|
||||
/* This table maps a character into a number representing a
|
||||
class. In each step there is a destination label for each
|
||||
class. */
|
||||
@@ -1679,8 +1685,8 @@ do_positional:
|
||||
size_t nspecs = 0;
|
||||
/* A more or less arbitrary start value. */
|
||||
size_t nspecs_size = 32 * sizeof (struct printf_spec);
|
||||
struct printf_spec *specs = alloca (nspecs_size);
|
||||
|
||||
specs = alloca (nspecs_size);
|
||||
/* The number of arguments the format string requests. This will
|
||||
determine the size of the array needed to store the argument
|
||||
attributes. */
|
||||
@@ -1721,11 +1727,39 @@ do_positional:
|
||||
if (nspecs * sizeof (*specs) >= nspecs_size)
|
||||
{
|
||||
/* Extend the array of format specifiers. */
|
||||
if (nspecs_size * 2 < nspecs_size)
|
||||
{
|
||||
__set_errno (ENOMEM);
|
||||
done = -1;
|
||||
goto all_done;
|
||||
}
|
||||
struct printf_spec *old = specs;
|
||||
specs = extend_alloca (specs, nspecs_size, 2 * nspecs_size);
|
||||
if (__libc_use_alloca (2 * nspecs_size))
|
||||
specs = extend_alloca (specs, nspecs_size, 2 * nspecs_size);
|
||||
else
|
||||
{
|
||||
nspecs_size *= 2;
|
||||
specs = malloc (nspecs_size);
|
||||
if (specs == NULL)
|
||||
{
|
||||
__set_errno (ENOMEM);
|
||||
specs = old;
|
||||
done = -1;
|
||||
goto all_done;
|
||||
}
|
||||
}
|
||||
|
||||
/* Copy the old array's elements to the new space. */
|
||||
memmove (specs, old, nspecs * sizeof (*specs));
|
||||
|
||||
/* If we had previously malloc'd space for SPECS, then
|
||||
release it after the copy is complete. */
|
||||
if (specs_malloced)
|
||||
free (old);
|
||||
|
||||
/* Now set SPECS_MALLOCED if needed. */
|
||||
if (!__libc_use_alloca (nspecs_size))
|
||||
specs_malloced = true;
|
||||
}
|
||||
|
||||
/* Parse the format specifier. */
|
||||
@@ -2046,6 +2080,8 @@ do_positional:
|
||||
}
|
||||
|
||||
all_done:
|
||||
if (specs_malloced)
|
||||
free (specs);
|
||||
if (__glibc_unlikely (args_malloced != NULL))
|
||||
free (args_malloced);
|
||||
if (__glibc_unlikely (workstart != NULL))
|
||||
|
||||
@@ -272,9 +272,10 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
|
||||
if (__glibc_unlikely (wpsize == wpmax)) \
|
||||
{ \
|
||||
CHAR_T *old = wp; \
|
||||
size_t newsize = (UCHAR_MAX + 1 > 2 * wpmax \
|
||||
? UCHAR_MAX + 1 : 2 * wpmax); \
|
||||
if (use_malloc || !__libc_use_alloca (newsize)) \
|
||||
bool fits = __glibc_likely (wpmax <= SIZE_MAX / sizeof (CHAR_T) / 2); \
|
||||
size_t wpneed = MAX (UCHAR_MAX + 1, 2 * wpmax); \
|
||||
size_t newsize = fits ? wpneed * sizeof (CHAR_T) : SIZE_MAX; \
|
||||
if (!__libc_use_alloca (newsize)) \
|
||||
{ \
|
||||
wp = realloc (use_malloc ? wp : NULL, newsize); \
|
||||
if (wp == NULL) \
|
||||
@@ -286,14 +287,13 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
|
||||
} \
|
||||
if (! use_malloc) \
|
||||
MEMCPY (wp, old, wpsize); \
|
||||
wpmax = newsize; \
|
||||
wpmax = wpneed; \
|
||||
use_malloc = true; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
size_t s = wpmax * sizeof (CHAR_T); \
|
||||
wp = (CHAR_T *) extend_alloca (wp, s, \
|
||||
newsize * sizeof (CHAR_T)); \
|
||||
wp = (CHAR_T *) extend_alloca (wp, s, newsize); \
|
||||
wpmax = s / sizeof (CHAR_T); \
|
||||
if (old != NULL) \
|
||||
MEMCPY (wp, old, wpsize); \
|
||||
|
||||
+7
-5
@@ -66,11 +66,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
|
||||
@@ -157,3 +157,5 @@ tst-tls-atexit-lib.so-no-z-defs = yes
|
||||
|
||||
$(objpfx)tst-tls-atexit: $(shared-thread-library) $(libdl)
|
||||
$(objpfx)tst-tls-atexit.out: $(objpfx)tst-tls-atexit-lib.so
|
||||
|
||||
$(objpfx)tst-makecontext: $(libdl)
|
||||
|
||||
@@ -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));
|
||||
|
||||
|
||||
@@ -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. */
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
+4
-5
@@ -41,6 +41,7 @@
|
||||
#define CONCAT1(a,b) a##b
|
||||
|
||||
#include "../locale/localeinfo.h"
|
||||
#include WEIGHT_H
|
||||
|
||||
/* Track status while looking for sequences in a string. */
|
||||
typedef struct
|
||||
@@ -152,7 +153,6 @@ get_next_seq (coll_seq *seq, int nrules, const unsigned char *rulesets,
|
||||
const USTRING_TYPE *weights, const int32_t *table,
|
||||
const USTRING_TYPE *extra, const int32_t *indirect)
|
||||
{
|
||||
#include WEIGHT_H
|
||||
size_t val = seq->val = 0;
|
||||
int len = seq->len;
|
||||
size_t backw_stop = seq->backw_stop;
|
||||
@@ -194,7 +194,7 @@ get_next_seq (coll_seq *seq, int nrules, const unsigned char *rulesets,
|
||||
|
||||
while (*us != L('\0'))
|
||||
{
|
||||
int32_t tmp = findidx (&us, -1);
|
||||
int32_t tmp = findidx (table, indirect, extra, &us, -1);
|
||||
rulearr[idxmax] = tmp >> 24;
|
||||
idxarr[idxmax] = tmp & 0xffffff;
|
||||
idxcnt = idxmax++;
|
||||
@@ -242,7 +242,6 @@ get_next_seq_nocache (coll_seq *seq, int nrules, const unsigned char *rulesets,
|
||||
const USTRING_TYPE *extra, const int32_t *indirect,
|
||||
int pass)
|
||||
{
|
||||
#include WEIGHT_H
|
||||
size_t val = seq->val = 0;
|
||||
int len = seq->len;
|
||||
size_t backw_stop = seq->backw_stop;
|
||||
@@ -285,7 +284,7 @@ get_next_seq_nocache (coll_seq *seq, int nrules, const unsigned char *rulesets,
|
||||
us = seq->back_us;
|
||||
while (i < backw)
|
||||
{
|
||||
int32_t tmp = findidx (&us, -1);
|
||||
int32_t tmp = findidx (table, indirect, extra, &us, -1);
|
||||
idx = tmp & 0xffffff;
|
||||
i++;
|
||||
}
|
||||
@@ -300,7 +299,7 @@ get_next_seq_nocache (coll_seq *seq, int nrules, const unsigned char *rulesets,
|
||||
|
||||
while (*us != L('\0'))
|
||||
{
|
||||
int32_t tmp = findidx (&us, -1);
|
||||
int32_t tmp = findidx (table, indirect, extra, &us, -1);
|
||||
unsigned char rule = tmp >> 24;
|
||||
prev_idx = idx;
|
||||
idx = tmp & 0xffffff;
|
||||
|
||||
+408
-109
@@ -40,8 +40,24 @@
|
||||
#define CONCAT(a,b) CONCAT1(a,b)
|
||||
#define CONCAT1(a,b) a##b
|
||||
|
||||
#include "../locale/localeinfo.h"
|
||||
/* 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"
|
||||
#include WEIGHT_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 +96,325 @@ 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;
|
||||
int32_t tmp = findidx (l_data->table, l_data->indirect, l_data->extra, us,
|
||||
-1);
|
||||
*rule_idx = tmp >> 24;
|
||||
int32_t idx = tmp & 0xffffff;
|
||||
size_t len = l_data->weights[idx++];
|
||||
|
||||
/* Skip over indices of previous levels. */
|
||||
for (int i = 0; i < pass; i++)
|
||||
{
|
||||
idx += len;
|
||||
len = l_data->weights[idx++];
|
||||
}
|
||||
|
||||
*weight_idx = idx;
|
||||
return len;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
size_t needed = 0;
|
||||
size_t last_needed;
|
||||
|
||||
/* Now the passes over the weights. */
|
||||
for (pass = 0; pass < l_data->nrules; ++pass)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
/* 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)
|
||||
{
|
||||
/* Remove the \1 byte. */
|
||||
if (--needed <= n)
|
||||
dest[needed - 1] = L('\0');
|
||||
}
|
||||
|
||||
/* Return the number of bytes/words we need, but don't count the NUL
|
||||
byte/word at the end. */
|
||||
return needed - 1;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
const USTRING_TYPE *usrc;
|
||||
size_t srclen = STRLEN (src);
|
||||
int32_t *idxarr;
|
||||
unsigned char *rulearr;
|
||||
size_t idxmax;
|
||||
size_t idxcnt;
|
||||
int use_malloc;
|
||||
|
||||
#include WEIGHT_H
|
||||
|
||||
if (nrules == 0)
|
||||
{
|
||||
if (n != 0)
|
||||
STPNCPY (dest, src, MIN (srclen + 1, n));
|
||||
|
||||
return srclen;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
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);
|
||||
|
||||
/* Handle an empty string as a special case. */
|
||||
if (srclen == 0)
|
||||
{
|
||||
if (n != 0)
|
||||
*dest = L('\0');
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* 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)))
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
idxmax = 0;
|
||||
do
|
||||
{
|
||||
int32_t tmp = findidx (&usrc, -1);
|
||||
rulearr[idxmax] = tmp >> 24;
|
||||
idxarr[idxmax] = tmp & 0xffffff;
|
||||
|
||||
++idxmax;
|
||||
}
|
||||
while (*usrc != L('\0'));
|
||||
|
||||
/* 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 +660,87 @@ 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);
|
||||
|
||||
do
|
||||
{
|
||||
int32_t tmp = findidx (l_data.table, l_data.indirect, l_data.extra, &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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -582,9 +582,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
|
||||
|
||||
@@ -78,6 +78,10 @@ struct udphdr
|
||||
#define UDP_CORK 1 /* Never send partially complete segments. */
|
||||
#define UDP_ENCAP 100 /* Set the socket to accept
|
||||
encapsulated packets. */
|
||||
#define UDP_NO_CHECK6_TX 101 /* Disable sending checksum for UDP
|
||||
over IPv6. */
|
||||
#define UDP_NO_CHECK6_RX 102 /* Disable accepting checksum for UDP
|
||||
over IPv6. */
|
||||
|
||||
/* UDP encapsulation types */
|
||||
#define UDP_ENCAP_ESPINUDP_NON_IKE 1 /* draft-ietf-ipsec-nat-t-ike-00/01 */
|
||||
|
||||
+69
-61
@@ -168,9 +168,58 @@ gaih_inet_serv (const char *servicename, const struct gaih_typeproto *tp,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Convert struct hostent to a list of struct gaih_addrtuple objects.
|
||||
h_name is not copied, and the struct hostent object must not be
|
||||
deallocated prematurely. *RESULT must be NULL or a pointer to an
|
||||
object allocated using malloc, which is freed. */
|
||||
static bool
|
||||
convert_hostent_to_gaih_addrtuple (const struct addrinfo *req,
|
||||
int family,
|
||||
struct hostent *h,
|
||||
struct gaih_addrtuple **result)
|
||||
{
|
||||
free (*result);
|
||||
*result = NULL;
|
||||
|
||||
/* Count the number of addresses in h->h_addr_list. */
|
||||
size_t count = 0;
|
||||
for (char **p = h->h_addr_list; *p != NULL; ++p)
|
||||
++count;
|
||||
|
||||
/* Report no data if no addresses are available, or if the incoming
|
||||
address size is larger than what we can store. */
|
||||
if (count == 0 || h->h_length > sizeof (((struct gaih_addrtuple) {}).addr))
|
||||
return true;
|
||||
|
||||
struct gaih_addrtuple *array = calloc (count, sizeof (*array));
|
||||
if (array == NULL)
|
||||
return false;
|
||||
|
||||
for (size_t i = 0; i < count; ++i)
|
||||
{
|
||||
if (family == AF_INET && req->ai_family == AF_INET6)
|
||||
{
|
||||
/* Perform address mapping. */
|
||||
array[i].family = AF_INET6;
|
||||
memcpy(array[i].addr + 3, h->h_addr_list[i], sizeof (uint32_t));
|
||||
array[i].addr[2] = htonl (0xffff);
|
||||
}
|
||||
else
|
||||
{
|
||||
array[i].family = family;
|
||||
memcpy (array[i].addr, h->h_addr_list[i], h->h_length);
|
||||
}
|
||||
array[i].next = array + i + 1;
|
||||
}
|
||||
array[0].name = h->h_name;
|
||||
array[count - 1].next = NULL;
|
||||
|
||||
*result = array;
|
||||
return true;
|
||||
}
|
||||
|
||||
#define gethosts(_family, _type) \
|
||||
{ \
|
||||
int i; \
|
||||
int herrno; \
|
||||
struct hostent th; \
|
||||
struct hostent *h; \
|
||||
@@ -219,36 +268,23 @@ gaih_inet_serv (const char *servicename, const struct gaih_typeproto *tp,
|
||||
} \
|
||||
else if (h != NULL) \
|
||||
{ \
|
||||
for (i = 0; h->h_addr_list[i]; i++) \
|
||||
/* Make sure that addrmem can be freed. */ \
|
||||
if (!malloc_addrmem) \
|
||||
addrmem = NULL; \
|
||||
if (!convert_hostent_to_gaih_addrtuple (req, _family,h, &addrmem)) \
|
||||
{ \
|
||||
if (*pat == NULL) \
|
||||
{ \
|
||||
*pat = __alloca (sizeof (struct gaih_addrtuple)); \
|
||||
(*pat)->scopeid = 0; \
|
||||
} \
|
||||
uint32_t *addr = (*pat)->addr; \
|
||||
(*pat)->next = NULL; \
|
||||
(*pat)->name = i == 0 ? strdupa (h->h_name) : NULL; \
|
||||
if (_family == AF_INET && req->ai_family == AF_INET6) \
|
||||
{ \
|
||||
(*pat)->family = AF_INET6; \
|
||||
addr[3] = *(uint32_t *) h->h_addr_list[i]; \
|
||||
addr[2] = htonl (0xffff); \
|
||||
addr[1] = 0; \
|
||||
addr[0] = 0; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
(*pat)->family = _family; \
|
||||
memcpy (addr, h->h_addr_list[i], sizeof(_type)); \
|
||||
} \
|
||||
pat = &((*pat)->next); \
|
||||
_res.options |= old_res_options & RES_USE_INET6; \
|
||||
result = -EAI_SYSTEM; \
|
||||
goto free_and_return; \
|
||||
} \
|
||||
*pat = addrmem; \
|
||||
/* The conversion uses malloc unconditionally. */ \
|
||||
malloc_addrmem = true; \
|
||||
\
|
||||
if (localcanon != NULL && canon == NULL) \
|
||||
canon = strdupa (localcanon); \
|
||||
\
|
||||
if (_family == AF_INET6 && i > 0) \
|
||||
if (_family == AF_INET6 && *pat != NULL) \
|
||||
got_ipv6 = true; \
|
||||
} \
|
||||
}
|
||||
@@ -612,44 +648,16 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||||
{
|
||||
if (h != NULL)
|
||||
{
|
||||
int i;
|
||||
/* We found data, count the number of addresses. */
|
||||
for (i = 0; h->h_addr_list[i]; ++i)
|
||||
;
|
||||
if (i > 0 && *pat != NULL)
|
||||
--i;
|
||||
|
||||
if (__libc_use_alloca (alloca_used
|
||||
+ i * sizeof (struct gaih_addrtuple)))
|
||||
addrmem = alloca_account (i * sizeof (struct gaih_addrtuple),
|
||||
alloca_used);
|
||||
else
|
||||
/* We found data, convert it. */
|
||||
if (!convert_hostent_to_gaih_addrtuple
|
||||
(req, AF_INET, h, &addrmem))
|
||||
{
|
||||
addrmem = malloc (i
|
||||
* sizeof (struct gaih_addrtuple));
|
||||
if (addrmem == NULL)
|
||||
{
|
||||
result = -EAI_MEMORY;
|
||||
goto free_and_return;
|
||||
}
|
||||
malloc_addrmem = true;
|
||||
}
|
||||
|
||||
/* Now convert it into the list. */
|
||||
struct gaih_addrtuple *addrfree = addrmem;
|
||||
for (i = 0; h->h_addr_list[i]; ++i)
|
||||
{
|
||||
if (*pat == NULL)
|
||||
{
|
||||
*pat = addrfree++;
|
||||
(*pat)->scopeid = 0;
|
||||
}
|
||||
(*pat)->next = NULL;
|
||||
(*pat)->family = AF_INET;
|
||||
memcpy ((*pat)->addr, h->h_addr_list[i],
|
||||
h->h_length);
|
||||
pat = &((*pat)->next);
|
||||
result = -EAI_MEMORY;
|
||||
goto free_and_return;
|
||||
}
|
||||
*pat = addrmem;
|
||||
/* The conversion uses malloc unconditionally. */
|
||||
malloc_addrmem = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
@@ -19,6 +19,9 @@
|
||||
# error "Never include <bits/link.h> directly; use <link.h> instead."
|
||||
#endif
|
||||
|
||||
#if defined HAVE_S390_VX_ASM_SUPPORT
|
||||
typedef char La_s390_vr[16];
|
||||
#endif
|
||||
|
||||
#if __ELF_NATIVE_CLASS == 32
|
||||
|
||||
@@ -32,6 +35,16 @@ typedef struct La_s390_32_regs
|
||||
uint32_t lr_r6;
|
||||
double lr_fp0;
|
||||
double lr_fp2;
|
||||
# if defined HAVE_S390_VX_ASM_SUPPORT
|
||||
La_s390_vr lr_v24;
|
||||
La_s390_vr lr_v25;
|
||||
La_s390_vr lr_v26;
|
||||
La_s390_vr lr_v27;
|
||||
La_s390_vr lr_v28;
|
||||
La_s390_vr lr_v29;
|
||||
La_s390_vr lr_v30;
|
||||
La_s390_vr lr_v31;
|
||||
# endif
|
||||
} La_s390_32_regs;
|
||||
|
||||
/* Return values for calls from PLT on s390-32. */
|
||||
@@ -40,6 +53,9 @@ typedef struct La_s390_32_retval
|
||||
uint32_t lrv_r2;
|
||||
uint32_t lrv_r3;
|
||||
double lrv_fp0;
|
||||
# if defined HAVE_S390_VX_ASM_SUPPORT
|
||||
La_s390_vr lrv_v24;
|
||||
# endif
|
||||
} La_s390_32_retval;
|
||||
|
||||
|
||||
@@ -77,6 +93,16 @@ typedef struct La_s390_64_regs
|
||||
double lr_fp2;
|
||||
double lr_fp4;
|
||||
double lr_fp6;
|
||||
# if defined HAVE_S390_VX_ASM_SUPPORT
|
||||
La_s390_vr lr_v24;
|
||||
La_s390_vr lr_v25;
|
||||
La_s390_vr lr_v26;
|
||||
La_s390_vr lr_v27;
|
||||
La_s390_vr lr_v28;
|
||||
La_s390_vr lr_v29;
|
||||
La_s390_vr lr_v30;
|
||||
La_s390_vr lr_v31;
|
||||
# endif
|
||||
} La_s390_64_regs;
|
||||
|
||||
/* Return values for calls from PLT on s390-64. */
|
||||
@@ -84,6 +110,9 @@ typedef struct La_s390_64_retval
|
||||
{
|
||||
uint64_t lrv_r2;
|
||||
double lrv_fp0;
|
||||
# if defined HAVE_S390_VX_ASM_SUPPORT
|
||||
La_s390_vr lrv_v24;
|
||||
# endif
|
||||
} La_s390_64_retval;
|
||||
|
||||
|
||||
|
||||
Vendored
+41
@@ -104,5 +104,46 @@ if test "$enable_lock_elision" = yes && test "$libc_cv_gcc_builtin_tbegin" = no
|
||||
critic_missing="$critic_missing The used GCC has no support for __builtin_tbegin, which is needed for lock-elision on target S390."
|
||||
fi
|
||||
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for S390 vector instruction support" >&5
|
||||
$as_echo_n "checking for S390 vector instruction support... " >&6; }
|
||||
if ${libc_cv_asm_s390_vx+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
cat > conftest.c <<\EOF
|
||||
void testvecinsn ()
|
||||
{
|
||||
__asm__ (".machine \"z13\" \n\t"
|
||||
".machinemode \"zarch_nohighgprs\" \n\t"
|
||||
"vistrbs %%v16,%%v17 \n\t"
|
||||
"locghie %%r1,0" : :);
|
||||
}
|
||||
EOF
|
||||
if { ac_try='${CC-cc} --shared conftest.c -o conftest.o &> /dev/null'
|
||||
{ { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
|
||||
(eval $ac_try) 2>&5
|
||||
ac_status=$?
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
|
||||
test $ac_status = 0; }; } ;
|
||||
then
|
||||
libc_cv_asm_s390_vx=yes
|
||||
else
|
||||
libc_cv_asm_s390_vx=no
|
||||
fi
|
||||
rm -f conftest*
|
||||
fi
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_asm_s390_vx" >&5
|
||||
$as_echo "$libc_cv_asm_s390_vx" >&6; }
|
||||
|
||||
if test "$libc_cv_asm_s390_vx" = yes ;
|
||||
then
|
||||
$as_echo "#define HAVE_S390_VX_ASM_SUPPORT 1" >>confdefs.h
|
||||
|
||||
else
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Use binutils with vector-support in order to use optimized implementations." >&5
|
||||
$as_echo "$as_me: WARNING: Use binutils with vector-support in order to use optimized implementations." >&2;}
|
||||
fi
|
||||
|
||||
|
||||
test -n "$critic_missing" && as_fn_error $? "
|
||||
*** $critic_missing" "$LINENO" 5
|
||||
|
||||
@@ -36,5 +36,34 @@ if test "$enable_lock_elision" = yes && test "$libc_cv_gcc_builtin_tbegin" = no
|
||||
critic_missing="$critic_missing The used GCC has no support for __builtin_tbegin, which is needed for lock-elision on target S390."
|
||||
fi
|
||||
|
||||
|
||||
AC_CACHE_CHECK(for S390 vector instruction support, libc_cv_asm_s390_vx, [dnl
|
||||
cat > conftest.c <<\EOF
|
||||
void testvecinsn ()
|
||||
{
|
||||
__asm__ (".machine \"z13\" \n\t"
|
||||
".machinemode \"zarch_nohighgprs\" \n\t"
|
||||
"vistrbs %%v16,%%v17 \n\t"
|
||||
"locghie %%r1,0" : :);
|
||||
}
|
||||
EOF
|
||||
dnl
|
||||
dnl test, if assembler supports S390 vector instructions
|
||||
if AC_TRY_COMMAND([${CC-cc} --shared conftest.c -o conftest.o &> /dev/null]) ;
|
||||
then
|
||||
libc_cv_asm_s390_vx=yes
|
||||
else
|
||||
libc_cv_asm_s390_vx=no
|
||||
fi
|
||||
rm -f conftest* ])
|
||||
|
||||
if test "$libc_cv_asm_s390_vx" = yes ;
|
||||
then
|
||||
AC_DEFINE(HAVE_S390_VX_ASM_SUPPORT)
|
||||
else
|
||||
AC_MSG_WARN([Use binutils with vector-support in order to use optimized implementations.])
|
||||
fi
|
||||
|
||||
|
||||
test -n "$critic_missing" && AC_MSG_ERROR([
|
||||
*** $critic_missing])
|
||||
|
||||
@@ -46,11 +46,11 @@
|
||||
#if !defined PROCINFO_DECL && defined SHARED
|
||||
._dl_s390_cap_flags
|
||||
#else
|
||||
PROCINFO_CLASS const char _dl_s390_cap_flags[11][9]
|
||||
PROCINFO_CLASS const char _dl_s390_cap_flags[12][9]
|
||||
#endif
|
||||
#ifndef PROCINFO_DECL
|
||||
= {
|
||||
"esan3", "zarch", "stfle", "msa", "ldisp", "eimm", "dfp", "edat", "etf3eh", "highgprs", "te"
|
||||
"esan3", "zarch", "stfle", "msa", "ldisp", "eimm", "dfp", "edat", "etf3eh", "highgprs", "te", "vx"
|
||||
}
|
||||
#endif
|
||||
#if !defined SHARED || defined PROCINFO_DECL
|
||||
@@ -62,11 +62,11 @@ PROCINFO_CLASS const char _dl_s390_cap_flags[11][9]
|
||||
#if !defined PROCINFO_DECL && defined SHARED
|
||||
._dl_s390_platforms
|
||||
#else
|
||||
PROCINFO_CLASS const char _dl_s390_platforms[7][7]
|
||||
PROCINFO_CLASS const char _dl_s390_platforms[8][7]
|
||||
#endif
|
||||
#ifndef PROCINFO_DECL
|
||||
= {
|
||||
"g5", "z900", "z990", "z9-109", "z10", "z196", "zEC12"
|
||||
"g5", "z900", "z990", "z9-109", "z10", "z196", "zEC12", "z13"
|
||||
}
|
||||
#endif
|
||||
#if !defined SHARED || defined PROCINFO_DECL
|
||||
|
||||
@@ -21,9 +21,9 @@
|
||||
#define _DL_PROCINFO_H 1
|
||||
#include <ldsodefs.h>
|
||||
|
||||
#define _DL_HWCAP_COUNT 10
|
||||
#define _DL_HWCAP_COUNT 12
|
||||
|
||||
#define _DL_PLATFORMS_COUNT 5
|
||||
#define _DL_PLATFORMS_COUNT 8
|
||||
|
||||
/* The kernel provides up to 32 capability bits with elf_hwcap. */
|
||||
#define _DL_FIRST_PLATFORM 32
|
||||
@@ -50,6 +50,7 @@ enum
|
||||
HWCAP_S390_ETF3EH = 1 << 8,
|
||||
HWCAP_S390_HIGH_GPRS = 1 << 9,
|
||||
HWCAP_S390_TE = 1 << 10,
|
||||
HWCAP_S390_VX = 1 << 11,
|
||||
};
|
||||
|
||||
#define HWCAP_IMPORTANT (HWCAP_S390_ZARCH | HWCAP_S390_LDISP \
|
||||
|
||||
@@ -89,6 +89,11 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
|
||||
{
|
||||
extern void _dl_runtime_resolve (Elf32_Word);
|
||||
extern void _dl_runtime_profile (Elf32_Word);
|
||||
#if defined HAVE_S390_VX_ASM_SUPPORT
|
||||
extern void _dl_runtime_resolve_vx (Elf32_Word);
|
||||
extern void _dl_runtime_profile_vx (Elf32_Word);
|
||||
#endif
|
||||
|
||||
|
||||
if (l->l_info[DT_JMPREL] && lazy)
|
||||
{
|
||||
@@ -116,7 +121,14 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
|
||||
end in this function. */
|
||||
if (__glibc_unlikely (profile))
|
||||
{
|
||||
#if defined HAVE_S390_VX_ASM_SUPPORT
|
||||
if (GLRO(dl_hwcap) & HWCAP_S390_VX)
|
||||
got[2] = (Elf32_Addr) &_dl_runtime_profile_vx;
|
||||
else
|
||||
got[2] = (Elf32_Addr) &_dl_runtime_profile;
|
||||
#else
|
||||
got[2] = (Elf32_Addr) &_dl_runtime_profile;
|
||||
#endif
|
||||
|
||||
if (GLRO(dl_profile) != NULL
|
||||
&& _dl_name_match_p (GLRO(dl_profile), l))
|
||||
@@ -125,9 +137,18 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
|
||||
GL(dl_profile_map) = l;
|
||||
}
|
||||
else
|
||||
/* This function will get called to fix up the GOT entry indicated by
|
||||
the offset on the stack, and then jump to the resolved address. */
|
||||
got[2] = (Elf32_Addr) &_dl_runtime_resolve;
|
||||
{
|
||||
/* This function will get called to fix up the GOT entry indicated by
|
||||
the offset on the stack, and then jump to the resolved address. */
|
||||
#if defined HAVE_S390_VX_ASM_SUPPORT
|
||||
if (GLRO(dl_hwcap) & HWCAP_S390_VX)
|
||||
got[2] = (Elf32_Addr) &_dl_runtime_resolve_vx;
|
||||
else
|
||||
got[2] = (Elf32_Addr) &_dl_runtime_resolve;
|
||||
#else
|
||||
got[2] = (Elf32_Addr) &_dl_runtime_resolve;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
return lazy;
|
||||
|
||||
@@ -16,130 +16,18 @@
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
/* This code is used in dl-runtime.c to call the `fixup' function
|
||||
and then redirect to the address it returns. */
|
||||
|
||||
/* The PLT stubs will call _dl_runtime_resolve/_dl_runtime_profile
|
||||
* with the following linkage:
|
||||
* r2 - r6 : parameter registers
|
||||
* f0, f2 : floating point parameter registers
|
||||
* 24(r15), 28(r15) : PLT arguments PLT1, PLT2
|
||||
* 96(r15) : additional stack parameters
|
||||
* The normal clobber rules for function calls apply:
|
||||
* r0 - r5 : call clobbered
|
||||
* r6 - r13 : call saved
|
||||
* r14 : return address (call clobbered)
|
||||
* r15 : stack pointer (call saved)
|
||||
* f4, f6 : call saved
|
||||
* f0 - f3, f5, f7 - f15 : call clobbered
|
||||
*/
|
||||
|
||||
#include <sysdep.h>
|
||||
|
||||
.text
|
||||
.globl _dl_runtime_resolve
|
||||
.type _dl_runtime_resolve, @function
|
||||
cfi_startproc
|
||||
.align 16
|
||||
_dl_runtime_resolve:
|
||||
stm %r2,%r5,32(%r15) # save registers
|
||||
st %r14,8(%r15)
|
||||
cfi_offset (r14, -88)
|
||||
lr %r0,%r15 # create stack frame
|
||||
ahi %r15,-96
|
||||
cfi_adjust_cfa_offset (96)
|
||||
st 0,0(%r15)
|
||||
lm %r2,%r3,120(%r15) # load args saved by PLT
|
||||
basr %r1,0
|
||||
0: l %r14,1f-0b(%r1)
|
||||
bas %r14,0(%r14,%r1) # call resolver
|
||||
lr %r1,%r2 # function addr returned in r2
|
||||
ahi %r15,96 # remove stack frame
|
||||
cfi_adjust_cfa_offset (-96)
|
||||
l %r14,8(15) # restore registers
|
||||
lm %r2,%r5,32(%r15)
|
||||
br %r1
|
||||
1: .long _dl_fixup - 0b
|
||||
cfi_endproc
|
||||
.size _dl_runtime_resolve, .-_dl_runtime_resolve
|
||||
/* Create variant of _dl_runtime_resolve/profile for machines before z13.
|
||||
No vector registers are saved/restored. */
|
||||
#include <dl-trampoline.h>
|
||||
|
||||
|
||||
#ifndef PROF
|
||||
.globl _dl_runtime_profile
|
||||
.type _dl_runtime_profile, @function
|
||||
cfi_startproc
|
||||
.align 16
|
||||
_dl_runtime_profile:
|
||||
stm %r2,%r6,32(%r15) # save registers
|
||||
std %f0,56(%r15)
|
||||
std %f2,64(%r15)
|
||||
st %r6,8(%r15)
|
||||
st %r12,12(%r15)
|
||||
st %r14,16(%r15)
|
||||
cfi_offset (r6, -64)
|
||||
cfi_offset (f0, -40)
|
||||
cfi_offset (f2, -32)
|
||||
cfi_offset (r12, -84)
|
||||
cfi_offset (r14, -80)
|
||||
lr %r12,%r15 # create stack frame
|
||||
cfi_def_cfa_register (12)
|
||||
ahi %r15,-96
|
||||
st %r12,0(%r15)
|
||||
lm %r2,%r3,24(%r12) # load arguments saved by PLT
|
||||
lr %r4,%r14 # return address as third parameter
|
||||
basr %r1,0
|
||||
0: l %r14,6f-0b(%r1)
|
||||
la %r5,32(%r12) # pointer to struct La_s390_32_regs
|
||||
la %r6,20(%r12) # long int * framesize
|
||||
bas %r14,0(%r14,%r1) # call resolver
|
||||
lr %r1,%r2 # function addr returned in r2
|
||||
icm %r0,15,20(%r12) # load & test framesize
|
||||
jnm 2f
|
||||
|
||||
lm %r2,%r6,32(%r12)
|
||||
ld %f0,56(%r12)
|
||||
ld %f2,64(%r12)
|
||||
lr %r15,%r12 # remove stack frame
|
||||
cfi_def_cfa_register (15)
|
||||
l %r14,16(%r15) # restore registers
|
||||
l %r12,12(%r15)
|
||||
br %r1 # tail-call to the resolved function
|
||||
|
||||
cfi_def_cfa_register (12)
|
||||
2: jz 4f # framesize == 0 ?
|
||||
ahi %r0,7 # align framesize to 8
|
||||
lhi %r2,-8
|
||||
nr %r0,%r2
|
||||
slr %r15,%r0 # make room for framesize bytes
|
||||
st %r12,0(%r15)
|
||||
la %r2,96(%r15)
|
||||
la %r3,96(%r12)
|
||||
srl %r0,3
|
||||
3: mvc 0(8,%r2),0(%r3) # copy additional parameters
|
||||
la %r2,8(%r2)
|
||||
la %r3,8(%r3)
|
||||
brct %r0,3b
|
||||
4: lm %r2,%r6,32(%r12) # load register parameters
|
||||
ld %f0,56(%r12)
|
||||
ld %f2,64(%r12)
|
||||
basr %r14,%r1 # call resolved function
|
||||
stm %r2,%r3,72(%r12)
|
||||
std %f0,80(%r12)
|
||||
lm %r2,%r3,24(%r12) # load arguments saved by PLT
|
||||
basr %r1,0
|
||||
5: l %r14,7f-5b(%r1)
|
||||
la %r4,32(%r12) # pointer to struct La_s390_32_regs
|
||||
la %r5,72(%r12) # pointer to struct La_s390_32_retval
|
||||
basr %r14,%r1 # call _dl_call_pltexit
|
||||
|
||||
lr %r15,%r12 # remove stack frame
|
||||
cfi_def_cfa_register (15)
|
||||
l %r14,16(%r15) # restore registers
|
||||
l %r12,12(%r15)
|
||||
br %r14
|
||||
|
||||
6: .long _dl_profile_fixup - 0b
|
||||
7: .long _dl_call_pltexit - 5b
|
||||
cfi_endproc
|
||||
.size _dl_runtime_profile, .-_dl_runtime_profile
|
||||
#if defined HAVE_S390_VX_ASM_SUPPORT
|
||||
/* Create variant of _dl_runtime_resolve/profile for z13 and newer.
|
||||
The vector registers are saved/restored, too.*/
|
||||
# define _dl_runtime_resolve _dl_runtime_resolve_vx
|
||||
# define _dl_runtime_profile _dl_runtime_profile_vx
|
||||
# define RESTORE_VRS
|
||||
# include <dl-trampoline.h>
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,231 @@
|
||||
/* PLT trampolines. s390 version.
|
||||
Copyright (C) 2016 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
/* This code is used in dl-runtime.c to call the `fixup' function
|
||||
and then redirect to the address it returns. */
|
||||
|
||||
/* The PLT stubs will call _dl_runtime_resolve/_dl_runtime_profile
|
||||
* with the following linkage:
|
||||
* r2 - r6 : parameter registers
|
||||
* f0, f2 : floating point parameter registers
|
||||
* v24, v26, v28, v30, v25, v27, v29, v31 : vector parameter registers
|
||||
* 24(r15), 28(r15) : PLT arguments PLT1, PLT2
|
||||
* 96(r15) : additional stack parameters
|
||||
* The normal clobber rules for function calls apply:
|
||||
* r0 - r5 : call clobbered
|
||||
* r6 - r13 : call saved
|
||||
* r14 : return address (call clobbered)
|
||||
* r15 : stack pointer (call saved)
|
||||
* f4, f6 : call saved
|
||||
* f0 - f3, f5, f7 - f15 : call clobbered
|
||||
* v0 - v3, v5, v7 - v15 : bytes 0-7 overlap with fprs: call clobbered
|
||||
bytes 8-15: call clobbered
|
||||
* v4, v6 : bytes 0-7 overlap with f4, f6: call saved
|
||||
bytes 8-15: call clobbered
|
||||
* v16 - v31 : call clobbered
|
||||
*/
|
||||
|
||||
|
||||
.globl _dl_runtime_resolve
|
||||
.type _dl_runtime_resolve, @function
|
||||
cfi_startproc
|
||||
.align 16
|
||||
_dl_runtime_resolve:
|
||||
stm %r2,%r5,32(%r15) # save registers
|
||||
cfi_offset (r2, -64)
|
||||
cfi_offset (r3, -60)
|
||||
cfi_offset (r4, -56)
|
||||
cfi_offset (r5, -52)
|
||||
std %f0,56(%r15)
|
||||
cfi_offset (f0, -40)
|
||||
std %f2,64(%r15)
|
||||
cfi_offset (f2, -32)
|
||||
st %r14,8(%r15)
|
||||
cfi_offset (r14, -88)
|
||||
lr %r0,%r15
|
||||
lm %r2,%r3,24(%r15) # load args saved by PLT
|
||||
#ifdef RESTORE_VRS
|
||||
ahi %r15,-224 # create stack frame
|
||||
cfi_adjust_cfa_offset (224)
|
||||
.machine push
|
||||
.machine "z13"
|
||||
.machinemode "zarch_nohighgprs"
|
||||
vstm %v24,%v31,96(%r15) # store call-clobbered vr arguments
|
||||
cfi_offset (v24, -224)
|
||||
cfi_offset (v25, -208)
|
||||
cfi_offset (v26, -192)
|
||||
cfi_offset (v27, -176)
|
||||
cfi_offset (v28, -160)
|
||||
cfi_offset (v29, -144)
|
||||
cfi_offset (v30, -128)
|
||||
cfi_offset (v31, -112)
|
||||
.machine pop
|
||||
#else
|
||||
ahi %r15,-96 # create stack frame
|
||||
cfi_adjust_cfa_offset (96)
|
||||
#endif
|
||||
st %r0,0(%r15) # write backchain
|
||||
basr %r1,0
|
||||
0: l %r14,1f-0b(%r1)
|
||||
bas %r14,0(%r14,%r1) # call _dl_fixup
|
||||
lr %r1,%r2 # function addr returned in r2
|
||||
#ifdef RESTORE_VRS
|
||||
.machine push
|
||||
.machine "z13"
|
||||
.machinemode "zarch_nohighgprs"
|
||||
vlm %v24,%v31,96(%r15) # restore vector registers
|
||||
.machine pop
|
||||
ahi %r15,224 # remove stack frame
|
||||
cfi_adjust_cfa_offset (-224)
|
||||
#else
|
||||
ahi %r15,96 # remove stack frame
|
||||
cfi_adjust_cfa_offset (-96)
|
||||
#endif
|
||||
l %r14,8(15) # restore registers
|
||||
ld %f0,56(%r15)
|
||||
ld %f2,64(%r15)
|
||||
lm %r2,%r5,32(%r15)
|
||||
br %r1
|
||||
1: .long _dl_fixup - 0b
|
||||
cfi_endproc
|
||||
.size _dl_runtime_resolve, .-_dl_runtime_resolve
|
||||
|
||||
|
||||
#ifndef PROF
|
||||
.globl _dl_runtime_profile
|
||||
.type _dl_runtime_profile, @function
|
||||
cfi_startproc
|
||||
.align 16
|
||||
_dl_runtime_profile:
|
||||
st %r12,12(%r15) # r12 is used as backup of r15
|
||||
cfi_offset (r12, -84)
|
||||
st %r14,16(%r15)
|
||||
cfi_offset (r14, -80)
|
||||
lr %r12,%r15 # backup stack pointer
|
||||
cfi_def_cfa_register (12)
|
||||
ahi %r15,-264 # create stack frame:
|
||||
# 96 + sizeof(La_s390_32_regs)
|
||||
st %r12,0(%r15) # save backchain
|
||||
|
||||
stm %r2,%r6,96(%r15) # save registers
|
||||
cfi_offset (r2, -264) # + r6 needed as arg for
|
||||
cfi_offset (r3, -260) # _dl_profile_fixup
|
||||
cfi_offset (r4, -256)
|
||||
cfi_offset (r5, -252)
|
||||
cfi_offset (r6, -248)
|
||||
std %f0,120(%r15)
|
||||
cfi_offset (f0, -240)
|
||||
std %f2,128(%r15)
|
||||
cfi_offset (f2, -232)
|
||||
#ifdef RESTORE_VRS
|
||||
.machine push
|
||||
.machine "z13"
|
||||
.machinemode "zarch_nohighgprs"
|
||||
vstm %v24,%v31,136(%r15) # store call-clobbered vr arguments
|
||||
cfi_offset (v24, -224)
|
||||
cfi_offset (v25, -208)
|
||||
cfi_offset (v26, -192)
|
||||
cfi_offset (v27, -176)
|
||||
cfi_offset (v28, -160)
|
||||
cfi_offset (v29, -144)
|
||||
cfi_offset (v30, -128)
|
||||
cfi_offset (v31, -112)
|
||||
.machine pop
|
||||
#endif
|
||||
|
||||
lm %r2,%r3,24(%r12) # load arguments saved by PLT
|
||||
lr %r4,%r14 # return address as third parameter
|
||||
basr %r1,0
|
||||
0: l %r14,6f-0b(%r1)
|
||||
la %r5,96(%r15) # pointer to struct La_s390_32_regs
|
||||
la %r6,20(%r12) # long int * framesize
|
||||
bas %r14,0(%r14,%r1) # call resolver
|
||||
lr %r1,%r2 # function addr returned in r2
|
||||
ld %f0,120(%r15) # restore call-clobbered arg fprs
|
||||
ld %f2,128(%r15)
|
||||
#ifdef RESTORE_VRS
|
||||
.machine push
|
||||
.machine "z13"
|
||||
.machinemode "zarch_nohighgprs"
|
||||
vlm %v24,%v31,136(%r15) # restore call-clobbered arg vrs
|
||||
.machine pop
|
||||
#endif
|
||||
icm %r0,15,20(%r12) # load & test framesize
|
||||
jnm 2f
|
||||
|
||||
lm %r2,%r6,96(%r15) # framesize < 0 means no pltexit call
|
||||
# so we can do a tail call without
|
||||
# copying the arg overflow area
|
||||
lr %r15,%r12 # remove stack frame
|
||||
cfi_def_cfa_register (15)
|
||||
l %r14,16(%r15) # restore registers
|
||||
l %r12,12(%r15)
|
||||
br %r1 # tail-call to the resolved function
|
||||
|
||||
cfi_def_cfa_register (12)
|
||||
2: la %r4,96(%r15) # pointer to struct La_s390_32_regs
|
||||
st %r4,32(%r12)
|
||||
jz 4f # framesize == 0 ?
|
||||
ahi %r0,7 # align framesize to 8
|
||||
lhi %r2,-8
|
||||
nr %r0,%r2
|
||||
slr %r15,%r0 # make room for framesize bytes
|
||||
st %r12,0(%r15) # save backchain
|
||||
la %r2,96(%r15)
|
||||
la %r3,96(%r12)
|
||||
srl %r0,3
|
||||
3: mvc 0(8,%r2),0(%r3) # copy additional parameters
|
||||
la %r2,8(%r2)
|
||||
la %r3,8(%r3)
|
||||
brct %r0,3b
|
||||
4: lm %r2,%r6,0(%r4) # load register parameters
|
||||
basr %r14,%r1 # call resolved function
|
||||
stm %r2,%r3,40(%r12) # store return values r2, r3, f0
|
||||
std %f0,48(%r12) # to struct La_s390_32_retval
|
||||
#ifdef RESTORE_VRS
|
||||
.machine push
|
||||
.machine "z13"
|
||||
vst %v24,56(%r12) # store return value v24
|
||||
.machine pop
|
||||
#endif
|
||||
lm %r2,%r4,24(%r12) # r2, r3: load arguments saved by PLT
|
||||
# r4: pointer to struct La_s390_32_regs
|
||||
basr %r1,0
|
||||
5: l %r14,7f-5b(%r1)
|
||||
la %r5,40(%r12) # pointer to struct La_s390_32_retval
|
||||
bas %r14,0(%r14,%r1) # call _dl_call_pltexit
|
||||
|
||||
lr %r15,%r12 # remove stack frame
|
||||
cfi_def_cfa_register (15)
|
||||
l %r14,16(%r15) # restore registers
|
||||
l %r12,12(%r15)
|
||||
lm %r2,%r3,40(%r15) # restore return values
|
||||
ld %f0,48(%r15)
|
||||
#ifdef RESTORE_VRS
|
||||
.machine push
|
||||
.machine "z13"
|
||||
vl %v24,56(%r15) # restore return value v24
|
||||
.machine pop
|
||||
#endif
|
||||
br %r14
|
||||
|
||||
6: .long _dl_profile_fixup - 0b
|
||||
7: .long _dl_call_pltexit - 5b
|
||||
cfi_endproc
|
||||
.size _dl_runtime_profile, .-_dl_runtime_profile
|
||||
#endif
|
||||
@@ -26,6 +26,7 @@
|
||||
#include <sys/param.h>
|
||||
#include <string.h>
|
||||
#include <link.h>
|
||||
#include <sysdeps/s390/dl-procinfo.h>
|
||||
#include <dl-irel.h>
|
||||
|
||||
#define ELF_MACHINE_IRELATIVE R_390_IRELATIVE
|
||||
@@ -78,6 +79,10 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
|
||||
{
|
||||
extern void _dl_runtime_resolve (Elf64_Word);
|
||||
extern void _dl_runtime_profile (Elf64_Word);
|
||||
#if defined HAVE_S390_VX_ASM_SUPPORT
|
||||
extern void _dl_runtime_resolve_vx (Elf64_Word);
|
||||
extern void _dl_runtime_profile_vx (Elf64_Word);
|
||||
#endif
|
||||
|
||||
if (l->l_info[DT_JMPREL] && lazy)
|
||||
{
|
||||
@@ -105,7 +110,14 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
|
||||
end in this function. */
|
||||
if (__glibc_unlikely (profile))
|
||||
{
|
||||
#if defined HAVE_S390_VX_ASM_SUPPORT
|
||||
if (GLRO(dl_hwcap) & HWCAP_S390_VX)
|
||||
got[2] = (Elf64_Addr) &_dl_runtime_profile_vx;
|
||||
else
|
||||
got[2] = (Elf64_Addr) &_dl_runtime_profile;
|
||||
#else
|
||||
got[2] = (Elf64_Addr) &_dl_runtime_profile;
|
||||
#endif
|
||||
|
||||
if (GLRO(dl_profile) != NULL
|
||||
&& _dl_name_match_p (GLRO(dl_profile), l))
|
||||
@@ -114,9 +126,18 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
|
||||
GL(dl_profile_map) = l;
|
||||
}
|
||||
else
|
||||
/* This function will get called to fix up the GOT entry indicated by
|
||||
the offset on the stack, and then jump to the resolved address. */
|
||||
got[2] = (Elf64_Addr) &_dl_runtime_resolve;
|
||||
{
|
||||
/* This function will get called to fix up the GOT entry indicated by
|
||||
the offset on the stack, and then jump to the resolved address. */
|
||||
#if defined HAVE_S390_VX_ASM_SUPPORT
|
||||
if (GLRO(dl_hwcap) & HWCAP_S390_VX)
|
||||
got[2] = (Elf64_Addr) &_dl_runtime_resolve_vx;
|
||||
else
|
||||
got[2] = (Elf64_Addr) &_dl_runtime_resolve;
|
||||
#else
|
||||
got[2] = (Elf64_Addr) &_dl_runtime_resolve;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
return lazy;
|
||||
|
||||
@@ -16,126 +16,18 @@
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
/* The PLT stubs will call _dl_runtime_resolve/_dl_runtime_profile
|
||||
* with the following linkage:
|
||||
* r2 - r6 : parameter registers
|
||||
* f0, f2, f4, f6 : floating point parameter registers
|
||||
* 48(r15), 56(r15) : PLT arguments PLT1, PLT2
|
||||
* 160(r15) : additional stack parameters
|
||||
* The normal clobber rules for function calls apply:
|
||||
* r0 - r5 : call clobbered
|
||||
* r6 - r13 : call saved
|
||||
* r14 : return address (call clobbered)
|
||||
* r15 : stack pointer (call saved)
|
||||
* f1, f3, f5, f7 : call saved
|
||||
* f0 - f3, f5, f7 - f15 : call clobbered
|
||||
*/
|
||||
|
||||
#include <sysdep.h>
|
||||
|
||||
.text
|
||||
.globl _dl_runtime_resolve
|
||||
.type _dl_runtime_resolve, @function
|
||||
cfi_startproc
|
||||
.align 16
|
||||
_dl_runtime_resolve:
|
||||
stmg %r2,%r5,64(15) # save call-clobbered argument registers
|
||||
stg %r14,96(15)
|
||||
cfi_offset (r14, -64)
|
||||
lgr %r0,%r15
|
||||
aghi %r15,-160 # create stack frame
|
||||
cfi_adjust_cfa_offset (160)
|
||||
stg %r0,0(%r15) # write backchain
|
||||
lmg %r2,%r3,208(%r15)# load args saved by PLT
|
||||
brasl %r14,_dl_fixup # call fixup
|
||||
lgr %r1,%r2 # function addr returned in r2
|
||||
aghi %r15,160 # remove stack frame
|
||||
cfi_adjust_cfa_offset (-160)
|
||||
lg %r14,96(15) # restore registers
|
||||
lmg %r2,%r5,64(15)
|
||||
br %r1
|
||||
cfi_endproc
|
||||
.size _dl_runtime_resolve, .-_dl_runtime_resolve
|
||||
/* Create variant of _dl_runtime_resolve/profile for machines before z13.
|
||||
No vector registers are saved/restored. */
|
||||
#include <dl-trampoline.h>
|
||||
|
||||
|
||||
#ifndef PROF
|
||||
.globl _dl_runtime_profile
|
||||
.type _dl_runtime_profile, @function
|
||||
cfi_startproc
|
||||
.align 16
|
||||
_dl_runtime_profile:
|
||||
stmg %r2,%r6,64(%r15) # save call-clobbered arg regs
|
||||
std %f0,104(%r15) # + r6 needed as arg for
|
||||
std %f2,112(%r15) # _dl_profile_fixup
|
||||
std %f4,120(%r15)
|
||||
std %f6,128(%r15)
|
||||
stg %r12,24(%r15) # r12 is used as backup of r15
|
||||
stg %r14,32(%r15)
|
||||
cfi_offset (r6, -96)
|
||||
cfi_offset (f0, -56)
|
||||
cfi_offset (f2, -48)
|
||||
cfi_offset (f4, -40)
|
||||
cfi_offset (f6, -32)
|
||||
cfi_offset (r12, -136)
|
||||
cfi_offset (r14, -128)
|
||||
lgr %r12,%r15 # backup stack pointer
|
||||
cfi_def_cfa_register (12)
|
||||
aghi %r15,-160 # create stack frame
|
||||
stg %r12,0(%r15) # save backchain
|
||||
lmg %r2,%r3,48(%r12) # load arguments saved by PLT
|
||||
lgr %r4,%r14 # return address as third parameter
|
||||
la %r5,64(%r12) # pointer to struct La_s390_32_regs
|
||||
la %r6,40(%r12) # long int * framesize
|
||||
brasl %r14,_dl_profile_fixup # call resolver
|
||||
lgr %r1,%r2 # function addr returned in r2
|
||||
lg %r0,40(%r12) # load framesize
|
||||
ltgr %r0,%r0
|
||||
jnm 1f
|
||||
|
||||
lmg %r2,%r6,64(%r12) # framesize < 0 means no pltexit call
|
||||
ld %f0,104(%r12) # so we can do a tail call without
|
||||
ld %f2,112(%r12) # copying the arg overflow area
|
||||
ld %f4,120(%r12)
|
||||
ld %f6,128(%r12)
|
||||
|
||||
lgr %r15,%r12 # remove stack frame
|
||||
cfi_def_cfa_register (15)
|
||||
lg %r14,32(%r15) # restore registers
|
||||
lg %r12,24(%r15)
|
||||
br %r1 # tail-call to resolved function
|
||||
|
||||
cfi_def_cfa_register (12)
|
||||
1: jz 4f # framesize == 0 ?
|
||||
aghi %r0,7 # align framesize to 8
|
||||
nill %r0,0xfff8
|
||||
slgr %r15,%r0 # make room for framesize bytes
|
||||
stg %r12,0(%r15)
|
||||
la %r2,160(%r15)
|
||||
la %r3,160(%r12)
|
||||
srlg %r0,%r0,3
|
||||
3: mvc 0(8,%r2),0(%r3) # copy additional parameters
|
||||
la %r2,8(%r2)
|
||||
la %r3,8(%r3)
|
||||
brctg %r0,3b
|
||||
4: lmg %r2,%r6,64(%r12) # load register parameters
|
||||
ld %f0,104(%r12) # restore call-clobbered arg regs
|
||||
ld %f2,112(%r12)
|
||||
ld %f4,120(%r12)
|
||||
ld %f6,128(%r12)
|
||||
basr %r14,%r1 # call resolved function
|
||||
stg %r2,136(%r12)
|
||||
std %f0,144(%r12)
|
||||
lmg %r2,%r3,48(%r12) # load arguments saved by PLT
|
||||
la %r4,32(%r12) # pointer to struct La_s390_32_regs
|
||||
la %r5,72(%r12) # pointer to struct La_s390_32_retval
|
||||
brasl %r14,_dl_call_pltexit
|
||||
|
||||
lgr %r15,%r12 # remove stack frame
|
||||
cfi_def_cfa_register (15)
|
||||
lg %r14,32(%r15) # restore registers
|
||||
lg %r12,24(%r15)
|
||||
br %r14
|
||||
|
||||
cfi_endproc
|
||||
.size _dl_runtime_profile, .-_dl_runtime_profile
|
||||
#if defined HAVE_S390_VX_ASM_SUPPORT
|
||||
/* Create variant of _dl_runtime_resolve/profile for z13 and newer.
|
||||
The vector registers are saved/restored, too.*/
|
||||
# define _dl_runtime_resolve _dl_runtime_resolve_vx
|
||||
# define _dl_runtime_profile _dl_runtime_profile_vx
|
||||
# define RESTORE_VRS
|
||||
# include <dl-trampoline.h>
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,225 @@
|
||||
/* PLT trampolines. s390x version.
|
||||
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/>. */
|
||||
|
||||
/* The PLT stubs will call _dl_runtime_resolve/_dl_runtime_profile
|
||||
* with the following linkage:
|
||||
* r2 - r6 : parameter registers
|
||||
* f0, f2, f4, f6 : floating point parameter registers
|
||||
* v24, v26, v28, v30, v25, v27, v29, v31 : vector parameter registers
|
||||
* 48(r15), 56(r15) : PLT arguments PLT1, PLT2
|
||||
* 160(r15) : additional stack parameters
|
||||
* The normal clobber rules for function calls apply:
|
||||
* r0 - r5 : call clobbered
|
||||
* r6 - r13 : call saved
|
||||
* r14 : return address (call clobbered)
|
||||
* r15 : stack pointer (call saved)
|
||||
* f0 - f7 : call clobbered
|
||||
* f8 - f15 : call saved
|
||||
* v0 - v7 : bytes 0-7 overlap with f0-f7: call clobbered
|
||||
bytes 8-15: call clobbered
|
||||
* v8 - v15 : bytes 0-7 overlap with f8-f15: call saved
|
||||
bytes 8-15: call clobbered
|
||||
* v16 - v31 : call clobbered
|
||||
*/
|
||||
|
||||
.globl _dl_runtime_resolve
|
||||
.type _dl_runtime_resolve, @function
|
||||
cfi_startproc
|
||||
.align 16
|
||||
_dl_runtime_resolve:
|
||||
stmg %r2,%r5,64(%r15) # save call-clobbered argument registers
|
||||
cfi_offset (r2, -96)
|
||||
cfi_offset (r3, -88)
|
||||
cfi_offset (r4, -80)
|
||||
cfi_offset (r5, -72)
|
||||
std %f0,104(%r15)
|
||||
cfi_offset (f0, -56)
|
||||
std %f2,112(%r15)
|
||||
cfi_offset (f2, -48)
|
||||
std %f4,120(%r15)
|
||||
cfi_offset (f4, -40)
|
||||
std %f6,128(%r15)
|
||||
cfi_offset (f6, -32)
|
||||
stg %r14,96(15)
|
||||
cfi_offset (r14, -64)
|
||||
lmg %r2,%r3,48(%r15) # load args for fixup saved by PLT
|
||||
lgr %r0,%r15
|
||||
#ifdef RESTORE_VRS
|
||||
aghi %r15,-288 # create stack frame
|
||||
cfi_adjust_cfa_offset (288)
|
||||
.machine push
|
||||
.machine "z13"
|
||||
vstm %v24,%v31,160(%r15)# store call-clobbered vector argument registers
|
||||
cfi_offset (v24, -288)
|
||||
cfi_offset (v25, -272)
|
||||
cfi_offset (v26, -256)
|
||||
cfi_offset (v27, -240)
|
||||
cfi_offset (v28, -224)
|
||||
cfi_offset (v29, -208)
|
||||
cfi_offset (v30, -192)
|
||||
cfi_offset (v31, -176)
|
||||
.machine pop
|
||||
#else
|
||||
aghi %r15,-160 # create stack frame
|
||||
cfi_adjust_cfa_offset (160)
|
||||
#endif
|
||||
stg %r0,0(%r15) # write backchain
|
||||
brasl %r14,_dl_fixup # call _dl_fixup
|
||||
lgr %r1,%r2 # function addr returned in r2
|
||||
#ifdef RESTORE_VRS
|
||||
.machine push
|
||||
.machine "z13"
|
||||
vlm %v24,%v31,160(%r15)# restore vector registers
|
||||
.machine pop
|
||||
aghi %r15,288 # remove stack frame
|
||||
cfi_adjust_cfa_offset (-288)
|
||||
#else
|
||||
aghi %r15,160 # remove stack frame
|
||||
cfi_adjust_cfa_offset (-160)
|
||||
#endif
|
||||
lg %r14,96(%r15) # restore registers
|
||||
ld %f0,104(%r15)
|
||||
ld %f2,112(%r15)
|
||||
ld %f4,120(%r15)
|
||||
ld %f6,128(%r15)
|
||||
lmg %r2,%r5,64(%r15)
|
||||
br %r1
|
||||
cfi_endproc
|
||||
.size _dl_runtime_resolve, .-_dl_runtime_resolve
|
||||
|
||||
|
||||
#ifndef PROF
|
||||
.globl _dl_runtime_profile
|
||||
.type _dl_runtime_profile, @function
|
||||
cfi_startproc
|
||||
.align 16
|
||||
_dl_runtime_profile:
|
||||
stg %r12,24(%r15) # r12 is used as backup of r15
|
||||
cfi_offset (r12, -136)
|
||||
stg %r14,32(%r15)
|
||||
cfi_offset (r14, -128)
|
||||
lgr %r12,%r15 # backup stack pointer
|
||||
cfi_def_cfa_register (12)
|
||||
aghi %r15,-360 # create stack frame:
|
||||
# 160 + sizeof(La_s390_64_regs)
|
||||
stg %r12,0(%r15) # save backchain
|
||||
|
||||
stmg %r2,%r6,160(%r15) # save call-clobbered arg regs
|
||||
cfi_offset (r2, -360) # + r6 needed as arg for
|
||||
cfi_offset (r3, -352) # _dl_profile_fixup
|
||||
cfi_offset (r4, -344)
|
||||
cfi_offset (r5, -336)
|
||||
cfi_offset (r6, -328)
|
||||
std %f0,200(%r15)
|
||||
cfi_offset (f0, -320)
|
||||
std %f2,208(%r15)
|
||||
cfi_offset (f2, -312)
|
||||
std %f4,216(%r15)
|
||||
cfi_offset (f4, -304)
|
||||
std %f6,224(%r15)
|
||||
cfi_offset (f6, -296)
|
||||
#ifdef RESTORE_VRS
|
||||
.machine push
|
||||
.machine "z13"
|
||||
vstm %v24,%v31,232(%r15) # store call-clobbered vector arguments
|
||||
cfi_offset (v24, -288)
|
||||
cfi_offset (v25, -272)
|
||||
cfi_offset (v26, -256)
|
||||
cfi_offset (v27, -240)
|
||||
cfi_offset (v28, -224)
|
||||
cfi_offset (v29, -208)
|
||||
cfi_offset (v30, -192)
|
||||
cfi_offset (v31, -176)
|
||||
.machine pop
|
||||
#endif
|
||||
lmg %r2,%r3,48(%r12) # load arguments saved by PLT
|
||||
lgr %r4,%r14 # return address as third parameter
|
||||
la %r5,160(%r15) # pointer to struct La_s390_64_regs
|
||||
la %r6,40(%r12) # long int * framesize
|
||||
brasl %r14,_dl_profile_fixup # call resolver
|
||||
lgr %r1,%r2 # function addr returned in r2
|
||||
ld %f0,200(%r15) # restore call-clobbered arg fprs
|
||||
ld %f2,208(%r15)
|
||||
ld %f4,216(%r15)
|
||||
ld %f6,224(%r15)
|
||||
#ifdef RESTORE_VRS
|
||||
.machine push
|
||||
.machine "z13"
|
||||
vlm %v24,%v31,232(%r15) # restore call-clobbered arg vrs
|
||||
.machine pop
|
||||
#endif
|
||||
lg %r0,40(%r12) # load framesize
|
||||
ltgr %r0,%r0
|
||||
jnm 1f
|
||||
|
||||
lmg %r2,%r6,160(%r15) # framesize < 0 means no pltexit call
|
||||
# so we can do a tail call without
|
||||
# copying the arg overflow area
|
||||
lgr %r15,%r12 # remove stack frame
|
||||
cfi_def_cfa_register (15)
|
||||
lg %r14,32(%r15) # restore registers
|
||||
lg %r12,24(%r15)
|
||||
br %r1 # tail-call to resolved function
|
||||
|
||||
cfi_def_cfa_register (12)
|
||||
1: la %r4,160(%r15) # pointer to struct La_s390_64_regs
|
||||
stg %r4,64(%r12)
|
||||
jz 4f # framesize == 0 ?
|
||||
aghi %r0,7 # align framesize to 8
|
||||
nill %r0,0xfff8
|
||||
slgr %r15,%r0 # make room for framesize bytes
|
||||
stg %r12,0(%r15) # save backchain
|
||||
la %r2,160(%r15)
|
||||
la %r3,160(%r12)
|
||||
srlg %r0,%r0,3
|
||||
3: mvc 0(8,%r2),0(%r3) # copy additional parameters
|
||||
la %r2,8(%r2) # depending on framesize
|
||||
la %r3,8(%r3)
|
||||
brctg %r0,3b
|
||||
4: lmg %r2,%r6,0(%r4) # restore call-clobbered arg gprs
|
||||
basr %r14,%r1 # call resolved function
|
||||
stg %r2,72(%r12) # store return values r2, f0
|
||||
std %f0,80(%r12) # to struct La_s390_64_retval
|
||||
#ifdef RESTORE_VRS
|
||||
.machine push
|
||||
.machine "z13"
|
||||
vst %v24,88(%r12) # store return value v24
|
||||
.machine pop
|
||||
#endif
|
||||
lmg %r2,%r4,48(%r12) # r2, r3: load arguments saved by PLT
|
||||
# r4: pointer to struct La_s390_64_regs
|
||||
la %r5,72(%r12) # pointer to struct La_s390_64_retval
|
||||
brasl %r14,_dl_call_pltexit
|
||||
|
||||
lgr %r15,%r12 # remove stack frame
|
||||
cfi_def_cfa_register (15)
|
||||
lg %r14,32(%r15) # restore registers
|
||||
lg %r12,24(%r15)
|
||||
lg %r2,72(%r15) # restore return values
|
||||
ld %f0,80(%r15)
|
||||
#ifdef RESTORE_VRS
|
||||
.machine push
|
||||
.machine "z13"
|
||||
vl %v24,88(%r15) # restore return value v24
|
||||
.machine pop
|
||||
#endif
|
||||
br %r14 # Jump back to caller
|
||||
|
||||
cfi_endproc
|
||||
.size _dl_runtime_profile, .-_dl_runtime_profile
|
||||
#endif
|
||||
@@ -1,3 +1,21 @@
|
||||
/* Two glob variants with 64-bit support, for dirent64 and __olddirent64.
|
||||
Copyright (C) 1998-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 <dirent.h>
|
||||
#include <glob.h>
|
||||
#include <sys/stat.h>
|
||||
@@ -38,11 +56,15 @@ int __old_glob64 (const char *__pattern, int __flags,
|
||||
|
||||
#undef dirent
|
||||
#define dirent __old_dirent64
|
||||
#undef GL_READDIR
|
||||
# define GL_READDIR(pglob, stream) \
|
||||
((struct __old_dirent64 *) (pglob)->gl_readdir (stream))
|
||||
#undef __readdir
|
||||
#define __readdir(dirp) __old_readdir64 (dirp)
|
||||
#undef glob
|
||||
#define glob(pattern, flags, errfunc, pglob) \
|
||||
__old_glob64 (pattern, flags, errfunc, pglob)
|
||||
#define convert_dirent __old_convert_dirent
|
||||
#define glob_in_dir __old_glob_in_dir
|
||||
#define GLOB_ATTRIBUTE attribute_compat_text_section
|
||||
|
||||
|
||||
@@ -770,20 +770,17 @@ getifaddrs_internal (struct ifaddrs **ifap)
|
||||
|
||||
if (cp != NULL)
|
||||
{
|
||||
char c;
|
||||
unsigned int preflen;
|
||||
|
||||
if ((max_prefixlen > 0) &&
|
||||
(ifam->ifa_prefixlen > max_prefixlen))
|
||||
if (ifam->ifa_prefixlen > max_prefixlen)
|
||||
preflen = max_prefixlen;
|
||||
else
|
||||
preflen = ifam->ifa_prefixlen;
|
||||
|
||||
for (i = 0; i < ((preflen - 1) / 8); i++)
|
||||
for (i = 0; i < preflen / 8; i++)
|
||||
*cp++ = 0xff;
|
||||
c = 0xff;
|
||||
c <<= ((128 - preflen) % 8);
|
||||
*cp = c;
|
||||
if (preflen % 8)
|
||||
*cp = 0xff << (8 - preflen % 8);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -108,3 +108,4 @@ L(error):
|
||||
|
||||
libc_hidden_def(__vfork)
|
||||
weak_alias (__vfork, vfork)
|
||||
strong_alias (__vfork, __libc_vfork)
|
||||
|
||||
@@ -35,3 +35,4 @@
|
||||
#define HWCAP_S390_ETF3EH 256
|
||||
#define HWCAP_S390_HIGH_GPRS 512
|
||||
#define HWCAP_S390_TE 1024
|
||||
#define HWCAP_S390_VX 2048
|
||||
|
||||
@@ -17,6 +17,14 @@
|
||||
|
||||
#include <sysdep.h>
|
||||
|
||||
/* We do not want .eh_frame info so that __makecontext_ret stops unwinding
|
||||
if backtrace was called within a context created by makecontext. (There
|
||||
is also no .eh_frame info for _start or thread_start.) */
|
||||
#undef cfi_startproc
|
||||
#define cfi_startproc
|
||||
#undef cfi_endproc
|
||||
#define cfi_endproc
|
||||
|
||||
ENTRY(__makecontext_ret)
|
||||
basr %r14,%r7
|
||||
ltr %r8,%r8 /* Check whether uc_link is 0. */
|
||||
|
||||
@@ -34,7 +34,7 @@ ENTRY(__setcontext)
|
||||
lr %r1,%r2
|
||||
|
||||
/* rt_sigprocmask (SIG_SETMASK, &sc->sc_mask, NULL, sigsetsize). */
|
||||
la %r2,SIG_BLOCK
|
||||
la %r2,SIG_SETMASK
|
||||
la %r3,SC_MASK(%r1)
|
||||
slr %r4,%r4
|
||||
lhi %r5,_NSIG8
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
/* __swapcontext (ucontext_t *oucp, const ucontext_t *ucp)
|
||||
|
||||
Saves the machine context in oucp such that when it is activated,
|
||||
it appears as if __swapcontextt() returned again, restores the
|
||||
it appears as if __swapcontext() returned again, restores the
|
||||
machine context in ucp and thereby resumes execution in that
|
||||
context.
|
||||
|
||||
@@ -39,13 +39,6 @@ ENTRY(__swapcontext)
|
||||
lr %r1,%r2
|
||||
lr %r0,%r3
|
||||
|
||||
/* sigprocmask (SIG_BLOCK, NULL, &sc->sc_mask). */
|
||||
la %r2,SIG_BLOCK
|
||||
slr %r3,%r3
|
||||
la %r4,SC_MASK(%r1)
|
||||
lhi %r5,_NSIG8
|
||||
svc SYS_ify(rt_sigprocmask)
|
||||
|
||||
/* Store fpu context. */
|
||||
stfpc SC_FPC(%r1)
|
||||
std %f0,SC_FPRS(%r1)
|
||||
@@ -74,11 +67,12 @@ ENTRY(__swapcontext)
|
||||
/* Store general purpose registers. */
|
||||
stm %r0,%r15,SC_GPRS(%r1)
|
||||
|
||||
/* sigprocmask (SIG_SETMASK, &sc->sc_mask, NULL). */
|
||||
la %r2,SIG_BLOCK
|
||||
/* rt_sigprocmask (SIG_SETMASK, &ucp->uc_sigmask, &oucp->uc_sigmask,
|
||||
sigsetsize). */
|
||||
la %r2,SIG_SETMASK
|
||||
lr %r5,%r0
|
||||
la %r3,SC_MASK(%r5)
|
||||
slr %r4,%r4
|
||||
la %r4,SC_MASK(%r1)
|
||||
lhi %r5,_NSIG8
|
||||
svc SYS_ify(rt_sigprocmask)
|
||||
|
||||
|
||||
@@ -17,6 +17,14 @@
|
||||
|
||||
#include <sysdep.h>
|
||||
|
||||
/* We do not want .eh_frame info so that __makecontext_ret stops unwinding
|
||||
if backtrace was called within a context created by makecontext. (There
|
||||
is also no .eh_frame info for _start or thread_start.) */
|
||||
#undef cfi_startproc
|
||||
#define cfi_startproc
|
||||
#undef cfi_endproc
|
||||
#define cfi_endproc
|
||||
|
||||
ENTRY(__makecontext_ret)
|
||||
basr %r14,%r7
|
||||
ltgr %r8,%r8 /* Check whether uc_link is 0. */
|
||||
|
||||
@@ -34,7 +34,7 @@ ENTRY(__setcontext)
|
||||
lgr %r1,%r2
|
||||
|
||||
/* sigprocmask (SIG_SETMASK, &sc->sc_mask, NULL). */
|
||||
la %r2,SIG_BLOCK
|
||||
la %r2,SIG_SETMASK
|
||||
la %r3,SC_MASK(%r1)
|
||||
slgr %r4,%r4
|
||||
lghi %r5,_NSIG8
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
/* __swapcontext (ucontext_t *oucp, const ucontext_t *ucp)
|
||||
|
||||
Saves the machine context in oucp such that when it is activated,
|
||||
it appears as if __swapcontextt() returned again, restores the
|
||||
it appears as if __swapcontext() returned again, restores the
|
||||
machine context in ucp and thereby resumes execution in that
|
||||
context.
|
||||
|
||||
@@ -39,13 +39,6 @@ ENTRY(__swapcontext)
|
||||
lgr %r1,%r2
|
||||
lgr %r0,%r3
|
||||
|
||||
/* sigprocmask (SIG_BLOCK, NULL, &sc->sc_mask). */
|
||||
la %r2,SIG_BLOCK
|
||||
slgr %r3,%r3
|
||||
la %r4,SC_MASK(%r1)
|
||||
lghi %r5,_NSIG8
|
||||
svc SYS_ify(rt_sigprocmask)
|
||||
|
||||
/* Store fpu context. */
|
||||
stfpc SC_FPC(%r1)
|
||||
std %f0,SC_FPRS(%r1)
|
||||
@@ -74,12 +67,13 @@ ENTRY(__swapcontext)
|
||||
/* Store general purpose registers. */
|
||||
stmg %r0,%r15,SC_GPRS(%r1)
|
||||
|
||||
/* rt_sigprocmask (SIG_SETMASK, &sc->sc_mask, NULL, sigsetsize). */
|
||||
la %r2,SIG_BLOCK
|
||||
/* rt_sigprocmask (SIG_SETMASK, &ucp->uc_sigmask, &oucp->uc_sigmask,
|
||||
sigsetsize). */
|
||||
la %r2,SIG_SETMASK
|
||||
lgr %r5,%r0
|
||||
la %r3,SC_MASK(%r5)
|
||||
la %r4,SC_MASK(%r1)
|
||||
lghi %r5,_NSIG8
|
||||
slgr %r4,%r4
|
||||
svc SYS_ify(rt_sigprocmask)
|
||||
|
||||
/* Load fpu context. */
|
||||
|
||||
@@ -12,22 +12,3 @@ shmget - shmget i:iii __shmget shmget
|
||||
semop - semop i:ipi __semop semop
|
||||
semget - semget i:iii __semget semget
|
||||
semctl - semctl i:iiii __semctl semctl
|
||||
|
||||
# proper socket implementations:
|
||||
accept - accept Ci:iBN __libc_accept __accept accept
|
||||
bind - bind i:ipi __bind bind
|
||||
connect - connect Ci:ipi __libc_connect __connect connect
|
||||
getpeername - getpeername i:ipp __getpeername getpeername
|
||||
getsockname - getsockname i:ipp __getsockname getsockname
|
||||
getsockopt - getsockopt i:iiiBN __getsockopt getsockopt
|
||||
listen - listen i:ii __listen listen
|
||||
recv - recv Ci:ibni __libc_recv __recv recv
|
||||
recvfrom - recvfrom Ci:ibniBN __libc_recvfrom __recvfrom recvfrom
|
||||
recvmsg - recvmsg Ci:ipi __libc_recvmsg __recvmsg recvmsg
|
||||
send - send Ci:ibni __libc_send __send send
|
||||
sendmsg - sendmsg Ci:ipi __libc_sendmsg __sendmsg sendmsg
|
||||
sendto - sendto Ci:ibnibn __libc_sendto __sendto sendto
|
||||
setsockopt - setsockopt i:iiibn __setsockopt setsockopt
|
||||
shutdown - shutdown i:ii __shutdown shutdown
|
||||
socket - socket i:iii __socket socket
|
||||
socketpair - socketpair i:iiif __socketpair socketpair
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
# error "Never include <bits/sigaction.h> directly; use <signal.h> instead."
|
||||
#endif
|
||||
|
||||
#include <bits/wordsize.h>
|
||||
|
||||
/* Structure describing the action to be taken when a signal arrives. */
|
||||
struct sigaction
|
||||
{
|
||||
@@ -43,7 +45,9 @@ struct sigaction
|
||||
__sigset_t sa_mask;
|
||||
|
||||
/* Special flags. */
|
||||
#if __WORDSIZE == 64
|
||||
int __glibc_reserved0;
|
||||
#endif
|
||||
int sa_flags;
|
||||
|
||||
/* Not used by Linux/Sparc yet. */
|
||||
|
||||
Vendored
+2
-2
@@ -117,7 +117,7 @@ rm -f conftest*
|
||||
fi
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_asm_avx512" >&5
|
||||
$as_echo "$libc_cv_asm_avx512" >&6; }
|
||||
if test $libc_cv_asm_avx512 == yes; then
|
||||
if test $libc_cv_asm_avx512 = yes; then
|
||||
$as_echo "#define HAVE_AVX512_ASM_SUPPORT 1" >>confdefs.h
|
||||
|
||||
fi
|
||||
@@ -244,7 +244,7 @@ rm -f conftest*
|
||||
fi
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_asm_mpx" >&5
|
||||
$as_echo "$libc_cv_asm_mpx" >&6; }
|
||||
if test $libc_cv_asm_mpx == yes; then
|
||||
if test $libc_cv_asm_mpx = yes; then
|
||||
$as_echo "#define HAVE_MPX_SUPPORT 1" >>confdefs.h
|
||||
|
||||
fi
|
||||
|
||||
@@ -34,7 +34,7 @@ else
|
||||
libc_cv_asm_avx512=no
|
||||
fi
|
||||
rm -f conftest*])
|
||||
if test $libc_cv_asm_avx512 == yes; then
|
||||
if test $libc_cv_asm_avx512 = yes; then
|
||||
AC_DEFINE(HAVE_AVX512_ASM_SUPPORT)
|
||||
fi
|
||||
|
||||
@@ -86,7 +86,7 @@ else
|
||||
libc_cv_asm_mpx=no
|
||||
fi
|
||||
rm -f conftest*])
|
||||
if test $libc_cv_asm_mpx == yes; then
|
||||
if test $libc_cv_asm_mpx = yes; then
|
||||
AC_DEFINE(HAVE_MPX_SUPPORT)
|
||||
fi
|
||||
|
||||
|
||||
@@ -167,9 +167,14 @@ __init_cpu_features (void)
|
||||
/* Determine if AVX is usable. */
|
||||
if (CPUID_AVX)
|
||||
__cpu_features.feature[index_AVX_Usable] |= bit_AVX_Usable;
|
||||
/* Determine if AVX2 is usable. */
|
||||
#if index_AVX2_Usable != index_AVX_Fast_Unaligned_Load
|
||||
# error index_AVX2_Usable != index_AVX_Fast_Unaligned_Load
|
||||
#endif
|
||||
/* Determine if AVX2 is usable. Unaligned load with 256-bit
|
||||
AVX registers are faster on processors with AVX2. */
|
||||
if (CPUID_AVX2)
|
||||
__cpu_features.feature[index_AVX2_Usable] |= bit_AVX2_Usable;
|
||||
__cpu_features.feature[index_AVX2_Usable]
|
||||
|= bit_AVX2_Usable | bit_AVX_Fast_Unaligned_Load;
|
||||
/* Determine if FMA is usable. */
|
||||
if (CPUID_FMA)
|
||||
__cpu_features.feature[index_FMA_Usable] |= bit_FMA_Usable;
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#define bit_FMA4_Usable (1 << 8)
|
||||
#define bit_Slow_SSE4_2 (1 << 9)
|
||||
#define bit_AVX2_Usable (1 << 10)
|
||||
#define bit_AVX_Fast_Unaligned_Load (1 << 11)
|
||||
|
||||
/* CPUID Feature flags. */
|
||||
|
||||
@@ -74,6 +75,7 @@
|
||||
# define index_FMA4_Usable FEATURE_INDEX_1*FEATURE_SIZE
|
||||
# define index_Slow_SSE4_2 FEATURE_INDEX_1*FEATURE_SIZE
|
||||
# define index_AVX2_Usable FEATURE_INDEX_1*FEATURE_SIZE
|
||||
# define index_AVX_Fast_Unaligned_Load FEATURE_INDEX_1*FEATURE_SIZE
|
||||
|
||||
#else /* __ASSEMBLER__ */
|
||||
|
||||
@@ -169,6 +171,7 @@ extern const struct cpu_features *__get_cpu_features (void)
|
||||
# define index_FMA4_Usable FEATURE_INDEX_1
|
||||
# define index_Slow_SSE4_2 FEATURE_INDEX_1
|
||||
# define index_AVX2_Usable FEATURE_INDEX_1
|
||||
# define index_AVX_Fast_Unaligned_Load FEATURE_INDEX_1
|
||||
|
||||
# define HAS_ARCH_FEATURE(name) \
|
||||
((__get_cpu_features ()->feature[index_##name] & (bit_##name)) != 0)
|
||||
@@ -181,5 +184,6 @@ extern const struct cpu_features *__get_cpu_features (void)
|
||||
# define HAS_AVX2 HAS_ARCH_FEATURE (AVX2_Usable)
|
||||
# define HAS_FMA HAS_ARCH_FEATURE (FMA_Usable)
|
||||
# define HAS_FMA4 HAS_ARCH_FEATURE (FMA4_Usable)
|
||||
# define HAS_AVX_FAST_UNALIGNED_LOAD HAS_ARCH_FEATURE (AVX_Fast_Unaligned_Load)
|
||||
|
||||
#endif /* __ASSEMBLER__ */
|
||||
|
||||
@@ -33,7 +33,7 @@ ENTRY(__new_memcpy)
|
||||
jne 1f
|
||||
call __init_cpu_features
|
||||
1: leaq __memcpy_avx_unaligned(%rip), %rax
|
||||
testl $bit_AVX_Usable, __cpu_features+FEATURE_OFFSET+index_AVX_Usable(%rip)
|
||||
testl $bit_AVX_Fast_Unaligned_Load, __cpu_features+FEATURE_OFFSET+index_AVX_Fast_Unaligned_Load(%rip)
|
||||
jz 1f
|
||||
ret
|
||||
1: leaq __memcpy_sse2(%rip), %rax
|
||||
|
||||
@@ -39,7 +39,7 @@ ENTRY(__memcpy_chk)
|
||||
testl $bit_Fast_Copy_Backward, __cpu_features+FEATURE_OFFSET+index_Fast_Copy_Backward(%rip)
|
||||
jz 2f
|
||||
leaq __memcpy_chk_ssse3_back(%rip), %rax
|
||||
testl $bit_AVX_Usable, __cpu_features+FEATURE_OFFSET+index_AVX_Usable(%rip)
|
||||
testl $bit_AVX_Fast_Unaligned_Load, __cpu_features+FEATURE_OFFSET+index_AVX_Fast_Unaligned_Load(%rip)
|
||||
jz 2f
|
||||
leaq __memcpy_chk_avx_unaligned(%rip), %rax
|
||||
2: ret
|
||||
|
||||
@@ -49,7 +49,7 @@ extern __typeof (__redirect_memmove) __memmove_avx_unaligned attribute_hidden;
|
||||
ifunc symbol properly. */
|
||||
extern __typeof (__redirect_memmove) __libc_memmove;
|
||||
libc_ifunc (__libc_memmove,
|
||||
HAS_AVX
|
||||
HAS_AVX_FAST_UNALIGNED_LOAD
|
||||
? __memmove_avx_unaligned
|
||||
: (HAS_SSSE3
|
||||
? (HAS_FAST_COPY_BACKWARD
|
||||
|
||||
@@ -30,7 +30,7 @@ extern __typeof (__memmove_chk) __memmove_chk_avx_unaligned attribute_hidden;
|
||||
#include "debug/memmove_chk.c"
|
||||
|
||||
libc_ifunc (__memmove_chk,
|
||||
HAS_AVX ? __memmove_chk_avx_unaligned :
|
||||
HAS_AVX_FAST_UNALIGNED_LOAD ? __memmove_chk_avx_unaligned :
|
||||
(HAS_SSSE3
|
||||
? (HAS_FAST_COPY_BACKWARD
|
||||
? __memmove_chk_ssse3_back : __memmove_chk_ssse3)
|
||||
|
||||
@@ -37,7 +37,7 @@ ENTRY(__mempcpy)
|
||||
testl $bit_Fast_Copy_Backward, __cpu_features+FEATURE_OFFSET+index_Fast_Copy_Backward(%rip)
|
||||
jz 2f
|
||||
leaq __mempcpy_ssse3_back(%rip), %rax
|
||||
testl $bit_AVX_Usable, __cpu_features+FEATURE_OFFSET+index_AVX_Usable(%rip)
|
||||
testl $bit_AVX_Fast_Unaligned_Load, __cpu_features+FEATURE_OFFSET+index_AVX_Fast_Unaligned_Load(%rip)
|
||||
jz 2f
|
||||
leaq __mempcpy_avx_unaligned(%rip), %rax
|
||||
2: ret
|
||||
|
||||
@@ -39,7 +39,7 @@ ENTRY(__mempcpy_chk)
|
||||
testl $bit_Fast_Copy_Backward, __cpu_features+FEATURE_OFFSET+index_Fast_Copy_Backward(%rip)
|
||||
jz 2f
|
||||
leaq __mempcpy_chk_ssse3_back(%rip), %rax
|
||||
testl $bit_AVX_Usable, __cpu_features+FEATURE_OFFSET+index_AVX_Usable(%rip)
|
||||
testl $bit_AVX_Fast_Unaligned_Load, __cpu_features+FEATURE_OFFSET+index_AVX_Fast_Unaligned_Load(%rip)
|
||||
jz 2f
|
||||
leaq __mempcpy_chk_avx_unaligned(%rip), %rax
|
||||
2: ret
|
||||
|
||||
Reference in New Issue
Block a user