[PATCH] ash: improve / fix glob expansion

Denys Vlasenko vda.linux at googlemail.com
Tue Jan 31 18:42:48 UTC 2017


On Sun, Jan 29, 2017 at 2:14 PM, Felix Fietkau <nbd at nbd.name> wrote:
> When using musl libc glob() a very long string can cause glob() to fail,
> which leads to an out of memory error being raised by ash.

But it works with glibc glob(), right?
So other programs will also be affected.

Let's fix it in musl (at least there; your patch does make sense
to use anyways since it prevents

    echo "*************"

from being needlessly passed to glob(), right?

I believe this behavior or erorring out on long patterns
is caused by this strnlen() check early in glob() in musl:

int glob(const char *restrict pat, int flags, int (*errfunc)(const
char *path, int err), glob_t *restrict g)
{
        const char *p=pat, *d;
        struct match head = { .next = NULL }, *tail = &head;
        size_t cnt, i;
        size_t offs = (flags & GLOB_DOOFFS) ? g->gl_offs : 0;
        int error = 0;

        if (*p == '/') {
                for (; *p == '/'; p++);
                d = "/";
        } else {
                d = "";
        }

        if (!errfunc) errfunc = ignore_err;

        if (!(flags & GLOB_APPEND)) {
                g->gl_offs = offs;
                g->gl_pathc = 0;
                g->gl_pathv = NULL;
        }

        if (strnlen(p, PATH_MAX+1) > PATH_MAX) return GLOB_NOSPACE;


commit 0dc99ac413d8bc054a2e95578475c7122455eee8
Author: Rich Felker <dalias at aerifal.cx>
Date:   Sun Jun 5 19:29:52 2011 -0400

    safety fix for glob's vla usage: disallow patterns longer than PATH_MAX

    this actually inadvertently disallows some valid patterns with
    redundant / or * characters, but it's better than allowing unbounded
    vla allocation.

    eventually i'll write code to move the pattern to the stack and
    eliminate redundancy to ensure that it fits in PATH_MAX at the
    beginning of glob. this would also allow it to be modified in place
    for passing to fnmatch rather than copied at each level of recursion.

diff --git a/src/regex/glob.c b/src/regex/glob.c
index 9a70f0b..67f84bc 100644
--- a/src/regex/glob.c
+++ b/src/regex/glob.c
@@ -171,6 +171,8 @@ int glob(const char *pat, int flags, int
(*errfunc)(const char *path, int err),
                d = "";
        }

+       if (strlen(p) > PATH_MAX) return GLOB_NOSPACE;


This sounds like musl having an implementation difficulty.


More information about the busybox mailing list