From patchwork Fri Aug 11 14:50:42 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adhemerval Zanella X-Patchwork-Id: 22099 Received: (qmail 91773 invoked by alias); 11 Aug 2017 14:51:36 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Delivered-To: mailing list libc-alpha@sourceware.org Received: (qmail 80126 invoked by uid 89); 11 Aug 2017 14:51:17 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-27.1 required=5.0 tests=BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, RCVD_IN_DNSWL_LOW, RCVD_IN_SORBS_SPAM, SPF_PASS autolearn=ham version=3.3.2 spammy=Hx-languages-length:6094 X-HELO: mail-qt0-f179.google.com X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references; bh=8Vi/qT6LUKc6gucjp+gE4JG5KMABTwG6RM6HY9jh7B8=; b=ZzGnrq9fwzK6Kp7SI3M818aUqws1NFDcWsp89FrXqiYHf6j3QHIhfZE5s3U8wMr6NA G1+rWU3BmK6+KcN9BycM/s53dhHu2q6bJgXWKjJEVs1yrADt46ydG6QWlo/6Fuyp/7ID GR31Ei5VrlPvGAdjDLz6dxQ2fT489qymgtvQp/fJswltMwmwtVmlHcZCuxpnOXUCeTLX /RGMPlm8Zi4OhVc2SYLIU/1rWBdmhDF0vcE3QKDaVA2nj73d/hNrtbTQHhh+jmiMD+Nj b7bHV7B5Zfc/a9DROZSfEqMh0wG6DP36H151bIq52eku9pOJqX9kCwk2VW1tq+GKNIXb I89Q== X-Gm-Message-State: AHYfb5hT9iNiGdH7lZmhnPm8fR2QAApNxwN78CJ8rJrmu+YcHeiknYHu oX0aAzydRd5Ki6c+Hvvzmw== X-Received: by 10.200.1.204 with SMTP id b12mr20262384qtg.2.1502463072618; Fri, 11 Aug 2017 07:51:12 -0700 (PDT) From: Adhemerval Zanella To: libc-alpha@sourceware.org Subject: [PATCH 16/18] posix: More check for overflow allocation in glob Date: Fri, 11 Aug 2017 11:50:42 -0300 Message-Id: <1502463044-4042-17-git-send-email-adhemerval.zanella@linaro.org> In-Reply-To: <1502463044-4042-1-git-send-email-adhemerval.zanella@linaro.org> References: <1502463044-4042-1-git-send-email-adhemerval.zanella@linaro.org> This patch adds and replace the allocation overflow based using malloc internal functions check_add_wrapv_size_t and __libc_reallocarray. Checked on x86_64-linux-gnu. * posix/glob.c (glob_malloc_incr): New function. (glob_malloc_incr2): Likewise. (glob_realloc_incr): Likewise. (glob): Use glob_{realloc,malloc}_incr{2}. --- posix/glob.c | 92 +++++++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 63 insertions(+), 29 deletions(-) diff --git a/posix/glob.c b/posix/glob.c index c85342a..647334d 100644 --- a/posix/glob.c +++ b/posix/glob.c @@ -303,6 +303,39 @@ get_home_directory (const char *user_name, struct char_array *home_dir) return retval; } +/* Allocate '(size + incr) * typesize' bytes while for overflow on the + arithmetic operations. */ +static void * +glob_malloc_incr (size_t size, size_t incr, size_t typesize) +{ + size_t newsize; + if (check_add_overflow_size_t (size, incr, &newsize)) + return NULL; + return __libc_reallocarray (NULL, newsize, typesize); +} + +/* Allocate '(size + incr1 + incr2) * typesize' bytes while for overflow on + the arithmetic operations. */ +static void * +glob_malloc_incr2 (size_t size, size_t incr1, size_t incr2, size_t typesize) +{ + size_t newsize; + if (check_add_overflow_size_t (size, incr1, &newsize) + || check_add_overflow_size_t (newsize, incr2, &newsize)) + return NULL; + return __libc_reallocarray (NULL, newsize, typesize); +} + +/* Reallocate '(size + incr1) * typesize' bytes while for overflow on the + arithmetic operations. */ +static void * +glob_realloc_incr (void *old, size_t size, size_t incr, size_t typesize) +{ + size_t newsize; + if (check_add_overflow_size_t (size, incr, &newsize)) + return NULL; + return __libc_reallocarray (old, newsize, typesize); +} /* Do glob searching for PATTERN, placing results in PGLOB. The bits defined above may be set in FLAGS. @@ -357,11 +390,8 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int), { size_t i; - if (pglob->gl_offs >= ~((size_t) 0) / sizeof (char *)) - goto err_nospace; - - pglob->gl_pathv = (char **) malloc ((pglob->gl_offs + 1) - * sizeof (char *)); + pglob->gl_pathv = glob_malloc_incr (pglob->gl_offs, 1, + sizeof (char *)); if (pglob->gl_pathv == NULL) goto err_nospace; @@ -817,10 +847,11 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int), : (__lstat64 (char_array_str (&dirname), &st64) == 0 && S_ISDIR (st64.st_mode))))) { - size_t newcount = pglob->gl_pathc + pglob->gl_offs; char **new_gl_pathv; + size_t newcount; - if (newcount > SIZE_MAX / sizeof (char *) - 2) + if (check_add_overflow_size_t (pglob->gl_pathc, pglob->gl_offs, + &newcount)) { nospace: free (pglob->gl_pathv); @@ -829,8 +860,8 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int), goto err_nospace; } - new_gl_pathv = realloc (pglob->gl_pathv, - (newcount + 2) * sizeof (char *)); + new_gl_pathv = glob_realloc_incr (pglob->gl_pathv, newcount, 2, + sizeof (char *)); if (new_gl_pathv == NULL) goto nospace; pglob->gl_pathv = new_gl_pathv; @@ -838,9 +869,12 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int), if (flags & GLOB_MARK) { char *p; - pglob->gl_pathv[newcount] = malloc (dirlen + 2); + + pglob->gl_pathv[newcount] = glob_malloc_incr (dirlen, 2, + sizeof (char)); if (pglob->gl_pathv[newcount] == NULL) goto nospace; + p = mempcpy (pglob->gl_pathv[newcount], char_array_str (&dirname), dirlen); p[0] = '/'; @@ -978,18 +1012,19 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int), /* No matches. */ if (flags & GLOB_NOCHECK) { - size_t newcount = pglob->gl_pathc + pglob->gl_offs; + size_t newcount; char **new_gl_pathv; - if (newcount > SIZE_MAX / sizeof (char *) - 2) + if (check_add_overflow_size_t (pglob->gl_pathc, pglob->gl_offs, + &newcount)) { nospace2: globfree (&dirs); goto err_nospace; } - new_gl_pathv = realloc (pglob->gl_pathv, - (newcount + 2) * sizeof (char *)); + new_gl_pathv = glob_realloc_incr (pglob->gl_pathv, newcount, 2, + sizeof (char *)); if (new_gl_pathv == NULL) goto nospace2; pglob->gl_pathv = new_gl_pathv; @@ -1091,15 +1126,16 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int), : (__lstat64 (pglob->gl_pathv[i], &st64) == 0 && (S_ISDIR (st64.st_mode) || S_ISLNK (st64.st_mode))))) { - size_t len = strlen (pglob->gl_pathv[i]) + 2; - char *new = realloc (pglob->gl_pathv[i], len); + size_t len = strlen (pglob->gl_pathv[i]); + char *new = glob_realloc_incr (pglob->gl_pathv[i], len, 2, + sizeof (char)); if (new == NULL) { globfree (pglob); pglob->gl_pathc = 0; goto err_nospace; } - strcpy (&new[len - 2], "/"); + strcpy (&new[len], "/"); pglob->gl_pathv[i] = new; } } @@ -1184,7 +1220,7 @@ prefix_array (const char *dirname, char **array, size_t n) for (i = 0; i < n; ++i) { size_t eltlen = strlen (array[i]) + 1; - char *new = malloc (dirlen + 1 + eltlen); + char *new = glob_malloc_incr2 (dirlen, 1, eltlen, sizeof (char)); if (new == NULL) { while (i > 0) @@ -1192,11 +1228,10 @@ prefix_array (const char *dirname, char **array, size_t n) return 1; } - { - char *endp = mempcpy (new, dirname, dirlen); - *endp++ = DIRSEP_CHAR; - mempcpy (endp, array[i], eltlen); - } + char *endp = mempcpy (new, dirname, dirlen); + *endp++ = DIRSEP_CHAR; + mempcpy (endp, array[i], eltlen); + free (array[i]); array[i] = new; } @@ -1349,16 +1384,15 @@ glob_in_dir (const char *pattern, const char *directory, int flags, if (nfound != 0) { char **new_gl_pathv; + size_t newlen; result = 0; - if (SIZE_MAX / sizeof (char *) - pglob->gl_pathc - < pglob->gl_offs + nfound + 1) + if (check_add_overflow_size_t (pglob->gl_pathc, pglob->gl_offs, &newlen) + || check_add_overflow_size_t (newlen, nfound, &newlen) + || check_add_overflow_size_t (newlen, 1, &newlen)) goto memory_error; - new_gl_pathv - = realloc (pglob->gl_pathv, - (pglob->gl_pathc + pglob->gl_offs + nfound + 1) - * sizeof (char *)); + new_gl_pathv = realloc (pglob->gl_pathv, newlen * sizeof (char *)); if (new_gl_pathv == NULL) {