From patchwork Thu Jun 8 21:13:31 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adhemerval Zanella Netto X-Patchwork-Id: 20869 Received: (qmail 41890 invoked by alias); 8 Jun 2017 21:14:30 -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 41302 invoked by uid 89); 8 Jun 2017 21:14:24 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-26.9 required=5.0 tests=BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, RCVD_IN_DNSWL_NONE, SPF_PASS autolearn=ham version=3.3.2 spammy= X-HELO: mail-qt0-f177.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=vKm4bLoEFjGS2Wp1IdI4wsvyJA895uL8gXks41B1DHM=; b=DOD34K9r/8MhigwnGOjZqwPpLMSMIU4W8bgsYpIkNKGMB9RshjD3JvR2zwolr13y1G vmYbZEUz4IRM/3U+BX68Xyu4m+Geq81CiyagTdJpXefvcuMlwnDeSPMY1fc8t6V0ueEV jZpvE5lqazyd+GhM8fvIYGxWddi+ypwL+RjyEUOZ91KDWtuLW2Iii+XWfKSEPXmATced KM0lxWXYMhwB154Kuclji/4VeawxDO9qo6W1uh7mKWMtFx7t1XW72hfBJie29F5NydUS OKoMEwvjvkQ5q/duUsv8XdILgg/nHG/AdN+Et+rJJW3dtX5xRKRXFGKFdWpTxhCCpHzY Or5A== X-Gm-Message-State: AKS2vOx9HYPcUZUY1HBCTy9Lo0EUNR1wwRGFsfr9kEiL4GAdA7Fzcrfh Jl+cmEgH7GnqJ+Ptn7O27w== X-Received: by 10.55.182.135 with SMTP id g129mr20153212qkf.111.1496956464010; Thu, 08 Jun 2017 14:14:24 -0700 (PDT) From: Adhemerval Zanella To: libc-alpha@sourceware.org Subject: [PATCH 17/17] posix: More check for overflow allocation in glob Date: Thu, 8 Jun 2017 18:13:31 -0300 Message-Id: <1496956411-25594-18-git-send-email-adhemerval.zanella@linaro.org> In-Reply-To: <1496956411-25594-1-git-send-email-adhemerval.zanella@linaro.org> References: <1496956411-25594-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 2b11e45..0de8233 100644 --- a/posix/glob.c +++ b/posix/glob.c @@ -302,6 +302,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_wrapv_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_wrapv_size_t (size, incr1, &newsize) + || check_add_wrapv_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_wrapv_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. @@ -356,11 +389,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; @@ -816,10 +846,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_wrapv_size_t (pglob->gl_pathc, pglob->gl_offs, + &newcount)) { nospace: free (pglob->gl_pathv); @@ -828,8 +859,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; @@ -837,9 +868,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] = '/'; @@ -976,18 +1010,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_wrapv_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; @@ -1089,15 +1124,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; } } @@ -1182,7 +1218,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) @@ -1190,11 +1226,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; } @@ -1345,16 +1380,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_wrapv_size_t (pglob->gl_pathc, pglob->gl_offs, &newlen) + || check_add_wrapv_size_t (newlen, nfound, &newlen) + || check_add_wrapv_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) {