diff options
34 files changed, 481 insertions, 156 deletions
diff --git a/libc/Android.mk b/libc/Android.mk index 46c9676..2007965 100644 --- a/libc/Android.mk +++ b/libc/Android.mk @@ -226,7 +226,6 @@ libc_bionic_src_files := \ bionic/unlink.cpp \ bionic/utimes.cpp \ bionic/vdso.cpp \ - bionic/vfork.cpp \ bionic/wait.cpp \ bionic/wchar.cpp \ bionic/wctype.cpp \ diff --git a/libc/SYSCALLS.TXT b/libc/SYSCALLS.TXT index 128ec6b..38ae831 100644 --- a/libc/SYSCALLS.TXT +++ b/libc/SYSCALLS.TXT @@ -77,6 +77,7 @@ int prlimit64(pid_t, int, struct rlimit64*, const struct rlimit64*) arm,mips,x8 int setgroups:setgroups32(int, const gid_t*) arm,x86 int setgroups:setgroups(int, const gid_t*) arm64,mips,mips64,x86_64 int setpgid(pid_t, pid_t) all +pid_t vfork(void) arm int setregid:setregid32(gid_t, gid_t) arm,x86 int setregid:setregid(gid_t, gid_t) arm64,mips,mips64,x86_64 int chroot(const char*) all diff --git a/libc/arch-arm/syscalls/vfork.S b/libc/arch-arm/syscalls/vfork.S new file mode 100644 index 0000000..e12fba5 --- /dev/null +++ b/libc/arch-arm/syscalls/vfork.S @@ -0,0 +1,14 @@ +/* Generated by gensyscalls.py. Do not edit. */ + +#include <private/bionic_asm.h> + +ENTRY(vfork) + mov ip, r7 + ldr r7, =__NR_vfork + swi #0 + mov r7, ip + cmn r0, #(MAX_ERRNO + 1) + bxls lr + neg r0, r0 + b __set_errno +END(vfork) diff --git a/libc/arch-arm64/arm64.mk b/libc/arch-arm64/arm64.mk index 314358e..ed991ce 100644 --- a/libc/arch-arm64/arm64.mk +++ b/libc/arch-arm64/arm64.mk @@ -36,6 +36,7 @@ libc_bionic_src_files_arm64 := \ arch-arm64/bionic/__set_tls.c \ arch-arm64/bionic/sigsetjmp.S \ arch-arm64/bionic/syscall.S \ + arch-arm64/bionic/vfork.S \ libc_crt_target_cflags_arm64 := \ diff --git a/libc/arch-arm64/bionic/vfork.S b/libc/arch-arm64/bionic/vfork.S new file mode 100644 index 0000000..c700623 --- /dev/null +++ b/libc/arch-arm64/bionic/vfork.S @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <private/bionic_asm.h> +#include <asm/signal.h> +#include <linux/sched.h> + +ENTRY(vfork) + mov x0, #(CLONE_VM | CLONE_VFORK | SIGCHLD) + mov x1, xzr + mov x2, xzr + mov x3, xzr + mov x4, xzr + + mov x8, __NR_clone + svc #0 + + cmn x0, #(MAX_ERRNO + 1) + cneg x0, x0, hi + b.hi __set_errno + + ret +END(vfork) diff --git a/libc/arch-mips/bionic/vfork.S b/libc/arch-mips/bionic/vfork.S new file mode 100644 index 0000000..96de69e --- /dev/null +++ b/libc/arch-mips/bionic/vfork.S @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <private/bionic_asm.h> +#include <linux/sched.h> + +// TODO: mips' uapi signal.h is missing #ifndef __ASSEMBLY__. +// #include <asm/signal.h> +#define SIGCHLD 18 + +ENTRY(vfork) + .set noreorder + .cpload t9 + + li a0, (CLONE_VM | CLONE_VFORK | SIGCHLD) + li a1, 0 + li a2, 0 + li a3, 0 + subu sp, 8 + sw $0, 16(sp) + li v0, __NR_clone + syscall + addu sp, 8 + bnez a3, 1f + move a0, v0 + + j ra + nop +1: + la t9, __set_errno + j t9 + nop +END(vfork) diff --git a/libc/arch-mips/mips.mk b/libc/arch-mips/mips.mk index bf3b8ae..8e415f9 100644 --- a/libc/arch-mips/mips.mk +++ b/libc/arch-mips/mips.mk @@ -59,6 +59,7 @@ libc_bionic_src_files_mips += \ arch-mips/bionic/setjmp.S \ arch-mips/bionic/sigsetjmp.S \ arch-mips/bionic/syscall.S \ + arch-mips/bionic/vfork.S \ ifndef ARCH_MIPS_REV6 libc_bionic_src_files_mips += \ diff --git a/libc/arch-mips64/bionic/vfork.S b/libc/arch-mips64/bionic/vfork.S new file mode 100644 index 0000000..911a264 --- /dev/null +++ b/libc/arch-mips64/bionic/vfork.S @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <private/bionic_asm.h> +#include <linux/sched.h> + +// TODO: mips' uapi signal.h is missing #ifndef __ASSEMBLY__. +// #include <asm/signal.h> +#define SIGCHLD 18 + + .text + +#if (_MIPS_SIM == _ABIO32) || (_MIPS_SIM == _ABI32) +FRAMESZ = MKFSIZ(5,0) +#else +FRAMESZ = MKFSIZ(0,0) +#endif + +LEAF(vfork,FRAMESZ) +#if FRAMESZ!=0 + PTR_SUBU sp, FRAMESZ +#endif + SETUP_GP64(a5, vfork) + LI a0, (CLONE_VM | CLONE_VFORK | SIGCHLD) + move a1, $0 + move a2, $0 + move a3, $0 +#if (_MIPS_SIM == _ABIO32) || (_MIPS_SIM == _ABI32) + REG_S $0, 4*REGSZ(sp) +#else + move a4, $0 +#endif + LI v0, __NR_clone + syscall +#if FRAMESZ!=0 + PTR_ADDU sp,FRAMESZ +#endif + move a0, v0 + bnez a3, 1f + RESTORE_GP64 + j ra +1: + LA t9,__set_errno + RESTORE_GP64 + j t9 + END(vfork) diff --git a/libc/arch-mips64/mips64.mk b/libc/arch-mips64/mips64.mk index 6f7a928..230cb26 100644 --- a/libc/arch-mips64/mips64.mk +++ b/libc/arch-mips64/mips64.mk @@ -46,6 +46,7 @@ libc_bionic_src_files_mips64 := \ arch-mips64/bionic/setjmp.S \ arch-mips64/bionic/sigsetjmp.S \ arch-mips64/bionic/syscall.S \ + arch-mips64/bionic/vfork.S \ # FIXME TODO ## libc_bionic_src_files_mips64 += arch-mips64/string/memcpy.S diff --git a/libc/arch-x86/bionic/vfork.S b/libc/arch-x86/bionic/vfork.S new file mode 100644 index 0000000..ffa6b16 --- /dev/null +++ b/libc/arch-x86/bionic/vfork.S @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <private/bionic_asm.h> + +// This custom code preserves the return address across the system call. + +ENTRY(vfork) + popl %ecx // Grab the return address. + movl $__NR_vfork, %eax + int $0x80 + cmpl $-MAX_ERRNO, %eax + jb 1f + negl %eax + pushl %eax + call __set_errno +1: + jmp *%ecx // Jump to the stored return address. +END(vfork) diff --git a/libc/arch-x86/x86.mk b/libc/arch-x86/x86.mk index 8aa2645..019dc8e 100644 --- a/libc/arch-x86/x86.mk +++ b/libc/arch-x86/x86.mk @@ -31,6 +31,7 @@ libc_bionic_src_files_x86 += \ arch-x86/bionic/__set_tls.c \ arch-x86/bionic/sigsetjmp.S \ arch-x86/bionic/syscall.S \ + arch-x86/bionic/vfork.S \ ## ARCH variant specific source files arch_variant_mk := $(LOCAL_PATH)/arch-x86/$(TARGET_ARCH_VARIANT)/$(TARGET_ARCH_VARIANT).mk diff --git a/libc/bionic/vfork.cpp b/libc/arch-x86_64/bionic/vfork.S index b706a7f..7c14cc0 100644 --- a/libc/bionic/vfork.cpp +++ b/libc/arch-x86_64/bionic/vfork.S @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014 The Android Open Source Project + * Copyright (C) 2013 The Android Open Source Project * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -26,10 +26,20 @@ * SUCH DAMAGE. */ -#include <unistd.h> +#include <private/bionic_asm.h> -// vfork(2) was removed from POSIX 2008, but it's common enough that we can't -// actually remove it entirely. -extern "C" pid_t vfork(void) { - return fork(); -} +// This custom code preserves the return address across the system call. + +ENTRY(vfork) + popq %rdi // Grab the return address. + movl $__NR_vfork, %eax + syscall + pushq %rdi // Restore the return address. + cmpq $-MAX_ERRNO, %rax + jb 1f + negl %eax + movl %eax, %edi + call __set_errno +1: + ret +END(vfork) diff --git a/libc/arch-x86_64/x86_64.mk b/libc/arch-x86_64/x86_64.mk index 234cf67..7887c51 100644 --- a/libc/arch-x86_64/x86_64.mk +++ b/libc/arch-x86_64/x86_64.mk @@ -37,6 +37,7 @@ libc_bionic_src_files_x86_64 := \ arch-x86_64/bionic/__set_tls.c \ arch-x86_64/bionic/sigsetjmp.S \ arch-x86_64/bionic/syscall.S \ + arch-x86_64/bionic/vfork.S \ libc_bionic_src_files_x86_64 += \ arch-x86_64/string/sse2-memcpy-slm.S \ diff --git a/libc/bionic/locale.cpp b/libc/bionic/locale.cpp index 363140e..4c3fd7f 100644 --- a/libc/bionic/locale.cpp +++ b/libc/bionic/locale.cpp @@ -30,10 +30,27 @@ #include <pthread.h> #include <stdlib.h> +#include "private/bionic_macros.h" + // We currently support a single locale, the "C" locale (also known as "POSIX"). +static bool __bionic_current_locale_is_utf8 = true; + struct __locale_t { - // Because we only support one locale, these are just tokens with no data. + size_t mb_cur_max; + + __locale_t(size_t mb_cur_max) : mb_cur_max(mb_cur_max) { + } + + __locale_t(const __locale_t* other) { + if (other == LC_GLOBAL_LOCALE) { + mb_cur_max = __bionic_current_locale_is_utf8 ? 4 : 1; + } else { + mb_cur_max = other->mb_cur_max; + } + } + + DISALLOW_COPY_AND_ASSIGN(__locale_t); }; static pthread_once_t g_locale_once = PTHREAD_ONCE_INIT; @@ -75,7 +92,14 @@ static void __locale_init() { g_locale.int_n_sign_posn = CHAR_MAX; } -static bool __bionic_current_locale_is_utf8 = false; +size_t __mb_cur_max() { + locale_t l = reinterpret_cast<locale_t>(pthread_getspecific(g_uselocale_key)); + if (l == nullptr || l == LC_GLOBAL_LOCALE) { + return __bionic_current_locale_is_utf8 ? 4 : 1; + } else { + return l->mb_cur_max; + } +} static bool __is_supported_locale(const char* locale) { return (strcmp(locale, "") == 0 || @@ -85,25 +109,17 @@ static bool __is_supported_locale(const char* locale) { strcmp(locale, "POSIX") == 0); } -static locale_t __new_locale() { - return reinterpret_cast<locale_t>(malloc(sizeof(__locale_t))); -} - lconv* localeconv() { pthread_once(&g_locale_once, __locale_init); return &g_locale; } locale_t duplocale(locale_t l) { - locale_t clone = __new_locale(); - if (clone != NULL && l != LC_GLOBAL_LOCALE) { - *clone = *l; - } - return clone; + return new __locale_t(l); } void freelocale(locale_t l) { - free(l); + delete l; } locale_t newlocale(int category_mask, const char* locale_name, locale_t /*base*/) { @@ -118,7 +134,7 @@ locale_t newlocale(int category_mask, const char* locale_name, locale_t /*base*/ return NULL; } - return __new_locale(); + return new __locale_t(strstr(locale_name, "UTF-8") != NULL ? 4 : 1); } char* setlocale(int category, const char* locale_name) { diff --git a/libc/bionic/ndk_cruft.cpp b/libc/bionic/ndk_cruft.cpp index e3e640a..0c72019 100644 --- a/libc/bionic/ndk_cruft.cpp +++ b/libc/bionic/ndk_cruft.cpp @@ -225,6 +225,7 @@ extern "C" int tkill(pid_t tid, int sig) { return syscall(__NR_tkill, tid, sig); } +// This was removed from POSIX 2008. extern "C" wchar_t* wcswcs(wchar_t* haystack, wchar_t* needle) { return wcsstr(haystack, needle); } @@ -267,7 +268,7 @@ extern "C" int getdtablesize() { return r.rlim_cur; } -// Only used by ftime, which was removed from POSIX. +// Only used by ftime, which was removed from POSIX 2008. struct timeb { time_t time; unsigned short millitm; diff --git a/libc/bionic/wchar.cpp b/libc/bionic/wchar.cpp index 438ce03..524ba07 100644 --- a/libc/bionic/wchar.cpp +++ b/libc/bionic/wchar.cpp @@ -84,6 +84,7 @@ size_t mbsnrtowcs(wchar_t* dst, const char** src, size_t nmc, size_t len, mbstat if (static_cast<uint8_t>((*src)[i]) < 0x80) { // Fast path for plain ASCII characters. if ((*src)[i] == '\0') { + *src = nullptr; return reset_and_return(o, state); } r = 1; @@ -96,6 +97,7 @@ size_t mbsnrtowcs(wchar_t* dst, const char** src, size_t nmc, size_t len, mbstat return reset_and_return_illegal(EILSEQ, state); } if (r == 0) { + *src = nullptr; return reset_and_return(o, state); } } @@ -118,7 +120,8 @@ size_t mbsnrtowcs(wchar_t* dst, const char** src, size_t nmc, size_t len, mbstat dst[o] = (*src)[i]; r = 1; if ((*src)[i] == '\0') { - break; + *src = nullptr; + return reset_and_return(o, state); } } else { r = mbrtowc(dst + o, *src + i, nmc - i, state); diff --git a/libc/dns/include/resolv_netid.h b/libc/dns/include/resolv_netid.h index f1b8892..e5521b8 100644 --- a/libc/dns/include/resolv_netid.h +++ b/libc/dns/include/resolv_netid.h @@ -61,6 +61,9 @@ int android_getaddrinfofornet(const char *, const char *, const struct addrinfo extern void _resolv_set_nameservers_for_net(unsigned netid, const char** servers, int numservers, const char *domains) __used_in_netd; +/* flush the cache associated with a certain network */ +extern void _resolv_flush_cache_for_net(unsigned netid) __used_in_netd; + /* delete the cache associated with a certain network */ extern void _resolv_delete_cache_for_net(unsigned netid) __used_in_netd; diff --git a/libc/dns/resolv/res_cache.c b/libc/dns/resolv/res_cache.c index c934b4e..419b748 100644 --- a/libc/dns/resolv/res_cache.c +++ b/libc/dns/resolv/res_cache.c @@ -1831,6 +1831,17 @@ _get_res_cache_for_net_locked(unsigned netid) return cache; } +void +_resolv_flush_cache_for_net(unsigned netid) +{ + pthread_once(&_res_cache_once, _res_cache_init); + pthread_mutex_lock(&_res_cache_list_lock); + + _flush_cache_for_net_locked(netid); + + pthread_mutex_unlock(&_res_cache_list_lock); +} + static void _flush_cache_for_net_locked(unsigned netid) { diff --git a/libc/include/stdlib.h b/libc/include/stdlib.h index e29fdba..a5eb3d1 100644 --- a/libc/include/stdlib.h +++ b/libc/include/stdlib.h @@ -161,7 +161,8 @@ extern int mbtowc(wchar_t *, const char *, size_t); extern int wctomb(char *, wchar_t); extern size_t wcstombs(char *, const wchar_t *, size_t); -#define MB_CUR_MAX 4U +extern size_t __mb_cur_max(void); +#define MB_CUR_MAX __mb_cur_max() __END_DECLS diff --git a/libc/include/string.h b/libc/include/string.h index af1c0c1..8df68e3 100644 --- a/libc/include/string.h +++ b/libc/include/string.h @@ -94,9 +94,6 @@ extern size_t strxfrm_l(char* __restrict, const char* __restrict, size_t, locale #if defined(__BIONIC_FORTIFY) -__errordecl(__memcpy_dest_size_error, "memcpy: prevented write past end of buffer"); -__errordecl(__memcpy_src_size_error, "memcpy: prevented read past end of buffer"); - __BIONIC_FORTIFY_INLINE void* memcpy(void* __restrict dest, const void* __restrict src, size_t copy_amount) { char *d = (char *) dest; @@ -104,14 +101,6 @@ void* memcpy(void* __restrict dest, const void* __restrict src, size_t copy_amou size_t s_len = __bos0(s); size_t d_len = __bos0(d); - if (__builtin_constant_p(copy_amount) && (copy_amount > d_len)) { - __memcpy_dest_size_error(); - } - - if (__builtin_constant_p(copy_amount) && (copy_amount > s_len)) { - __memcpy_src_size_error(); - } - return __builtin___memcpy_chk(dest, src, copy_amount, d_len); } @@ -130,16 +119,12 @@ char* strcpy(char* __restrict dest, const char* __restrict src) { return __builtin___strcpy_chk(dest, src, __bos(dest)); } -__errordecl(__stpncpy_error, "stpncpy: prevented write past end of buffer"); extern char* __stpncpy_chk2(char* __restrict, const char* __restrict, size_t, size_t, size_t); __BIONIC_FORTIFY_INLINE char* stpncpy(char* __restrict dest, const char* __restrict src, size_t n) { size_t bos_dest = __bos(dest); size_t bos_src = __bos(src); - if (__builtin_constant_p(n) && (n > bos_dest)) { - __stpncpy_error(); - } if (bos_src == __BIONIC_FORTIFY_UNKNOWN_SIZE) { return __builtin___stpncpy_chk(dest, src, n, bos_dest); @@ -157,16 +142,12 @@ char* stpncpy(char* __restrict dest, const char* __restrict src, size_t n) { return __stpncpy_chk2(dest, src, n, bos_dest, bos_src); } -__errordecl(__strncpy_error, "strncpy: prevented write past end of buffer"); extern char* __strncpy_chk2(char* __restrict, const char* __restrict, size_t, size_t, size_t); __BIONIC_FORTIFY_INLINE char* strncpy(char* __restrict dest, const char* __restrict src, size_t n) { size_t bos_dest = __bos(dest); size_t bos_src = __bos(src); - if (__builtin_constant_p(n) && (n > bos_dest)) { - __strncpy_error(); - } if (bos_src == __BIONIC_FORTIFY_UNKNOWN_SIZE) { return __builtin___strncpy_chk(dest, src, n, bos_dest); @@ -201,7 +182,6 @@ void* memset(void *s, int c, size_t n) { extern size_t __strlcpy_real(char* __restrict, const char* __restrict, size_t) __asm__(__USER_LABEL_PREFIX__ "strlcpy"); -__errordecl(__strlcpy_error, "strlcpy: prevented write past end of buffer"); extern size_t __strlcpy_chk(char *, const char *, size_t, size_t); __BIONIC_FORTIFY_INLINE @@ -219,12 +199,6 @@ size_t strlcpy(char* __restrict dest, const char* __restrict src, size_t size) { if (__builtin_constant_p(size) && (size <= bos)) { return __strlcpy_real(dest, src, size); } - - // Compiler can prove, at compile time, that the passed in size - // is always > the actual object size. Force a compiler error. - if (__builtin_constant_p(size) && (size > bos)) { - __strlcpy_error(); - } #endif /* !defined(__clang__) */ return __strlcpy_chk(dest, src, size, bos); @@ -232,7 +206,6 @@ size_t strlcpy(char* __restrict dest, const char* __restrict src, size_t size) { extern size_t __strlcat_real(char* __restrict, const char* __restrict, size_t) __asm__(__USER_LABEL_PREFIX__ "strlcat"); -__errordecl(__strlcat_error, "strlcat: prevented write past end of buffer"); extern size_t __strlcat_chk(char* __restrict, const char* __restrict, size_t, size_t); @@ -251,12 +224,6 @@ size_t strlcat(char* __restrict dest, const char* __restrict src, size_t size) { if (__builtin_constant_p(size) && (size <= bos)) { return __strlcat_real(dest, src, size); } - - // Compiler can prove, at compile time, that the passed in size - // is always > the actual object size. Force a compiler error. - if (__builtin_constant_p(size) && (size > bos)) { - __strlcat_error(); - } #endif /* !defined(__clang__) */ return __strlcat_chk(dest, src, size, bos); diff --git a/libc/tools/zoneinfo/ZoneCompactor.java b/libc/tools/zoneinfo/ZoneCompactor.java index f47afd1..bf3153e 100644 --- a/libc/tools/zoneinfo/ZoneCompactor.java +++ b/libc/tools/zoneinfo/ZoneCompactor.java @@ -1,9 +1,6 @@ import java.io.*; -import java.nio.ByteOrder; import java.util.*; -import libcore.io.BufferIterator; -import libcore.util.ZoneInfo; // usage: java ZoneCompiler <setup file> <data directory> <output directory> <tzdata version> // @@ -27,66 +24,20 @@ import libcore.util.ZoneInfo; // public class ZoneCompactor { - public static class ByteArrayBufferIteratorBE extends BufferIterator { - private final byte[] bytes; - private int offset = 0; - - public ByteArrayBufferIteratorBE(byte[] bytes) { - this.bytes = bytes; - this.offset = 0; - } - - public void seek(int offset) { - this.offset = offset; - } - - public void skip(int byteCount) { - this.offset += byteCount; - } - - public void readByteArray(byte[] dst, int dstOffset, int byteCount) { - System.arraycopy(bytes, offset, dst, dstOffset, byteCount); - offset += byteCount; - } - - public byte readByte() { - return bytes[offset++]; - } - - public int readInt() { - return ((readByte() & 0xff) << 24) | ((readByte() & 0xff) << 16) | ((readByte() & 0xff) << 8) | (readByte() & 0xff); - } - - public void readIntArray(int[] dst, int dstOffset, int intCount) { - for (int i = 0; i < intCount; ++i) { - dst[dstOffset++] = readInt(); - } - } - - public short readShort() { - throw new UnsupportedOperationException(); - } - } - - // Maximum number of characters in a zone name, including '\0' terminator + // Maximum number of characters in a zone name, including '\0' terminator. private static final int MAXNAME = 40; - // Zone name synonyms + // Zone name synonyms. private Map<String,String> links = new HashMap<String,String>(); - // File starting bytes by zone name - private Map<String,Integer> starts = new HashMap<String,Integer>(); + // File offsets by zone name. + private Map<String,Integer> offsets = new HashMap<String,Integer>(); - // File lengths by zone name + // File lengths by zone name. private Map<String,Integer> lengths = new HashMap<String,Integer>(); - // Raw GMT offsets by zone name - private Map<String,Integer> offsets = new HashMap<String,Integer>(); - private int start = 0; - - // Concatenate the contents of 'inFile' onto 'out' - // and return the contents as a byte array. - private static byte[] copyFile(File inFile, OutputStream out) throws Exception { + // Concatenate the contents of 'inFile' onto 'out'. + private static void copyFile(File inFile, OutputStream out) throws Exception { byte[] ret = new byte[0]; InputStream in = new FileInputStream(inFile); @@ -104,14 +55,14 @@ public class ZoneCompactor { ret = nret; } out.flush(); - return ret; } public ZoneCompactor(String setupFile, String dataDirectory, String zoneTabFile, String outputDirectory, String version) throws Exception { - // Read the setup file, and concatenate all the data. + // Read the setup file and concatenate all the data. ByteArrayOutputStream allData = new ByteArrayOutputStream(); BufferedReader reader = new BufferedReader(new FileReader(setupFile)); String s; + int offset = 0; while ((s = reader.readLine()) != null) { s = s.trim(); if (s.startsWith("Link")) { @@ -125,16 +76,11 @@ public class ZoneCompactor { if (link == null) { File sourceFile = new File(dataDirectory, s); long length = sourceFile.length(); - starts.put(s, start); + offsets.put(s, offset); lengths.put(s, (int) length); - start += length; - byte[] data = copyFile(sourceFile, allData); - - BufferIterator it = new ByteArrayBufferIteratorBE(data); - TimeZone tz = ZoneInfo.makeTimeZone(s, it); - int gmtOffset = tz.getRawOffset(); - offsets.put(s, gmtOffset); + offset += length; + copyFile(sourceFile, allData); } } } @@ -146,9 +92,8 @@ public class ZoneCompactor { String from = it.next(); String to = links.get(from); - starts.put(from, starts.get(to)); - lengths.put(from, lengths.get(to)); offsets.put(from, offsets.get(to)); + lengths.put(from, lengths.get(to)); } // Create/truncate the destination file. @@ -178,7 +123,7 @@ public class ZoneCompactor { // Write the index. ArrayList<String> sortedOlsonIds = new ArrayList<String>(); - sortedOlsonIds.addAll(starts.keySet()); + sortedOlsonIds.addAll(offsets.keySet()); Collections.sort(sortedOlsonIds); it = sortedOlsonIds.iterator(); while (it.hasNext()) { @@ -188,9 +133,9 @@ public class ZoneCompactor { } f.write(toAscii(new byte[MAXNAME], zoneName)); - f.writeInt(starts.get(zoneName)); - f.writeInt(lengths.get(zoneName)); f.writeInt(offsets.get(zoneName)); + f.writeInt(lengths.get(zoneName)); + f.writeInt(0); // Used to be raw GMT offset. No longer used. } int data_offset = (int) f.getFilePointer(); diff --git a/libc/tools/zoneinfo/update-tzdata.py b/libc/tools/zoneinfo/update-tzdata.py index 6b69a5a..e800e8f 100755 --- a/libc/tools/zoneinfo/update-tzdata.py +++ b/libc/tools/zoneinfo/update-tzdata.py @@ -115,7 +115,7 @@ def BuildIcuToolsAndData(data_filename): print 'Configuring ICU tools...' subprocess.check_call(['%s/runConfigureICU' % icu_dir, 'Linux']) print 'Making ICU tools...' - subprocess.check_call(['make', '-j6']) + subprocess.check_call(['make', '-j32']) # Run the ICU tools. os.chdir('tools/tzcode') @@ -169,11 +169,8 @@ def BuildBionicToolsAndData(data_filename): WriteSetupFile() print 'Calling ZoneCompactor to update bionic to %s...' % new_version - libcore_src_dir = '%s/../libcore/luni/src/main/java/' % bionic_dir subprocess.check_call(['javac', '-d', '.', - '%s/ZoneCompactor.java' % bionic_libc_tools_zoneinfo_dir, - '%s/libcore/util/ZoneInfo.java' % libcore_src_dir, - '%s/libcore/io/BufferIterator.java' % libcore_src_dir]) + '%s/ZoneCompactor.java' % bionic_libc_tools_zoneinfo_dir]) subprocess.check_call(['java', 'ZoneCompactor', 'setup', 'data', 'extracted/zone.tab', bionic_libc_zoneinfo_dir, new_version]) diff --git a/libc/tzcode/localtime.c b/libc/tzcode/localtime.c index 5e4e962..3bbed90 100644 --- a/libc/tzcode/localtime.c +++ b/libc/tzcode/localtime.c @@ -2210,7 +2210,7 @@ static int __bionic_open_tzdata_path(const char* path_prefix_variable, const cha char buf[NAME_LENGTH]; int32_t start; int32_t length; - int32_t raw_gmt_offset; + int32_t unused; // Was raw GMT offset; always 0 since tzdata2014f (L). }; size_t id_count = (ntohl(header.data_offset) - ntohl(header.index_offset)) / sizeof(struct index_entry_t); diff --git a/libc/zoneinfo/tzdata b/libc/zoneinfo/tzdata Binary files differindex a5ae1f6..9547f58 100644 --- a/libc/zoneinfo/tzdata +++ b/libc/zoneinfo/tzdata diff --git a/linker/dlfcn.cpp b/linker/dlfcn.cpp index efb829e..8ebf357 100644 --- a/linker/dlfcn.cpp +++ b/linker/dlfcn.cpp @@ -111,8 +111,7 @@ void* dlsym(void* handle, const char* symbol) { sym = dlsym_linear_lookup(symbol, &found, caller_si->next, caller_si); } } else { - found = reinterpret_cast<soinfo*>(handle); - sym = dlsym_handle_lookup(found, symbol, caller_si); + sym = dlsym_handle_lookup(reinterpret_cast<soinfo*>(handle), &found, symbol, caller_si); } if (sym != NULL && sym->st_shndx != 0) { diff --git a/linker/linked_list.h b/linker/linked_list.h index 52af0f1..7f8c901 100644 --- a/linker/linked_list.h +++ b/linker/linked_list.h @@ -31,13 +31,45 @@ struct LinkedListEntry { template<typename T, typename Allocator> class LinkedList { public: - LinkedList() : head_(nullptr) {} + LinkedList() : head_(nullptr), tail_(nullptr) {} void push_front(T* const element) { LinkedListEntry<T>* new_entry = Allocator::alloc(); new_entry->next = head_; new_entry->element = element; head_ = new_entry; + if (tail_ == nullptr) { + tail_ = new_entry; + } + } + + void push_back(T* const element) { + LinkedListEntry<T>* new_entry = Allocator::alloc(); + new_entry->next = nullptr; + new_entry->element = element; + if (tail_ == nullptr) { + tail_ = head_ = new_entry; + } else { + tail_->next = new_entry; + tail_ = new_entry; + } + } + + T* pop_front() { + if (head_ == nullptr) { + return nullptr; + } + + LinkedListEntry<T>* entry = head_; + T* element = entry->element; + head_ = entry->next; + Allocator::free(entry); + + if (head_ == nullptr) { + tail_ = nullptr; + } + + return element; } void clear() { @@ -46,6 +78,8 @@ class LinkedList { head_ = head_->next; Allocator::free(p); } + + tail_ = nullptr; } template<typename F> @@ -68,6 +102,7 @@ class LinkedList { private: LinkedListEntry<T>* head_; + LinkedListEntry<T>* tail_; DISALLOW_COPY_AND_ASSIGN(LinkedList); }; diff --git a/linker/linker.cpp b/linker/linker.cpp index 59b9938..f8b35d7 100644 --- a/linker/linker.cpp +++ b/linker/linker.cpp @@ -469,6 +469,10 @@ static ElfW(Sym)* soinfo_elf_lookup(soinfo* si, unsigned hash, const char* name, } } + TRACE_TYPE(LOOKUP, "NOT FOUND %s in %s@%p %x %zd", + name, si->name, reinterpret_cast<void*>(si->base), hash, hash % si->nbucket); + + return NULL; } @@ -585,18 +589,43 @@ done: return NULL; } -/* This is used by dlsym(3). It performs symbol lookup only within the - specified soinfo object and not in any of its dependencies. +// Another soinfo list allocator to use in dlsym. We don't reuse +// SoinfoListAllocator because it is write-protected most of the time. +static LinkerAllocator<LinkedListEntry<soinfo>> g_soinfo_list_allocator_rw; +class SoinfoListAllocatorRW { + public: + static LinkedListEntry<soinfo>* alloc() { + return g_soinfo_list_allocator_rw.alloc(); + } - TODO: Only looking in the specified soinfo seems wrong. dlsym(3) says - that it should do a breadth first search through the dependency - tree. This agrees with the ELF spec (aka System V Application - Binary Interface) where in Chapter 5 it discuss resolving "Shared - Object Dependencies" in breadth first search order. - */ -ElfW(Sym)* dlsym_handle_lookup(soinfo* si, const char* name, soinfo* caller) { - return soinfo_elf_lookup(si, elfhash(name), name, - caller == si ? SymbolLookupScope::kAllowLocal : SymbolLookupScope::kExcludeLocal); + static void free(LinkedListEntry<soinfo>* ptr) { + g_soinfo_list_allocator_rw.free(ptr); + } +}; + +// This is used by dlsym(3). It performs symbol lookup only within the +// specified soinfo object and its dependencies in breadth first order. +ElfW(Sym)* dlsym_handle_lookup(soinfo* si, soinfo** found, const char* name, soinfo* caller) { + LinkedList<soinfo, SoinfoListAllocatorRW> visit_list; + visit_list.push_back(si); + soinfo* current_soinfo; + while ((current_soinfo = visit_list.pop_front()) != nullptr) { + ElfW(Sym)* result = soinfo_elf_lookup(current_soinfo, elfhash(name), name, + caller == current_soinfo ? SymbolLookupScope::kAllowLocal : SymbolLookupScope::kExcludeLocal); + + if (result != nullptr) { + *found = current_soinfo; + visit_list.clear(); + return result; + } + + current_soinfo->get_children().for_each([&](soinfo* child) { + visit_list.push_back(child); + }); + } + + visit_list.clear(); + return nullptr; } /* This is used by dlsym(3) to performs a global symbol lookup. If the diff --git a/linker/linker.h b/linker/linker.h index e1112e6..03672b2 100644 --- a/linker/linker.h +++ b/linker/linker.h @@ -238,7 +238,7 @@ ElfW(Sym)* dlsym_linear_lookup(const char* name, soinfo** found, soinfo* start, soinfo* find_containing_library(const void* addr); ElfW(Sym)* dladdr_find_symbol(soinfo* si, const void* addr); -ElfW(Sym)* dlsym_handle_lookup(soinfo* si, const char* name, soinfo* caller_si); +ElfW(Sym)* dlsym_handle_lookup(soinfo* si, soinfo** found, const char* name, soinfo* caller_si); void debuggerd_init(); extern "C" abort_msg_t* g_abort_message; diff --git a/linker/tests/linked_list_test.cpp b/linker/tests/linked_list_test.cpp index 31ec7d5..b9816fa 100644 --- a/linker/tests/linked_list_test.cpp +++ b/linker/tests/linked_list_test.cpp @@ -95,3 +95,23 @@ TEST(linked_list, simple) { ASSERT_TRUE(free_called); ASSERT_EQ("", test_list_to_string(list)); } + +TEST(linked_list, push_pop) { + test_list_t list; + list.push_front("b"); + list.push_front("a"); + ASSERT_EQ("ab", test_list_to_string(list)); + list.push_back("c"); + ASSERT_EQ("abc", test_list_to_string(list)); + ASSERT_EQ("a", list.pop_front()); + ASSERT_EQ("bc", test_list_to_string(list)); + ASSERT_EQ("b", list.pop_front()); + ASSERT_EQ("c", test_list_to_string(list)); + ASSERT_EQ("c", list.pop_front()); + ASSERT_EQ("", test_list_to_string(list)); + ASSERT_TRUE(list.pop_front() == nullptr); + list.push_back("r"); + ASSERT_EQ("r", test_list_to_string(list)); + ASSERT_EQ("r", list.pop_front()); + ASSERT_TRUE(list.pop_front() == nullptr); +} diff --git a/tests/dlfcn_test.cpp b/tests/dlfcn_test.cpp index f056fb6..9bc2557 100644 --- a/tests/dlfcn_test.cpp +++ b/tests/dlfcn_test.cpp @@ -62,10 +62,9 @@ TEST(dlfcn, dlsym_in_self) { ASSERT_EQ(0, dlclose(self)); } -#if !defined(__LP64__) -// Current compiler/static linker used for aarch64 -// platform optimizes LOCAL PROTECTED symbol -// in libtest_local_symbol.so out of existence +#if defined(__arm__) +// This seems to be working only for arm. +// Others platforms optimize LOCAL PROTECTED symbols. TEST(dlfcn, dlsym_local_symbol) { void* handle = dlopen("libtest_local_symbol.so", RTLD_NOW); ASSERT_TRUE(handle != NULL); @@ -78,9 +77,23 @@ TEST(dlfcn, dlsym_local_symbol) { f = reinterpret_cast<uint32_t (*)(void)>(dlsym(handle, "dlsym_local_symbol_get_taxicab_number_using_dlsym")); ASSERT_TRUE(f != NULL); ASSERT_EQ(1729U, f()); + dlclose(handle); } #endif +TEST(dlfcn, dlsym_with_dependencies) { + void* handle = dlopen("libtest_with_dependency.so", RTLD_NOW); + ASSERT_TRUE(handle != NULL); + dlerror(); + // This symbol is in DT_NEEDED library. + void* sym = dlsym(handle, "getRandomNumber"); + ASSERT_TRUE(sym != NULL); + int (*fn)(void); + fn = reinterpret_cast<int (*)(void)>(sym); + EXPECT_EQ(4, fn()); + dlclose(handle); +} + TEST(dlfcn, dlopen_noload) { void* handle = dlopen("libtest_simple.so", RTLD_NOW | RTLD_NOLOAD); ASSERT_TRUE(handle == NULL); diff --git a/tests/libs/Android.mk b/tests/libs/Android.mk index a374e48..7ed3e7b 100644 --- a/tests/libs/Android.mk +++ b/tests/libs/Android.mk @@ -102,6 +102,19 @@ build_target := SHARED_LIBRARY include $(TEST_PATH)/Android.build.mk # ----------------------------------------------------------------------------- +# Library with dependency used by dlfcn tests +# ----------------------------------------------------------------------------- +libtest_with_dependency_src_files := \ + dlopen_testlib_simple.cpp + +libtest_with_dependency_shared_libraries := libdlext_test + +module := libtest_with_dependency +build_type := target +build_target := SHARED_LIBRARY +include $(TEST_PATH)/Android.build.mk + +# ----------------------------------------------------------------------------- # Library used to test local symbol lookup # ----------------------------------------------------------------------------- libtest_local_symbol_src_files := \ diff --git a/tests/locale_test.cpp b/tests/locale_test.cpp index 7d063f9..325f6ce 100644 --- a/tests/locale_test.cpp +++ b/tests/locale_test.cpp @@ -48,8 +48,8 @@ TEST(locale, localeconv) { } TEST(locale, setlocale) { - EXPECT_STREQ("C", setlocale(LC_ALL, NULL)); - EXPECT_STREQ("C", setlocale(LC_CTYPE, NULL)); + EXPECT_STREQ("C.UTF-8", setlocale(LC_ALL, NULL)); + EXPECT_STREQ("C.UTF-8", setlocale(LC_CTYPE, NULL)); errno = 0; EXPECT_EQ(NULL, setlocale(-1, NULL)); @@ -105,3 +105,20 @@ TEST(locale, uselocale) { EXPECT_EQ(n, uselocale(NULL)); } + +TEST(locale, mb_cur_max) { + // We can't reliably test the behavior with setlocale(3) or the behavior for + // initial program conditions because (unless we're the only test that was + // run), another test has almost certainly called uselocale(3) in this thread. + // See b/16685652. + locale_t cloc = newlocale(LC_ALL, "C", 0); + locale_t cloc_utf8 = newlocale(LC_ALL, "C.UTF-8", 0); + + uselocale(cloc); + ASSERT_EQ(1U, MB_CUR_MAX); + uselocale(cloc_utf8); + ASSERT_EQ(4U, MB_CUR_MAX); + + freelocale(cloc); + freelocale(cloc_utf8); +} diff --git a/tests/stdio_test.cpp b/tests/stdio_test.cpp index 18dae9c..bb86509 100644 --- a/tests/stdio_test.cpp +++ b/tests/stdio_test.cpp @@ -427,6 +427,9 @@ TEST(stdio, snprintf_negative_zero_5084292) { } TEST(stdio, snprintf_utf8_15439554) { + locale_t cloc = newlocale(LC_ALL, "C.UTF-8", 0); + uselocale(cloc); + // http://b/15439554 char buf[BUFSIZ]; @@ -442,6 +445,8 @@ TEST(stdio, snprintf_utf8_15439554) { // 4-byte character. snprintf(buf, sizeof(buf), "%d\xf0\xa4\xad\xa2%d", 1, 2); EXPECT_STREQ("1𤭢2", buf); + + freelocale(cloc); } TEST(stdio, fprintf_failures_7229520) { diff --git a/tests/wchar_test.cpp b/tests/wchar_test.cpp index f052ce6..d02c4bf 100644 --- a/tests/wchar_test.cpp +++ b/tests/wchar_test.cpp @@ -351,7 +351,7 @@ void test_mbsrtowcs(mbstate_t* ps) { // Check that we didn't clobber the rest of out. ASSERT_EQ(L'x', out[3]); // Check that valid has advanced to the end of the string. - ASSERT_EQ(L'\0', *valid); + ASSERT_EQ(nullptr, valid); const char* invalid = "A" "\xc2\x20" "ef"; ASSERT_EQ(static_cast<size_t>(-1), mbsrtowcs(out, &invalid, 4, ps)); |
