make globfree safe after failed glob from over-length argument
authorRich Felker <dalias@aerifal.cx>
Tue, 3 Jan 2017 00:47:12 +0000 (19:47 -0500)
committerRich Felker <dalias@aerifal.cx>
Tue, 3 Jan 2017 00:47:12 +0000 (19:47 -0500)
commit 0dc99ac413d8bc054a2e95578475c7122455eee8 added input length
checking to avoid unsafe VLA allocation, but put it in the wrong
place, before the glob_t structure was zeroed out. while POSIX isn't
clear on whether it's permitted to call globfree after glob failed
with GLOB_NOSPACE, making it safe is clearly better than letting
uninitialized pointers get passed to free in non-conforming callers.

while we're fixing this, change strlen check to the idiomatic strnlen
version to avoid unbounded input scanning before returning an error.

src/regex/glob.c

index 6affee040c310f435008d227c73bfee7eacab3cb..5b6ff1247f437416e1a95dae05ba26f9e269fb91 100644 (file)
@@ -169,8 +169,6 @@ int glob(const char *restrict pat, int flags, int (*errfunc)(const char *path, i
                d = "";
        }
 
-       if (strlen(p) > PATH_MAX) return GLOB_NOSPACE;
-
        if (!errfunc) errfunc = ignore_err;
 
        if (!(flags & GLOB_APPEND)) {
@@ -179,6 +177,8 @@ int glob(const char *restrict pat, int flags, int (*errfunc)(const char *path, i
                g->gl_pathv = NULL;
        }
 
+       if (strnlen(p, PATH_MAX+1) > PATH_MAX) return GLOB_NOSPACE;
+
        if (*p) error = match_in_dir(d, p, flags, errfunc, &tail);
        if (error == GLOB_NOSPACE) {
                freelist(&head);