[PATCH 6/6] posix: Do not recurse once per pattern component in glob [BZ #34453]
Adhemerval Zanella Netto
adhemerval.zanella@linaro.org
Sat Aug 8 18:52:25 GMT 2026
On 08/08/26 02:52, Collin Funk wrote:
> Adhemerval Zanella <adhemerval.zanella@linaro.org> writes:
>
>> +/* Remove one unquoted trailing backslash from P, which is *LENP bytes long,
>> + and update *LENP. */
>> +static void
>> +glob_strip_backslash (char *p, size_t *lenp)
>> +{
>> + size_t len = *lenp;
>> + char *q = &p[len - 1];
>> +
>> + while (q > p && q[-1] == '\\')
>> + --q;
>> + /* Check if the number of '\' is odd. */
>> + if ((&p[len] - q) & 1)
>> + p[--len] = '\0';
>> + *lenp = len;
>> +}
>> +
>> +/* Remove the quoting backslashes from P, which is *LENP bytes long and
>> + contains at least one backslash, and update *LENP. */
>> +static void
>> +glob_unescape (char *p, size_t *lenp)
>> +{
>> + size_t len = *lenp;
>> + char *s = strchr (p, '\\');
>> + char *d = s;
>
> Since we have LEN, can't we use memchr? Not that P will be long enough
> to matter much, of course.
We can, I will change to use.
>
>> + do
>> + {
>> + if (*s == '\\')
>> + {
>> + *d = *++s;
>> + --len;
>> + }
>> + else
>> + *d = *s;
>> + ++d;
>> + }
>> + while (*s++ != '\0');
>> + *lenp = len;
>> +}
>
> I think it would be better for glob_strip_backslash and glob_unescape
> should return LEN instead of modifying a pointer. Any reason why they
> shouldn't?
Not reason in fact, and returning LEN makes more sense. I will change it.
>
> These functions are small, so it isn't a major issue, but I find it
> easier to forget to set a pointer in one path than to forget a return.
>
>> +/* Expand DIRPATTERN, the directory part of a pattern, into PGLOB. FLAGS
>> + holds GLOB_ERR, GLOB_NOESCAPE and GLOB_ALTDIRFUNC as inherited from the
>> + caller, plus GLOB_NOSORT and GLOB_ONLYDIR.
>> +
>> + DIRPATTERN is split at its slashes into components, each recorded in a
>> + heap-allocated array along with what it has to do with the directories
>> + it matches. The components are then matched from left to right,
>> + starting at the longest leading part that has no metacharacter. Stack
>> + usage does not depend on how many components there are, and a component
>> + that matches nothing ends the expansion at once. */
>> +static int
>> +glob_dir_pattern (const char *dirpattern, int flags,
>> + int (*errfunc) (const char *, int), glob_t *pglob)
>> +{
>> + bool quote = !(flags & GLOB_NOESCAPE);
>> + struct glob_dir_step *steps = NULL;
>> + size_t nsteps = 0;
>> + size_t maxsteps;
>> + char *work;
>> + char *p;
>> + const char *base;
>> + const char *base_pattern;
>> + size_t baselen;
>> + /* Whether the level being scanned appends slashes to its result. A
>> + component followed by a slash passes this down instead of matching
>> + anything itself, exactly as GLOB_MARK is passed down by glob. */
>> + bool mark = false;
>> + glob_t cur;
>> + int retval;
>> +
>> + /* The pattern is split in place, so work on a copy. */
>> + work = strdup (dirpattern);
>> + if (work == NULL)
>> + return GLOB_NOSPACE;
>> + p = work;
>> +
>> + /* Every step splits the pattern at a slash, so there is never more than one
>> + step per slash. */
>> + maxsteps = glob_count (dirpattern, '/');
>
> I will probably need to reduce the variable scope here and some other
> places before importing it to gnulib. But I think it is okay for now.
> There is already a large diff in what gnulib and glibc have since
> Bruno's reduction of variable scope last year [1].
I will work on the variable scope reduction to keep gnulib sync easier.
>
> Generally, the patch looks good though. I tested them in gnulib and it
> passes those tests on GNU/Linux.
Thanks for checking on this.
>
> Anyway, I don't think the minor points I brought up require a V2. Feel
> free to add my Reviewed-by after checking them, whether you decide to
> make the changes or not.
>
> Reviewed-by: Collin Funk <collin.funk1@gmail.com>
Ack.
>
> Collin
>
> [1] https://github.com/coreutils/gnulib/commit/6edf6dbacf1e136539da03115adee858ec8a3d33
More information about the Libc-alpha
mailing list