From a828a2f8e6fd5271787a7dea4c682cbf54425a14 Mon Sep 17 00:00:00 2001 From: "Torne (Richard Coles)" Date: Wed, 2 Sep 2015 14:14:08 +0100 Subject: linker: don't pass dlextinfo to dependent loads. Don't pass the parent load's dlextinfo to dependent loads, since this causes the linker to try to load the dependencies using the same addresses/relro/fds/etc as the main library, which is never going to work. This was how it worked before ae69a95 which broke this. Bug: 23742664 Change-Id: I53d8cdf0982d8758e6d2ced4864c704cdf74118f --- linker/linker.cpp | 7 ++++--- tests/libs/Android.mk | 2 ++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/linker/linker.cpp b/linker/linker.cpp index b860f70..faacd49 100644 --- a/linker/linker.cpp +++ b/linker/linker.cpp @@ -1468,13 +1468,14 @@ static bool find_libraries(soinfo* start_with, const char* const library_names[] // Step 1: load and pre-link all DT_NEEDED libraries in breadth first order. for (LoadTask::unique_ptr task(load_tasks.pop_front()); task.get() != nullptr; task.reset(load_tasks.pop_front())) { - soinfo* si = find_library_internal(load_tasks, task->get_name(), rtld_flags, extinfo); + soinfo* needed_by = task->get_needed_by(); + + soinfo* si = find_library_internal(load_tasks, task->get_name(), + rtld_flags, needed_by == nullptr ? extinfo : nullptr); if (si == nullptr) { return false; } - soinfo* needed_by = task->get_needed_by(); - if (needed_by != nullptr) { needed_by->add_child(si); } diff --git a/tests/libs/Android.mk b/tests/libs/Android.mk index a5ef622..5b96306 100644 --- a/tests/libs/Android.mk +++ b/tests/libs/Android.mk @@ -67,6 +67,8 @@ libdlext_test_src_files := \ libdlext_test_ldflags := \ -Wl,-z,relro \ +libdlext_test_shared_libraries := libtest_simple + module := libdlext_test module_tag := optional include $(LOCAL_PATH)/Android.build.testlib.mk -- cgit v1.1 From f32b689d3dbe7a1317bce58d1d9bef9bba173c66 Mon Sep 17 00:00:00 2001 From: Dmitriy Ivanov Date: Tue, 13 Oct 2015 11:07:56 -0700 Subject: Log dlopen failures caused by text relocations Some apps will fail to load native libraries with text relocations when switching target sdk version to M. It could be hard to diagnose because some of them suppress dlerror and/or UnsatisfiedLinkError. This change unconditionally logs the error message making the cause of the failure more visible to developers. Bug: http://b/24876001 Change-Id: I0477a0d1307d0879000f3a3a43b974b4cf34bdb2 --- linker/linker.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/linker/linker.cpp b/linker/linker.cpp index faacd49..c99042f 100644 --- a/linker/linker.cpp +++ b/linker/linker.cpp @@ -2937,6 +2937,7 @@ bool soinfo::link_image(const soinfo_list_t& global_group, const soinfo_list_t& // TODO (dimitry): remove != __ANDROID_API__ check once http://b/20020312 is fixed if (get_application_target_sdk_version() != __ANDROID_API__ && get_application_target_sdk_version() > 22) { + PRINT("%s: has text relocations", get_realpath()); DL_ERR("%s: has text relocations", get_realpath()); return false; } -- cgit v1.1 From cd9278798a61b653fd8875eca77fb13b1b44496a Mon Sep 17 00:00:00 2001 From: Neil Fuller Date: Fri, 9 Oct 2015 17:58:58 +0100 Subject: Update timezone data to 2015g Changes affecting future time stamps Turkey's 2015 fall-back transition is scheduled for Nov. 8, not Oct. 25. (Thanks to Fatih.) Norfolk moves from +1130 to +1100 on 2015-10-04 at 02:00 local time. (Thanks to Alexander Krivenyshev.) Fiji's 2016 fall-back transition is scheduled for January 17, not 24. (Thanks to Ken Rylander.) Fort Nelson, British Columbia will not fall back on 2015-11-01. It has effectively been on MST (-0700) since it advanced its clocks on 2015-03-08. New zone America/Fort_Nelson. (Thanks to Matt Johnson.) Changes affecting past time stamps Norfolk observed DST from 1974-10-27 02:00 to 1975-03-02 02:00. Bug: 24595281 (cherry-picked from commit 31740bfdb942399235e42ea920b6b717dfa0279c) Change-Id: I6a57fbdaf12a4b4ebf2a760fd3bd872055621106 --- libc/zoneinfo/tzdata | Bin 491816 -> 494261 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/libc/zoneinfo/tzdata b/libc/zoneinfo/tzdata index f22464e..c464f46 100644 Binary files a/libc/zoneinfo/tzdata and b/libc/zoneinfo/tzdata differ -- cgit v1.1 From cf92738fa5dee24050028a1235f815f2a0fd33b5 Mon Sep 17 00:00:00 2001 From: Dmitriy Ivanov Date: Wed, 14 Oct 2015 11:15:45 -0700 Subject: Ensure that readlink has access to /proc/self/fd /proc/self/fd is not available when PR_DUMPABLE is set to 0 which is default for the user builds. It leads to permission denials on readlink. This change fixes the problem by setting PR_DUMPABLE flag to 1 for readlink and restoring it's previous value after the call. Bug: http://b/24912743 Change-Id: I3fd179c5c6b56af96d6a15ee597024ccb15e1a13 --- linker/linker.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/linker/linker.cpp b/linker/linker.cpp index c99042f..d3ac1d0 100644 --- a/linker/linker.cpp +++ b/linker/linker.cpp @@ -37,6 +37,7 @@ #include #include #include +#include #include #include @@ -317,6 +318,13 @@ static void parse_LD_PRELOAD(const char* path) { static bool realpath_fd(int fd, std::string* realpath) { std::vector buf(PATH_MAX), proc_self_fd(PATH_MAX); snprintf(&proc_self_fd[0], proc_self_fd.size(), "/proc/self/fd/%d", fd); + // set DUMPABLE to 1 to access /proc/self/fd + int dumpable = prctl(PR_GET_DUMPABLE, 0, 0, 0, 0); + prctl(PR_SET_DUMPABLE, 1, 0, 0, 0); + auto guard = make_scope_guard([&]() { + // restore dumpable + prctl(PR_SET_DUMPABLE, dumpable, 0, 0, 0); + }); if (readlink(&proc_self_fd[0], &buf[0], buf.size()) == -1) { PRINT("readlink('%s') failed: %s [fd=%d]", &proc_self_fd[0], strerror(errno), fd); return false; -- cgit v1.1 From 9a9572d577eacc5f1c83a92655fbbe5cd897236b Mon Sep 17 00:00:00 2001 From: Elliott Hughes Date: Mon, 14 Sep 2015 18:45:52 -0700 Subject: Sync with upstream NetBSD lib/libc/regex. Bug: http://b/22850181 (cherry picked from commit 71927a82379f7a72559ea96e6678d6215090937f) Change-Id: I4a914f0594a66f38efb3026b7ba9d28a4887cb2d --- libc/Android.mk | 1 + .../android/include/netbsd-compat.h | 3 + libc/upstream-netbsd/lib/libc/regex/regcomp.c | 81 +++++++----------- libc/upstream-netbsd/lib/libc/stdlib/reallocarr.c | 95 ++++++++++++++++++++++ 4 files changed, 130 insertions(+), 50 deletions(-) create mode 100644 libc/upstream-netbsd/lib/libc/stdlib/reallocarr.c diff --git a/libc/Android.mk b/libc/Android.mk index b50717d..f0c5e9f 100644 --- a/libc/Android.mk +++ b/libc/Android.mk @@ -309,6 +309,7 @@ libc_upstream_netbsd_src_files := \ upstream-netbsd/lib/libc/stdlib/nrand48.c \ upstream-netbsd/lib/libc/stdlib/_rand48.c \ upstream-netbsd/lib/libc/stdlib/rand_r.c \ + upstream-netbsd/lib/libc/stdlib/reallocarr.c \ upstream-netbsd/lib/libc/stdlib/seed48.c \ upstream-netbsd/lib/libc/stdlib/srand48.c \ upstream-netbsd/lib/libc/string/memccpy.c \ diff --git a/libc/upstream-netbsd/android/include/netbsd-compat.h b/libc/upstream-netbsd/android/include/netbsd-compat.h index 04bc728..0212d16 100644 --- a/libc/upstream-netbsd/android/include/netbsd-compat.h +++ b/libc/upstream-netbsd/android/include/netbsd-compat.h @@ -31,4 +31,7 @@ #define __readlockenv() 0 #define __unlockenv() 0 +#include +int reallocarr(void*, size_t, size_t); + #endif diff --git a/libc/upstream-netbsd/lib/libc/regex/regcomp.c b/libc/upstream-netbsd/lib/libc/regex/regcomp.c index 2644a22..6af9734 100644 --- a/libc/upstream-netbsd/lib/libc/regex/regcomp.c +++ b/libc/upstream-netbsd/lib/libc/regex/regcomp.c @@ -1,4 +1,4 @@ -/* $NetBSD: regcomp.c,v 1.33 2012/03/13 21:13:43 christos Exp $ */ +/* $NetBSD: regcomp.c,v 1.36 2015/09/12 19:08:47 christos Exp $ */ /*- * Copyright (c) 1992, 1993, 1994 @@ -76,7 +76,7 @@ #if 0 static char sccsid[] = "@(#)regcomp.c 8.5 (Berkeley) 3/20/94"; #else -__RCSID("$NetBSD: regcomp.c,v 1.33 2012/03/13 21:13:43 christos Exp $"); +__RCSID("$NetBSD: regcomp.c,v 1.36 2015/09/12 19:08:47 christos Exp $"); #endif #endif /* LIBC_SCCS and not lint */ @@ -262,12 +262,11 @@ regcomp( len = strlen(pattern); /* do the mallocs early so failure handling is easy */ - g = (struct re_guts *)malloc(sizeof(struct re_guts) + - (NC-1)*sizeof(cat_t)); + g = malloc(sizeof(struct re_guts) + (NC - 1) * sizeof(cat_t)); if (g == NULL) return(REG_ESPACE); p->ssize = len/(size_t)2*(size_t)3 + (size_t)1; /* ugh */ - p->strip = malloc(p->ssize * sizeof(sop)); + p->strip = calloc(p->ssize, sizeof(sop)); p->slen = 0; if (p->strip == NULL) { free(g); @@ -1075,19 +1074,19 @@ ordinary( int ch) { cat_t *cap; + unsigned char uc = (unsigned char)ch; _DIAGASSERT(p != NULL); cap = p->g->categories; - if ((p->g->cflags®_ICASE) && isalpha((unsigned char) ch) - && othercase((unsigned char) ch) != (unsigned char) ch) - bothcases(p, (unsigned char) ch); + if ((p->g->cflags & REG_ICASE) && isalpha(uc) && othercase(uc) != uc) + bothcases(p, uc); else { - EMIT(OCHAR, (sopno)(unsigned char)ch); - if (cap[ch] == 0) { + EMIT(OCHAR, (sopno)uc); + if (cap[uc] == 0) { _DIAGASSERT(__type_fit(unsigned char, p->g->ncategories + 1)); - cap[ch] = (unsigned char)p->g->ncategories++; + cap[uc] = (unsigned char)p->g->ncategories++; } } } @@ -1236,6 +1235,7 @@ allocset( cset *cs; size_t css; size_t i; + void *old_ptr; _DIAGASSERT(p != NULL); @@ -1248,28 +1248,18 @@ allocset( nbytes = nc / CHAR_BIT * css; if (MEMSIZE(p) > MEMLIMIT) goto oomem; - if (p->g->sets == NULL) - p->g->sets = malloc(nc * sizeof(cset)); - else - p->g->sets = realloc(p->g->sets, nc * sizeof(cset)); - if (p->g->setbits == NULL) - p->g->setbits = malloc(nbytes); - else { - p->g->setbits = realloc(p->g->setbits, nbytes); - /* xxx this isn't right if setbits is now NULL */ + if (reallocarr(&p->g->sets, nc, sizeof(cset))) + goto oomem; + old_ptr = p->g->setbits; + if (reallocarr(&p->g->setbits, nc / CHAR_BIT, css)) { + free(old_ptr); + goto oomem; + } + if (old_ptr != p->g->setbits) { for (i = 0; i < no; i++) p->g->sets[i].ptr = p->g->setbits + css*(i/CHAR_BIT); } - if (p->g->sets != NULL && p->g->setbits != NULL) - (void) memset((char *)p->g->setbits + (nbytes - css), - 0, css); - else { -oomem: - no = 0; - SETERROR(REG_ESPACE); - /* caller's responsibility not to do set ops */ - return NULL; - } + (void) memset((char *)p->g->setbits + (nbytes - css), 0, css); } cs = &p->g->sets[no]; @@ -1280,6 +1270,11 @@ oomem: cs->multis = NULL; return(cs); + +oomem: + SETERROR(REG_ESPACE); + /* caller's responsibility not to do set ops */ + return NULL; } /* @@ -1763,30 +1758,18 @@ dofwd( == static void enlarge(struct parse *p, sopno size); */ static int -enlarge( - struct parse *p, - sopno size) +enlarge(struct parse *p, sopno size) { - sop *sp; - sopno osize; - _DIAGASSERT(p != NULL); if (p->ssize >= size) return 1; - osize = p->ssize; - p->ssize = size; - if (MEMSIZE(p) > MEMLIMIT) - goto oomem; - sp = realloc(p->strip, p->ssize * sizeof(sop)); - if (sp == NULL) { -oomem: - p->ssize = osize; + if (MEMSIZE(p) > MEMLIMIT || reallocarr(&p->strip, size, sizeof(sop))) { SETERROR(REG_ESPACE); return 0; } - p->strip = sp; + p->ssize = size; return 1; } @@ -1804,11 +1787,9 @@ stripsnug( _DIAGASSERT(g != NULL); g->nstates = p->slen; - g->strip = realloc(p->strip, p->slen * sizeof(sop)); - if (g->strip == NULL) { - SETERROR(REG_ESPACE); - g->strip = p->strip; - } + g->strip = p->strip; + reallocarr(&g->strip, p->slen, sizeof(sop)); + /* Ignore error as tries to free memory only. */ } /* diff --git a/libc/upstream-netbsd/lib/libc/stdlib/reallocarr.c b/libc/upstream-netbsd/lib/libc/stdlib/reallocarr.c new file mode 100644 index 0000000..6ffe811 --- /dev/null +++ b/libc/upstream-netbsd/lib/libc/stdlib/reallocarr.c @@ -0,0 +1,95 @@ +/* $NetBSD: reallocarr.c,v 1.5 2015/08/20 22:27:49 kamil Exp $ */ + +/*- + * Copyright (c) 2015 Joerg Sonnenberger . + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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 HOLDERS 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. + */ + +#if HAVE_NBTOOL_CONFIG_H +#include "nbtool_config.h" +#endif + +#include +__RCSID("$NetBSD: reallocarr.c,v 1.5 2015/08/20 22:27:49 kamil Exp $"); + +#include "namespace.h" +#include +/* Old POSIX has SIZE_MAX in limits.h */ +#include +#include +#include +#include + +#ifdef _LIBC +#ifdef __weak_alias +__weak_alias(reallocarr, _reallocarr) +#endif +#endif + +#define SQRT_SIZE_MAX (((size_t)1) << (sizeof(size_t) * CHAR_BIT / 2)) + +#if !HAVE_REALLOCARR +int +reallocarr(void *ptr, size_t number, size_t size) +{ + int saved_errno, result; + void *optr; + void *nptr; + + saved_errno = errno; + memcpy(&optr, ptr, sizeof(ptr)); + if (number == 0 || size == 0) { + free(optr); + nptr = NULL; + memcpy(ptr, &nptr, sizeof(ptr)); + errno = saved_errno; + return 0; + } + + /* + * Try to avoid division here. + * + * It isn't possible to overflow during multiplication if neither + * operand uses any of the most significant half of the bits. + */ + if (__predict_false((number|size) >= SQRT_SIZE_MAX && + number > SIZE_MAX / size)) { + errno = saved_errno; + return EOVERFLOW; + } + + nptr = realloc(optr, number * size); + if (__predict_false(nptr == NULL)) { + result = errno; + } else { + result = 0; + memcpy(ptr, &nptr, sizeof(ptr)); + } + errno = saved_errno; + return result; +} +#endif -- cgit v1.1 From beb6e08abf1393663151afde2742bb23eccab4e1 Mon Sep 17 00:00:00 2001 From: Elliott Hughes Date: Mon, 14 Sep 2015 18:45:52 -0700 Subject: Sync with upstream NetBSD lib/libc/regex. Bug: http://b/22850181 (cherry-picked from commit 71927a82379f7a72559ea96e6678d6215090937f) Change-Id: I11a51a2031e68a953ccd5691da98c699c7d01904 --- libc/Android.mk | 1 + libc/upstream-netbsd/libc/regex/regcomp.c | 81 +++++++++-------------- libc/upstream-netbsd/libc/stdlib/reallocarr.c | 95 +++++++++++++++++++++++++++ libc/upstream-netbsd/netbsd-compat.h | 3 + 4 files changed, 130 insertions(+), 50 deletions(-) create mode 100644 libc/upstream-netbsd/libc/stdlib/reallocarr.c diff --git a/libc/Android.mk b/libc/Android.mk index 9610c14..984187f 100644 --- a/libc/Android.mk +++ b/libc/Android.mk @@ -349,6 +349,7 @@ libc_upstream_netbsd_src_files := \ upstream-netbsd/libc/stdlib/mrand48.c \ upstream-netbsd/libc/stdlib/nrand48.c \ upstream-netbsd/libc/stdlib/_rand48.c \ + upstream-netbsd/libc/stdlib/reallocarr.c \ upstream-netbsd/libc/stdlib/seed48.c \ upstream-netbsd/libc/stdlib/srand48.c \ upstream-netbsd/libc/stdlib/tdelete.c \ diff --git a/libc/upstream-netbsd/libc/regex/regcomp.c b/libc/upstream-netbsd/libc/regex/regcomp.c index 2644a22..6af9734 100644 --- a/libc/upstream-netbsd/libc/regex/regcomp.c +++ b/libc/upstream-netbsd/libc/regex/regcomp.c @@ -1,4 +1,4 @@ -/* $NetBSD: regcomp.c,v 1.33 2012/03/13 21:13:43 christos Exp $ */ +/* $NetBSD: regcomp.c,v 1.36 2015/09/12 19:08:47 christos Exp $ */ /*- * Copyright (c) 1992, 1993, 1994 @@ -76,7 +76,7 @@ #if 0 static char sccsid[] = "@(#)regcomp.c 8.5 (Berkeley) 3/20/94"; #else -__RCSID("$NetBSD: regcomp.c,v 1.33 2012/03/13 21:13:43 christos Exp $"); +__RCSID("$NetBSD: regcomp.c,v 1.36 2015/09/12 19:08:47 christos Exp $"); #endif #endif /* LIBC_SCCS and not lint */ @@ -262,12 +262,11 @@ regcomp( len = strlen(pattern); /* do the mallocs early so failure handling is easy */ - g = (struct re_guts *)malloc(sizeof(struct re_guts) + - (NC-1)*sizeof(cat_t)); + g = malloc(sizeof(struct re_guts) + (NC - 1) * sizeof(cat_t)); if (g == NULL) return(REG_ESPACE); p->ssize = len/(size_t)2*(size_t)3 + (size_t)1; /* ugh */ - p->strip = malloc(p->ssize * sizeof(sop)); + p->strip = calloc(p->ssize, sizeof(sop)); p->slen = 0; if (p->strip == NULL) { free(g); @@ -1075,19 +1074,19 @@ ordinary( int ch) { cat_t *cap; + unsigned char uc = (unsigned char)ch; _DIAGASSERT(p != NULL); cap = p->g->categories; - if ((p->g->cflags®_ICASE) && isalpha((unsigned char) ch) - && othercase((unsigned char) ch) != (unsigned char) ch) - bothcases(p, (unsigned char) ch); + if ((p->g->cflags & REG_ICASE) && isalpha(uc) && othercase(uc) != uc) + bothcases(p, uc); else { - EMIT(OCHAR, (sopno)(unsigned char)ch); - if (cap[ch] == 0) { + EMIT(OCHAR, (sopno)uc); + if (cap[uc] == 0) { _DIAGASSERT(__type_fit(unsigned char, p->g->ncategories + 1)); - cap[ch] = (unsigned char)p->g->ncategories++; + cap[uc] = (unsigned char)p->g->ncategories++; } } } @@ -1236,6 +1235,7 @@ allocset( cset *cs; size_t css; size_t i; + void *old_ptr; _DIAGASSERT(p != NULL); @@ -1248,28 +1248,18 @@ allocset( nbytes = nc / CHAR_BIT * css; if (MEMSIZE(p) > MEMLIMIT) goto oomem; - if (p->g->sets == NULL) - p->g->sets = malloc(nc * sizeof(cset)); - else - p->g->sets = realloc(p->g->sets, nc * sizeof(cset)); - if (p->g->setbits == NULL) - p->g->setbits = malloc(nbytes); - else { - p->g->setbits = realloc(p->g->setbits, nbytes); - /* xxx this isn't right if setbits is now NULL */ + if (reallocarr(&p->g->sets, nc, sizeof(cset))) + goto oomem; + old_ptr = p->g->setbits; + if (reallocarr(&p->g->setbits, nc / CHAR_BIT, css)) { + free(old_ptr); + goto oomem; + } + if (old_ptr != p->g->setbits) { for (i = 0; i < no; i++) p->g->sets[i].ptr = p->g->setbits + css*(i/CHAR_BIT); } - if (p->g->sets != NULL && p->g->setbits != NULL) - (void) memset((char *)p->g->setbits + (nbytes - css), - 0, css); - else { -oomem: - no = 0; - SETERROR(REG_ESPACE); - /* caller's responsibility not to do set ops */ - return NULL; - } + (void) memset((char *)p->g->setbits + (nbytes - css), 0, css); } cs = &p->g->sets[no]; @@ -1280,6 +1270,11 @@ oomem: cs->multis = NULL; return(cs); + +oomem: + SETERROR(REG_ESPACE); + /* caller's responsibility not to do set ops */ + return NULL; } /* @@ -1763,30 +1758,18 @@ dofwd( == static void enlarge(struct parse *p, sopno size); */ static int -enlarge( - struct parse *p, - sopno size) +enlarge(struct parse *p, sopno size) { - sop *sp; - sopno osize; - _DIAGASSERT(p != NULL); if (p->ssize >= size) return 1; - osize = p->ssize; - p->ssize = size; - if (MEMSIZE(p) > MEMLIMIT) - goto oomem; - sp = realloc(p->strip, p->ssize * sizeof(sop)); - if (sp == NULL) { -oomem: - p->ssize = osize; + if (MEMSIZE(p) > MEMLIMIT || reallocarr(&p->strip, size, sizeof(sop))) { SETERROR(REG_ESPACE); return 0; } - p->strip = sp; + p->ssize = size; return 1; } @@ -1804,11 +1787,9 @@ stripsnug( _DIAGASSERT(g != NULL); g->nstates = p->slen; - g->strip = realloc(p->strip, p->slen * sizeof(sop)); - if (g->strip == NULL) { - SETERROR(REG_ESPACE); - g->strip = p->strip; - } + g->strip = p->strip; + reallocarr(&g->strip, p->slen, sizeof(sop)); + /* Ignore error as tries to free memory only. */ } /* diff --git a/libc/upstream-netbsd/libc/stdlib/reallocarr.c b/libc/upstream-netbsd/libc/stdlib/reallocarr.c new file mode 100644 index 0000000..6ffe811 --- /dev/null +++ b/libc/upstream-netbsd/libc/stdlib/reallocarr.c @@ -0,0 +1,95 @@ +/* $NetBSD: reallocarr.c,v 1.5 2015/08/20 22:27:49 kamil Exp $ */ + +/*- + * Copyright (c) 2015 Joerg Sonnenberger . + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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 HOLDERS 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. + */ + +#if HAVE_NBTOOL_CONFIG_H +#include "nbtool_config.h" +#endif + +#include +__RCSID("$NetBSD: reallocarr.c,v 1.5 2015/08/20 22:27:49 kamil Exp $"); + +#include "namespace.h" +#include +/* Old POSIX has SIZE_MAX in limits.h */ +#include +#include +#include +#include + +#ifdef _LIBC +#ifdef __weak_alias +__weak_alias(reallocarr, _reallocarr) +#endif +#endif + +#define SQRT_SIZE_MAX (((size_t)1) << (sizeof(size_t) * CHAR_BIT / 2)) + +#if !HAVE_REALLOCARR +int +reallocarr(void *ptr, size_t number, size_t size) +{ + int saved_errno, result; + void *optr; + void *nptr; + + saved_errno = errno; + memcpy(&optr, ptr, sizeof(ptr)); + if (number == 0 || size == 0) { + free(optr); + nptr = NULL; + memcpy(ptr, &nptr, sizeof(ptr)); + errno = saved_errno; + return 0; + } + + /* + * Try to avoid division here. + * + * It isn't possible to overflow during multiplication if neither + * operand uses any of the most significant half of the bits. + */ + if (__predict_false((number|size) >= SQRT_SIZE_MAX && + number > SIZE_MAX / size)) { + errno = saved_errno; + return EOVERFLOW; + } + + nptr = realloc(optr, number * size); + if (__predict_false(nptr == NULL)) { + result = errno; + } else { + result = 0; + memcpy(ptr, &nptr, sizeof(ptr)); + } + errno = saved_errno; + return result; +} +#endif diff --git a/libc/upstream-netbsd/netbsd-compat.h b/libc/upstream-netbsd/netbsd-compat.h index e33885e..3ef19e1 100644 --- a/libc/upstream-netbsd/netbsd-compat.h +++ b/libc/upstream-netbsd/netbsd-compat.h @@ -33,4 +33,7 @@ #define __readlockenv() 0 #define __unlockenv() 0 +#include +__LIBC_HIDDEN__ int reallocarr(void*, size_t, size_t); + #endif -- cgit v1.1 From 055a66c9b1017c01b82c12b65a571bf9efad8b19 Mon Sep 17 00:00:00 2001 From: Elliott Hughes Date: Mon, 14 Sep 2015 18:45:52 -0700 Subject: Sync with upstream NetBSD lib/libc/regex. Bug: http://b/22850181 Change-Id: I11a51a2031e68a953ccd5691da98c699c7d01904 (cherry-picked from commit 71927a82379f7a72559ea96e6678d6215090937f) --- libc/Android.mk | 1 + .../android/include/netbsd-compat.h | 3 + libc/upstream-netbsd/lib/libc/regex/regcomp.c | 81 +++++++----------- libc/upstream-netbsd/lib/libc/stdlib/reallocarr.c | 95 ++++++++++++++++++++++ 4 files changed, 130 insertions(+), 50 deletions(-) create mode 100644 libc/upstream-netbsd/lib/libc/stdlib/reallocarr.c diff --git a/libc/Android.mk b/libc/Android.mk index 9c5e785..5ea57be 100644 --- a/libc/Android.mk +++ b/libc/Android.mk @@ -295,6 +295,7 @@ libc_upstream_netbsd_src_files := \ upstream-netbsd/lib/libc/stdlib/nrand48.c \ upstream-netbsd/lib/libc/stdlib/_rand48.c \ upstream-netbsd/lib/libc/stdlib/rand_r.c \ + upstream-netbsd/lib/libc/stdlib/reallocarr.c \ upstream-netbsd/lib/libc/stdlib/remque.c \ upstream-netbsd/lib/libc/stdlib/seed48.c \ upstream-netbsd/lib/libc/stdlib/srand48.c \ diff --git a/libc/upstream-netbsd/android/include/netbsd-compat.h b/libc/upstream-netbsd/android/include/netbsd-compat.h index 84be931..f61e90a 100644 --- a/libc/upstream-netbsd/android/include/netbsd-compat.h +++ b/libc/upstream-netbsd/android/include/netbsd-compat.h @@ -31,4 +31,7 @@ #define __readlockenv() 0 #define __unlockenv() 0 +#include +__LIBC_HIDDEN__ int reallocarr(void*, size_t, size_t); + #endif diff --git a/libc/upstream-netbsd/lib/libc/regex/regcomp.c b/libc/upstream-netbsd/lib/libc/regex/regcomp.c index 2644a22..6af9734 100644 --- a/libc/upstream-netbsd/lib/libc/regex/regcomp.c +++ b/libc/upstream-netbsd/lib/libc/regex/regcomp.c @@ -1,4 +1,4 @@ -/* $NetBSD: regcomp.c,v 1.33 2012/03/13 21:13:43 christos Exp $ */ +/* $NetBSD: regcomp.c,v 1.36 2015/09/12 19:08:47 christos Exp $ */ /*- * Copyright (c) 1992, 1993, 1994 @@ -76,7 +76,7 @@ #if 0 static char sccsid[] = "@(#)regcomp.c 8.5 (Berkeley) 3/20/94"; #else -__RCSID("$NetBSD: regcomp.c,v 1.33 2012/03/13 21:13:43 christos Exp $"); +__RCSID("$NetBSD: regcomp.c,v 1.36 2015/09/12 19:08:47 christos Exp $"); #endif #endif /* LIBC_SCCS and not lint */ @@ -262,12 +262,11 @@ regcomp( len = strlen(pattern); /* do the mallocs early so failure handling is easy */ - g = (struct re_guts *)malloc(sizeof(struct re_guts) + - (NC-1)*sizeof(cat_t)); + g = malloc(sizeof(struct re_guts) + (NC - 1) * sizeof(cat_t)); if (g == NULL) return(REG_ESPACE); p->ssize = len/(size_t)2*(size_t)3 + (size_t)1; /* ugh */ - p->strip = malloc(p->ssize * sizeof(sop)); + p->strip = calloc(p->ssize, sizeof(sop)); p->slen = 0; if (p->strip == NULL) { free(g); @@ -1075,19 +1074,19 @@ ordinary( int ch) { cat_t *cap; + unsigned char uc = (unsigned char)ch; _DIAGASSERT(p != NULL); cap = p->g->categories; - if ((p->g->cflags®_ICASE) && isalpha((unsigned char) ch) - && othercase((unsigned char) ch) != (unsigned char) ch) - bothcases(p, (unsigned char) ch); + if ((p->g->cflags & REG_ICASE) && isalpha(uc) && othercase(uc) != uc) + bothcases(p, uc); else { - EMIT(OCHAR, (sopno)(unsigned char)ch); - if (cap[ch] == 0) { + EMIT(OCHAR, (sopno)uc); + if (cap[uc] == 0) { _DIAGASSERT(__type_fit(unsigned char, p->g->ncategories + 1)); - cap[ch] = (unsigned char)p->g->ncategories++; + cap[uc] = (unsigned char)p->g->ncategories++; } } } @@ -1236,6 +1235,7 @@ allocset( cset *cs; size_t css; size_t i; + void *old_ptr; _DIAGASSERT(p != NULL); @@ -1248,28 +1248,18 @@ allocset( nbytes = nc / CHAR_BIT * css; if (MEMSIZE(p) > MEMLIMIT) goto oomem; - if (p->g->sets == NULL) - p->g->sets = malloc(nc * sizeof(cset)); - else - p->g->sets = realloc(p->g->sets, nc * sizeof(cset)); - if (p->g->setbits == NULL) - p->g->setbits = malloc(nbytes); - else { - p->g->setbits = realloc(p->g->setbits, nbytes); - /* xxx this isn't right if setbits is now NULL */ + if (reallocarr(&p->g->sets, nc, sizeof(cset))) + goto oomem; + old_ptr = p->g->setbits; + if (reallocarr(&p->g->setbits, nc / CHAR_BIT, css)) { + free(old_ptr); + goto oomem; + } + if (old_ptr != p->g->setbits) { for (i = 0; i < no; i++) p->g->sets[i].ptr = p->g->setbits + css*(i/CHAR_BIT); } - if (p->g->sets != NULL && p->g->setbits != NULL) - (void) memset((char *)p->g->setbits + (nbytes - css), - 0, css); - else { -oomem: - no = 0; - SETERROR(REG_ESPACE); - /* caller's responsibility not to do set ops */ - return NULL; - } + (void) memset((char *)p->g->setbits + (nbytes - css), 0, css); } cs = &p->g->sets[no]; @@ -1280,6 +1270,11 @@ oomem: cs->multis = NULL; return(cs); + +oomem: + SETERROR(REG_ESPACE); + /* caller's responsibility not to do set ops */ + return NULL; } /* @@ -1763,30 +1758,18 @@ dofwd( == static void enlarge(struct parse *p, sopno size); */ static int -enlarge( - struct parse *p, - sopno size) +enlarge(struct parse *p, sopno size) { - sop *sp; - sopno osize; - _DIAGASSERT(p != NULL); if (p->ssize >= size) return 1; - osize = p->ssize; - p->ssize = size; - if (MEMSIZE(p) > MEMLIMIT) - goto oomem; - sp = realloc(p->strip, p->ssize * sizeof(sop)); - if (sp == NULL) { -oomem: - p->ssize = osize; + if (MEMSIZE(p) > MEMLIMIT || reallocarr(&p->strip, size, sizeof(sop))) { SETERROR(REG_ESPACE); return 0; } - p->strip = sp; + p->ssize = size; return 1; } @@ -1804,11 +1787,9 @@ stripsnug( _DIAGASSERT(g != NULL); g->nstates = p->slen; - g->strip = realloc(p->strip, p->slen * sizeof(sop)); - if (g->strip == NULL) { - SETERROR(REG_ESPACE); - g->strip = p->strip; - } + g->strip = p->strip; + reallocarr(&g->strip, p->slen, sizeof(sop)); + /* Ignore error as tries to free memory only. */ } /* diff --git a/libc/upstream-netbsd/lib/libc/stdlib/reallocarr.c b/libc/upstream-netbsd/lib/libc/stdlib/reallocarr.c new file mode 100644 index 0000000..6ffe811 --- /dev/null +++ b/libc/upstream-netbsd/lib/libc/stdlib/reallocarr.c @@ -0,0 +1,95 @@ +/* $NetBSD: reallocarr.c,v 1.5 2015/08/20 22:27:49 kamil Exp $ */ + +/*- + * Copyright (c) 2015 Joerg Sonnenberger . + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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 HOLDERS 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. + */ + +#if HAVE_NBTOOL_CONFIG_H +#include "nbtool_config.h" +#endif + +#include +__RCSID("$NetBSD: reallocarr.c,v 1.5 2015/08/20 22:27:49 kamil Exp $"); + +#include "namespace.h" +#include +/* Old POSIX has SIZE_MAX in limits.h */ +#include +#include +#include +#include + +#ifdef _LIBC +#ifdef __weak_alias +__weak_alias(reallocarr, _reallocarr) +#endif +#endif + +#define SQRT_SIZE_MAX (((size_t)1) << (sizeof(size_t) * CHAR_BIT / 2)) + +#if !HAVE_REALLOCARR +int +reallocarr(void *ptr, size_t number, size_t size) +{ + int saved_errno, result; + void *optr; + void *nptr; + + saved_errno = errno; + memcpy(&optr, ptr, sizeof(ptr)); + if (number == 0 || size == 0) { + free(optr); + nptr = NULL; + memcpy(ptr, &nptr, sizeof(ptr)); + errno = saved_errno; + return 0; + } + + /* + * Try to avoid division here. + * + * It isn't possible to overflow during multiplication if neither + * operand uses any of the most significant half of the bits. + */ + if (__predict_false((number|size) >= SQRT_SIZE_MAX && + number > SIZE_MAX / size)) { + errno = saved_errno; + return EOVERFLOW; + } + + nptr = realloc(optr, number * size); + if (__predict_false(nptr == NULL)) { + result = errno; + } else { + result = 0; + memcpy(ptr, &nptr, sizeof(ptr)); + } + errno = saved_errno; + return result; +} +#endif -- cgit v1.1