From patchwork Tue Jan 5 18:58:14 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adhemerval Zanella Netto X-Patchwork-Id: 41643 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 6DC42393BC2D; Tue, 5 Jan 2021 18:58:34 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 6DC42393BC2D DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1609873114; bh=5hBRwF/R7b2diX1WzX/5N67vMXtF1GzyzvuRqHdpVU0=; h=To:Subject:Date:In-Reply-To:References:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=Wi9LTaLuNnzbkQDUFtl1DGJaR7vGYBsnxE42wumWhV4kcc60KXft9bBkS+pbsylyj IGZvcMJNiLkfOs1Y8uqfu8iOf5ta4ZtipHhcwKvfPcTZl0Nk62ai9e4S8G3eOLD50y XpVKzwczof/PfEFXrsUAQS8Sc/T9XkItGJHIIgyI= X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mail-qv1-xf36.google.com (mail-qv1-xf36.google.com [IPv6:2607:f8b0:4864:20::f36]) by sourceware.org (Postfix) with ESMTPS id C6CE93894C09 for ; Tue, 5 Jan 2021 18:58:30 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org C6CE93894C09 Received: by mail-qv1-xf36.google.com with SMTP id et9so124848qvb.10 for ; Tue, 05 Jan 2021 10:58:30 -0800 (PST) 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:mime-version:content-transfer-encoding; bh=5hBRwF/R7b2diX1WzX/5N67vMXtF1GzyzvuRqHdpVU0=; b=QFu7ICddT5NFxVNFXueykcWo7v+Zr1+ntHd0/S1U4WwUqV74hiDXgBjye1GwTqquLk CpRFMxCX8lHWUxMPQah3W9gDp+6l4PlUHJ4OrlGC7exsuDkqDcylpFxDZJsgoqBuS82L btioE5MU8mOQJ0cvSicVVXRdMbzA7t+LJai16UJvKEU7G46ENSlw7u9W79mYKtDAuC+F S7jAqS9c5NhU2Exq+UFEUrpN5siKegt+yPpXV13otJx5EnJN2AssUj45fDCZ1mlC59HT nrMdxLeFW7QfpVfCWGLrRJDy8afh2daPMtZTiwoBT0GC+Q4T6DDTad3yLRNPhm4KdHiu v6zw== X-Gm-Message-State: AOAM5338+ODA0DRkENhINEOxyVaE9PtEypM5SQXsr7pJj0DIWiFu4C6Z VR//yYdu2P8mCKWEpPFH6lHo+Rq/ynv8Ow== X-Google-Smtp-Source: ABdhPJzTg0Byrdf2hPXD1bGFM69k3zTInomgUbL3gS9gUWAMAJt/KLsCpflx9mzfkwsh+d2o6xJsPg== X-Received: by 2002:ad4:55f2:: with SMTP id bu18mr930006qvb.27.1609873109804; Tue, 05 Jan 2021 10:58:29 -0800 (PST) Received: from localhost.localdomain ([177.194.48.209]) by smtp.googlemail.com with ESMTPSA id t68sm67792qkd.35.2021.01.05.10.58.28 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 05 Jan 2021 10:58:29 -0800 (PST) To: libc-alpha@sourceware.org, Paul Eggert , bug-gnulib@gnu.org Subject: [PATCH 2/8] posix: Use char_array for internal glob dirname Date: Tue, 5 Jan 2021 15:58:14 -0300 Message-Id: <20210105185820.3796657-3-adhemerval.zanella@linaro.org> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210105185820.3796657-1-adhemerval.zanella@linaro.org> References: <20210105185820.3796657-1-adhemerval.zanella@linaro.org> MIME-Version: 1.0 X-Spam-Status: No, score=-13.7 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Adhemerval Zanella via Libc-alpha From: Adhemerval Zanella Netto Reply-To: Adhemerval Zanella Errors-To: libc-alpha-bounces@sourceware.org Sender: "Libc-alpha" This is the first patch of the set to remove alloca usage on glob implementation. Internal path to search for file might expand to a non static directory derived from pattern for some difference cases (GLOB_NOESCAPE, GNU GLOB_TILDE) and to allow a non-static dirname path glob uses a lot of boilerplate code to manage the buffer (which is either allocated using alloca or malloc depending both to size requested and the total alloca_used). The patch changes to use the char_array struct with the default size (256 bytes). It simplifies all the allocation code by using char_array one and every internal buffer access is done using char_array provided functions. No functional changes are expected. Checked on x86_64-linux-gnu. --- posix/glob.c | 275 +++++++++++++++++++++------------------------------ 1 file changed, 111 insertions(+), 164 deletions(-) diff --git a/posix/glob.c b/posix/glob.c index 32c88e5d15..8c6e1914c5 100644 --- a/posix/glob.c +++ b/posix/glob.c @@ -85,6 +85,7 @@ #include #include #include +#include static const char *next_brace_sub (const char *begin, int flags) __THROWNL; @@ -298,16 +299,15 @@ __glob (const char *pattern, int flags, int (*errfunc) (const char *, int), glob_t *pglob) { const char *filename; - char *dirname = NULL; size_t dirlen; int status; size_t oldcount; int meta; - int dirname_modified; - int malloc_dirname = 0; glob_t dirs; int retval = 0; size_t alloca_used = 0; + struct char_array dirname; + bool dirname_modified; if (pattern == NULL || pglob == NULL || (flags & ~__GLOB_FLAGS) != 0) { @@ -315,6 +315,10 @@ __glob (const char *pattern, int flags, int (*errfunc) (const char *, int), return -1; } + /* Default char array is stack allocated, so there is no need to check + if setting the initial '\0' succeeds. */ + char_array_init_empty (&dirname); + /* POSIX requires all slashes to be matched. This means that with a trailing slash we must match only directories. */ if (pattern[0] && pattern[strlen (pattern) - 1] == '/') @@ -335,12 +339,12 @@ __glob (const char *pattern, int flags, int (*errfunc) (const char *, int), size_t i; if (pglob->gl_offs >= ~((size_t) 0) / sizeof (char *)) - return GLOB_NOSPACE; + goto err_nospace; pglob->gl_pathv = (char **) malloc ((pglob->gl_offs + 1) * sizeof (char *)); if (pglob->gl_pathv == NULL) - return GLOB_NOSPACE; + goto err_nospace; for (i = 0; i <= pglob->gl_offs; ++i) pglob->gl_pathv[i] = NULL; @@ -392,7 +396,7 @@ __glob (const char *pattern, int flags, int (*errfunc) (const char *, int), { onealt = malloc (pattern_len); if (onealt == NULL) - return GLOB_NOSPACE; + goto err_nospace; } /* We know the prefix for all sub-patterns. */ @@ -454,7 +458,8 @@ __glob (const char *pattern, int flags, int (*errfunc) (const char *, int), globfree (pglob); pglob->gl_pathc = 0; } - return result; + retval = result; + goto out; } if (*next == '}') @@ -471,9 +476,10 @@ __glob (const char *pattern, int flags, int (*errfunc) (const char *, int), if (pglob->gl_pathc != firstc) /* We found some entries. */ - return 0; + retval = 0; else if (!(flags & (GLOB_NOCHECK|GLOB_NOMAGIC))) - return GLOB_NOMATCH; + retval = GLOB_NOMATCH; + goto out; } } @@ -492,14 +498,15 @@ __glob (const char *pattern, int flags, int (*errfunc) (const char *, int), filename = strchr (pattern, ':'); #endif /* __MSDOS__ || WINDOWS32 */ - dirname_modified = 0; + dirname_modified = false; if (filename == NULL) { /* This can mean two things: a simple name or "~name". The latter case is nothing but a notation for a directory. */ if ((flags & (GLOB_TILDE|GLOB_TILDE_CHECK)) && pattern[0] == '~') { - dirname = (char *) pattern; + if (!char_array_set_str (&dirname, pattern)) + goto err_nospace; dirlen = strlen (pattern); /* Set FILENAME to NULL as a special flag. This is ugly but @@ -516,7 +523,8 @@ __glob (const char *pattern, int flags, int (*errfunc) (const char *, int), } filename = pattern; - dirname = (char *) "."; + if (!char_array_set_str (&dirname, ".")) + goto err_nospace; dirlen = 0; } } @@ -525,13 +533,13 @@ __glob (const char *pattern, int flags, int (*errfunc) (const char *, int), && (flags & GLOB_NOESCAPE) == 0)) { /* "/pattern" or "\\/pattern". */ - dirname = (char *) "/"; + if (!char_array_set_str (&dirname, "/")) + goto err_nospace; dirlen = 1; ++filename; } else { - char *newp; dirlen = filename - pattern; #if defined __MSDOS__ || defined WINDOWS32 if (*filename == ':' @@ -545,31 +553,26 @@ __glob (const char *pattern, int flags, int (*errfunc) (const char *, int), /* For now, disallow wildcards in the drive spec, to prevent infinite recursion in glob. */ if (__glob_pattern_p (drive_spec, !(flags & GLOB_NOESCAPE))) - return GLOB_NOMATCH; + { + retval = GLOB_NOMATCH; + goto out; + } /* If this is "d:pattern", we need to copy ':' to DIRNAME as well. If it's "d:/pattern", don't remove the slash from "d:/", since "d:" and "d:/" are not the same.*/ } #endif - if (glob_use_alloca (alloca_used, dirlen + 1)) - newp = alloca_account (dirlen + 1, alloca_used); - else - { - newp = malloc (dirlen + 1); - if (newp == NULL) - return GLOB_NOSPACE; - malloc_dirname = 1; - } - *((char *) mempcpy (newp, pattern, dirlen)) = '\0'; - dirname = newp; + if (!char_array_set_str_size (&dirname, pattern, dirlen)) + goto err_nospace; ++filename; #if defined __MSDOS__ || defined WINDOWS32 bool drive_root = (dirlen > 1 - && (dirname[dirlen - 1] == ':' - || (dirlen > 2 && dirname[dirlen - 2] == ':' - && dirname[dirlen - 1] == '/'))); + && (char_array_pos (&dirname, dirlen - 1) != ':' + || (dirlen > 2 + && char_array_pos (&dirname, dirlen - 2) != ':' + && char_array_pos (&dirname, dirlen - 1) != '/'))); #else bool drive_root = false; #endif @@ -578,20 +581,24 @@ __glob (const char *pattern, int flags, int (*errfunc) (const char *, int), /* "pattern/". Expand "pattern", appending slashes. */ { int orig_flags = flags; - if (!(flags & GLOB_NOESCAPE) && dirname[dirlen - 1] == '\\') + if (!(flags & GLOB_NOESCAPE) + && char_array_pos (&dirname, dirlen - 1) == '\\') { /* "pattern\\/". Remove the final backslash if it hasn't been quoted. */ - char *p = (char *) &dirname[dirlen - 1]; - - while (p > dirname && p[-1] == '\\') --p; - if ((&dirname[dirlen] - p) & 1) + size_t p = dirlen - 1; + while (p > 0 && char_array_pos (&dirname, p - 1) == '\\') --p; + if ((dirlen - p) & 1) { - *(char *) &dirname[--dirlen] = '\0'; + /* Since we are shrinking the array, there is no need to + check the function return. */ + dirlen -= 1; + char_array_crop (&dirname, dirlen); flags &= ~(GLOB_NOCHECK | GLOB_NOMAGIC); } } - int val = __glob (dirname, flags | GLOB_MARK, errfunc, pglob); + int val = __glob (char_array_str (&dirname), flags | GLOB_MARK, + errfunc, pglob); if (val == 0) pglob->gl_flags = ((pglob->gl_flags & ~GLOB_MARK) | (flags & GLOB_MARK)); @@ -608,11 +615,14 @@ __glob (const char *pattern, int flags, int (*errfunc) (const char *, int), } } - if ((flags & (GLOB_TILDE|GLOB_TILDE_CHECK)) && dirname[0] == '~') + if ((flags & (GLOB_TILDE|GLOB_TILDE_CHECK)) + && char_array_pos (&dirname, 0) == '~') { - if (dirname[1] == '\0' || dirname[1] == '/' - || (!(flags & GLOB_NOESCAPE) && dirname[1] == '\\' - && (dirname[2] == '\0' || dirname[2] == '/'))) + if (char_array_pos (&dirname, 1) == '\0' + || char_array_pos (&dirname, 1) == '/' + || (!(flags & GLOB_NOESCAPE) && char_array_pos (&dirname, 1) == '\\' + && (char_array_pos (&dirname, 2) == '\0' + || char_array_pos (&dirname, 2) == '/'))) { /* Look up home directory. */ char *home_dir = getenv ("HOME"); @@ -663,10 +673,7 @@ __glob (const char *pattern, int flags, int (*errfunc) (const char *, int), if (err != ERANGE) break; if (!scratch_buffer_grow (&s)) - { - retval = GLOB_NOSPACE; - goto out; - } + goto err_nospace; } if (err == 0) { @@ -675,10 +682,7 @@ __glob (const char *pattern, int flags, int (*errfunc) (const char *, int), } scratch_buffer_free (&s); if (err == 0 && home_dir == NULL) - { - retval = GLOB_NOSPACE; - goto out; - } + goto err_nospace; #endif /* WINDOWS32 */ } if (home_dir == NULL || home_dir[0] == '\0') @@ -697,53 +701,26 @@ __glob (const char *pattern, int flags, int (*errfunc) (const char *, int), } } /* Now construct the full directory. */ - if (dirname[1] == '\0') + if (char_array_pos (&dirname, 1) == '\0') { - if (__glibc_unlikely (malloc_dirname)) - free (dirname); - - dirname = home_dir; - dirlen = strlen (dirname); - malloc_dirname = malloc_home_dir; + if (!char_array_set_str (&dirname, home_dir)) + goto err_nospace; + dirlen = char_array_size (&dirname) - 1; } else { - char *newp; - size_t home_len = strlen (home_dir); - int use_alloca = glob_use_alloca (alloca_used, home_len + dirlen); - if (use_alloca) - newp = alloca_account (home_len + dirlen, alloca_used); - else - { - newp = malloc (home_len + dirlen); - if (newp == NULL) - { - if (__glibc_unlikely (malloc_home_dir)) - free (home_dir); - retval = GLOB_NOSPACE; - goto out; - } - } - - mempcpy (mempcpy (newp, home_dir, home_len), - &dirname[1], dirlen); - - if (__glibc_unlikely (malloc_dirname)) - free (dirname); - - dirname = newp; - dirlen += home_len - 1; - malloc_dirname = !use_alloca; - - if (__glibc_unlikely (malloc_home_dir)) - free (home_dir); + /* Replaces '~' by the obtained HOME dir. */ + char_array_erase (&dirname, 0); + if (!char_array_prepend_str (&dirname, home_dir)) + goto err_nospace; } - dirname_modified = 1; + dirname_modified = true; } else { #ifndef WINDOWS32 - char *end_name = strchr (dirname, '/'); + char *dirnamestr = char_array_at (&dirname, 0); + char *end_name = strchr (dirnamestr, '/'); char *user_name; int malloc_user_name = 0; char *unescape = NULL; @@ -752,23 +729,23 @@ __glob (const char *pattern, int flags, int (*errfunc) (const char *, int), { if (end_name == NULL) { - unescape = strchr (dirname, '\\'); + unescape = strchr (dirnamestr, '\\'); if (unescape) end_name = strchr (unescape, '\0'); } else - unescape = memchr (dirname, '\\', end_name - dirname); + unescape = memchr (dirnamestr, '\\', end_name - dirnamestr); } if (end_name == NULL) - user_name = dirname + 1; + user_name = dirnamestr + 1; else { char *newp; - if (glob_use_alloca (alloca_used, end_name - dirname)) - newp = alloca_account (end_name - dirname, alloca_used); + if (glob_use_alloca (alloca_used, end_name - dirnamestr)) + newp = alloca_account (end_name - dirnamestr, alloca_used); else { - newp = malloc (end_name - dirname); + newp = malloc (end_name - dirnamestr); if (newp == NULL) { retval = GLOB_NOSPACE; @@ -778,8 +755,8 @@ __glob (const char *pattern, int flags, int (*errfunc) (const char *, int), } if (unescape != NULL) { - char *p = mempcpy (newp, dirname + 1, - unescape - dirname - 1); + char *p = mempcpy (newp, dirnamestr + 1, + unescape - dirnamestr - 1); char *q = unescape; while (q != end_name) { @@ -801,8 +778,9 @@ __glob (const char *pattern, int flags, int (*errfunc) (const char *, int), *p = '\0'; } else - *((char *) mempcpy (newp, dirname + 1, end_name - dirname - 1)) - = '\0'; + *((char *) mempcpy (newp, dirnamestr + 1, + end_name - dirnamestr - 1)) + = '\0'; user_name = newp; } @@ -835,39 +813,14 @@ __glob (const char *pattern, int flags, int (*errfunc) (const char *, int), /* If we found a home directory use this. */ if (p != NULL) { - size_t home_len = strlen (p->pw_dir); - size_t rest_len = end_name == NULL ? 0 : strlen (end_name); - /* dirname contains end_name; we can't free it now. */ - char *prev_dirname = - (__glibc_unlikely (malloc_dirname) ? dirname : NULL); - char *d; - - malloc_dirname = 0; - - if (glob_use_alloca (alloca_used, home_len + rest_len + 1)) - dirname = alloca_account (home_len + rest_len + 1, - alloca_used); - else + if (!char_array_set_str (&dirname, p->pw_dir)) { - dirname = malloc (home_len + rest_len + 1); - if (dirname == NULL) - { - free (prev_dirname); - scratch_buffer_free (&pwtmpbuf); - retval = GLOB_NOSPACE; - goto out; - } - malloc_dirname = 1; + scratch_buffer_free (&pwtmpbuf); + goto err_nospace; } - d = mempcpy (dirname, p->pw_dir, home_len); - if (end_name != NULL) - d = mempcpy (d, end_name, rest_len); - *d = '\0'; - - free (prev_dirname); - dirlen = home_len + rest_len; - dirname_modified = 1; + dirlen = strlen (p->pw_dir); + dirname_modified = true; } else { @@ -908,37 +861,33 @@ __glob (const char *pattern, int flags, int (*errfunc) (const char *, int), goto nospace; pglob->gl_pathv = new_gl_pathv; - if (flags & GLOB_MARK && is_dir (dirname, flags, pglob)) + if (flags & GLOB_MARK + && is_dir (char_array_str (&dirname), flags, pglob)) { char *p; pglob->gl_pathv[newcount] = malloc (dirlen + 2); if (pglob->gl_pathv[newcount] == NULL) goto nospace; - p = mempcpy (pglob->gl_pathv[newcount], dirname, dirlen); + p = mempcpy (pglob->gl_pathv[newcount], + char_array_str (&dirname), dirlen); p[0] = '/'; p[1] = '\0'; - if (__glibc_unlikely (malloc_dirname)) - free (dirname); } else { - if (__glibc_unlikely (malloc_dirname)) - pglob->gl_pathv[newcount] = dirname; - else - { - pglob->gl_pathv[newcount] = strdup (dirname); - if (pglob->gl_pathv[newcount] == NULL) - goto nospace; - } + pglob->gl_pathv[newcount] = strdup (char_array_str (&dirname)); + if (pglob->gl_pathv[newcount] == NULL) + goto nospace; } pglob->gl_pathv[++newcount] = NULL; ++pglob->gl_pathc; pglob->gl_flags = flags; - return 0; + goto out; } - meta = __glob_pattern_type (dirname, !(flags & GLOB_NOESCAPE)); + meta = __glob_pattern_type (char_array_str (&dirname), + !(flags & GLOB_NOESCAPE)); /* meta is 1 if correct glob pattern containing metacharacters. If meta has bit (1 << 2) set, it means there was an unterminated [ which we handle the same, using fnmatch. Broken unterminated @@ -951,15 +900,15 @@ __glob (const char *pattern, int flags, int (*errfunc) (const char *, int), the pattern in each directory found. */ size_t i; - if (!(flags & GLOB_NOESCAPE) && dirlen > 0 && dirname[dirlen - 1] == '\\') + if (!(flags & GLOB_NOESCAPE) && dirlen > 0 + && char_array_pos (&dirname, dirlen - 1) == '\\') { /* "foo\\/bar". Remove the final backslash from dirname if it has not been quoted. */ - char *p = (char *) &dirname[dirlen - 1]; - - while (p > dirname && p[-1] == '\\') --p; - if ((&dirname[dirlen] - p) & 1) - *(char *) &dirname[--dirlen] = '\0'; + size_t p = dirlen - 1; + while (p > 0 && char_array_pos (&dirname, p - 1) == '\\') --p; + if ((dirlen - p) & 1) + char_array_crop (&dirname, --dirlen); } if (__glibc_unlikely ((flags & GLOB_ALTDIRFUNC) != 0)) @@ -973,7 +922,7 @@ __glob (const char *pattern, int flags, int (*errfunc) (const char *, int), dirs.gl_lstat = pglob->gl_lstat; } - status = __glob (dirname, + status = __glob (char_array_str (&dirname), ((flags & (GLOB_ERR | GLOB_NOESCAPE | GLOB_ALTDIRFUNC)) | GLOB_NOSORT | GLOB_ONLYDIR), errfunc, &dirs); @@ -1020,8 +969,7 @@ __glob (const char *pattern, int flags, int (*errfunc) (const char *, int), globfree (&dirs); globfree (pglob); pglob->gl_pathc = 0; - retval = GLOB_NOSPACE; - goto out; + goto err_nospace; } } @@ -1043,8 +991,7 @@ __glob (const char *pattern, int flags, int (*errfunc) (const char *, int), { nospace2: globfree (&dirs); - retval = GLOB_NOSPACE; - goto out; + goto err_nospace; } new_gl_pathv = realloc (pglob->gl_pathv, @@ -1059,8 +1006,7 @@ __glob (const char *pattern, int flags, int (*errfunc) (const char *, int), globfree (&dirs); globfree (pglob); pglob->gl_pathc = 0; - retval = GLOB_NOSPACE; - goto out; + goto err_nospace; } ++pglob->gl_pathc; @@ -1086,7 +1032,7 @@ __glob (const char *pattern, int flags, int (*errfunc) (const char *, int), if (meta & GLOBPAT_BACKSLASH) { - char *p = strchr (dirname, '\\'), *q; + char *p = strchr (char_array_str (&dirname), '\\'), *q; /* We need to unescape the dirname string. It is certainly allocated by alloca, as otherwise filename would be NULL or dirname wouldn't contain backslashes. */ @@ -1103,12 +1049,12 @@ __glob (const char *pattern, int flags, int (*errfunc) (const char *, int), ++q; } while (*p++ != '\0'); - dirname_modified = 1; + dirname_modified = true; } if (dirname_modified) flags &= ~(GLOB_NOCHECK | GLOB_NOMAGIC); - status = glob_in_dir (filename, dirname, flags, errfunc, pglob, - alloca_used); + status = glob_in_dir (filename, char_array_str (&dirname), flags, + errfunc, pglob, alloca_used); if (status != 0) { if (status == GLOB_NOMATCH && flags != orig_flags @@ -1126,14 +1072,13 @@ __glob (const char *pattern, int flags, int (*errfunc) (const char *, int), if (dirlen > 0) { /* Stick the directory on the front of each name. */ - if (prefix_array (dirname, + if (prefix_array (char_array_str (&dirname), &pglob->gl_pathv[old_pathc + pglob->gl_offs], pglob->gl_pathc - old_pathc)) { globfree (pglob); pglob->gl_pathc = 0; - retval = GLOB_NOSPACE; - goto out; + goto err_nospace; } } } @@ -1152,8 +1097,7 @@ __glob (const char *pattern, int flags, int (*errfunc) (const char *, int), { globfree (pglob); pglob->gl_pathc = 0; - retval = GLOB_NOSPACE; - goto out; + goto err_nospace; } strcpy (&new[len - 2], "/"); pglob->gl_pathv[i] = new; @@ -1169,10 +1113,13 @@ __glob (const char *pattern, int flags, int (*errfunc) (const char *, int), } out: - if (__glibc_unlikely (malloc_dirname)) - free (dirname); + char_array_free (&dirname); return retval; + + err_nospace: + char_array_free (&dirname); + return GLOB_NOSPACE; } #if defined _LIBC && !defined __glob versioned_symbol (libc, __glob, glob, GLIBC_2_27);