diff --git a/libc/Android.mk b/libc/Android.mk index 3e37ca7ec..ef1fb9be6 100644 --- a/libc/Android.mk +++ b/libc/Android.mk @@ -479,6 +479,7 @@ libc_upstream_openbsd_src_files := \ upstream-openbsd/lib/libc/stdlib/getenv.c \ upstream-openbsd/lib/libc/stdlib/insque.c \ upstream-openbsd/lib/libc/stdlib/lsearch.c \ + upstream-openbsd/lib/libc/stdlib/reallocarray.c \ upstream-openbsd/lib/libc/stdlib/remque.c \ upstream-openbsd/lib/libc/stdlib/setenv.c \ upstream-openbsd/lib/libc/stdlib/strtoimax.c \ diff --git a/libc/bionic/fts.c b/libc/bionic/fts.c index c491b6a0b..31a4b2ff5 100644 --- a/libc/bionic/fts.c +++ b/libc/bionic/fts.c @@ -1,4 +1,4 @@ -/* $OpenBSD: fts.c,v 1.46 2014/05/25 17:47:04 tedu Exp $ */ +/* $OpenBSD: fts.c,v 1.48 2014/11/20 04:14:15 guenther Exp $ */ /*- * Copyright (c) 1990, 1993, 1994 @@ -49,11 +49,12 @@ static size_t fts_maxarglen(char * const *); static void fts_padjust(FTS *, FTSENT *); static int fts_palloc(FTS *, size_t); static FTSENT *fts_sort(FTS *, FTSENT *, int); -static u_short fts_stat(FTS *, FTSENT *, int); +static u_short fts_stat(FTS *, FTSENT *, int, int); static int fts_safe_changedir(FTS *, FTSENT *, int, char *); #define ALIGNBYTES (sizeof(uintptr_t) - 1) #define ALIGN(p) (((uintptr_t)(p) + ALIGNBYTES) &~ ALIGNBYTES) +void* reallocarray(void*, size_t, size_t); #define ISDOT(a) (a[0] == '.' && (!a[1] || (a[1] == '.' && !a[2]))) @@ -119,7 +120,7 @@ fts_open(char * const *argv, int options, p->fts_level = FTS_ROOTLEVEL; p->fts_parent = parent; p->fts_accpath = p->fts_name; - p->fts_info = fts_stat(sp, p, ISSET(FTS_COMFOLLOW)); + p->fts_info = fts_stat(sp, p, ISSET(FTS_COMFOLLOW), -1); /* Command-line "." and ".." are real directories. */ if (p->fts_info == FTS_DOT) @@ -273,7 +274,7 @@ fts_read(FTS *sp) /* Any type of file may be re-visited; re-stat and re-turn. */ if (instr == FTS_AGAIN) { - p->fts_info = fts_stat(sp, p, 0); + p->fts_info = fts_stat(sp, p, 0, -1); return (p); } @@ -285,7 +286,7 @@ fts_read(FTS *sp) */ if (instr == FTS_FOLLOW && (p->fts_info == FTS_SL || p->fts_info == FTS_SLNONE)) { - p->fts_info = fts_stat(sp, p, 1); + p->fts_info = fts_stat(sp, p, 1, -1); if (p->fts_info == FTS_D && !ISSET(FTS_NOCHDIR)) { if ((p->fts_symfd = open(".", O_RDONLY, 0)) < 0) { p->fts_errno = errno; @@ -374,7 +375,7 @@ next: tmp = p; if (p->fts_instr == FTS_SKIP) goto next; if (p->fts_instr == FTS_FOLLOW) { - p->fts_info = fts_stat(sp, p, 1); + p->fts_info = fts_stat(sp, p, 1, -1); if (p->fts_info == FTS_D && !ISSET(FTS_NOCHDIR)) { if ((p->fts_symfd = open(".", O_RDONLY, 0)) < 0) { @@ -719,10 +720,11 @@ mem1: saved_errno = errno; if (ISSET(FTS_NOCHDIR)) { p->fts_accpath = p->fts_path; memmove(cp, p->fts_name, p->fts_namelen + 1); - } else + p->fts_info = fts_stat(sp, p, 0, dirfd(dirp)); + } else { p->fts_accpath = p->fts_name; - /* Stat it. */ - p->fts_info = fts_stat(sp, p, 0); + p->fts_info = fts_stat(sp, p, 0, -1); + } /* Decrement link count if applicable. */ if (nlinks > 0 && (p->fts_info == FTS_D || @@ -789,13 +791,20 @@ mem1: saved_errno = errno; } static u_short -fts_stat(FTS *sp, FTSENT *p, int follow) +fts_stat(FTS *sp, FTSENT *p, int follow, int dfd) { FTSENT *t; dev_t dev; ino_t ino; struct stat *sbp, sb; int saved_errno; + const char *path; + + if (dfd == -1) { + path = p->fts_accpath; + dfd = AT_FDCWD; + } else + path = p->fts_name; /* If user needs stat info, stat buffer already allocated. */ sbp = ISSET(FTS_NOSTAT) ? &sb : p->fts_statp; @@ -806,16 +815,16 @@ fts_stat(FTS *sp, FTSENT *p, int follow) * fail, set the errno from the stat call. */ if (ISSET(FTS_LOGICAL) || follow) { - if (stat(p->fts_accpath, sbp)) { + if (fstatat(dfd, path, sbp, 0)) { saved_errno = errno; - if (!lstat(p->fts_accpath, sbp)) { + if (!fstatat(dfd, path, sbp, AT_SYMLINK_NOFOLLOW)) { errno = 0; return (FTS_SLNONE); } p->fts_errno = saved_errno; goto err; } - } else if (lstat(p->fts_accpath, sbp)) { + } else if (fstatat(dfd, path, sbp, AT_SYMLINK_NOFOLLOW)) { p->fts_errno = errno; err: memset(sbp, 0, sizeof(struct stat)); return (FTS_NS); @@ -873,8 +882,8 @@ fts_sort(FTS *sp, FTSENT *head, int nitems) struct _ftsent **a; sp->fts_nitems = nitems + 40; - if ((a = realloc(sp->fts_array, - sp->fts_nitems * sizeof(FTSENT *))) == NULL) { + if ((a = reallocarray(sp->fts_array, + sp->fts_nitems, sizeof(FTSENT *))) == NULL) { if (sp->fts_array) free(sp->fts_array); sp->fts_array = NULL; diff --git a/libc/upstream-openbsd/android/include/openbsd-compat.h b/libc/upstream-openbsd/android/include/openbsd-compat.h index 268b3b63a..8386ba5fc 100644 --- a/libc/upstream-openbsd/android/include/openbsd-compat.h +++ b/libc/upstream-openbsd/android/include/openbsd-compat.h @@ -59,6 +59,9 @@ /* We have OpenBSD's getentropy_linux.c, but we don't mention getentropy in any header. */ __LIBC_HIDDEN__ extern int getentropy(void*, size_t); +/* OpenBSD has this as API, but we just use it internally. */ +__LIBC_HIDDEN__ void* reallocarray(void*, size_t, size_t); + /* LP32 NDK ctype.h contained references to these. */ __LIBC64_HIDDEN__ extern const short* _tolower_tab_; __LIBC64_HIDDEN__ extern const short* _toupper_tab_; diff --git a/libc/upstream-openbsd/lib/libc/stdlib/reallocarray.c b/libc/upstream-openbsd/lib/libc/stdlib/reallocarray.c new file mode 100644 index 000000000..7accd99e0 --- /dev/null +++ b/libc/upstream-openbsd/lib/libc/stdlib/reallocarray.c @@ -0,0 +1,38 @@ +/* $OpenBSD: reallocarray.c,v 1.1 2014/05/08 21:43:49 deraadt Exp $ */ +/* + * Copyright (c) 2008 Otto Moerbeek + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include + +/* + * This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX + * if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW + */ +#define MUL_NO_OVERFLOW (1UL << (sizeof(size_t) * 4)) + +void * +reallocarray(void *optr, size_t nmemb, size_t size) +{ + if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) && + nmemb > 0 && SIZE_MAX / nmemb < size) { + errno = ENOMEM; + return NULL; + } + return realloc(optr, size * nmemb); +}