fix regression in glob with literal . or .. path component
authorRich Felker <dalias@aerifal.cx>
Sat, 21 Oct 2017 16:17:49 +0000 (12:17 -0400)
committerRich Felker <dalias@aerifal.cx>
Sat, 21 Oct 2017 16:32:16 +0000 (12:32 -0400)
commit 8c4be3e2209d2a1d3874b8bc2b474668fcbbbac6 was written to
preclude the GLOB_PERIOD extension from matching these directory
entries, but also precluded literal matches.

adjust the check that excludes . and .. to check whether the
GLOB_PERIOD flag is in effect, so that it cannot alter behavior in
cases governed by the standard, and also don't exclude . or .. in any
case where normal glob behavior (fnmatch's FNM_PERIOD flag) would have
included one or both of them (patterns such as ".*").

it's still not clear whether this is the preferred behavior for
GLOB_PERIOD, but at least it's clear that it can no longer break
applications which are not relying on quirks of a nonstandard feature.

src/regex/glob.c

index 6f8425c..8567198 100644 (file)
@@ -100,9 +100,11 @@ static int match_in_dir(const char *d, const char *p, int flags, int (*errfunc)(
                        continue;
                if (p2 && de->d_type && !S_ISDIR(de->d_type<<12) && !S_ISLNK(de->d_type<<12))
                        continue;
-               if (p2 && de->d_name[0]=='.' && !de->d_name[1])
-                       continue;
-               if (p2 && de->d_name[0]=='.' && de->d_name[1]=='.' && !de->d_name[2])
+               /* With GLOB_PERIOD, don't allow matching . or .. unless
+                * fnmatch would match them with FNM_PERIOD rules in effect. */
+               if (p2 && (flags & GLOB_PERIOD) && de->d_name[0]=='.'
+                   && (!de->d_name[1] || de->d_name[1]=='.' && !de->d_name[2])
+                   && fnmatch(p, de->d_name, fnm_flags | FNM_PERIOD))
                        continue;
                if (*d) {
                        memcpy(name, d, l);