summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRich Felker <dalias@aerifal.cx>2012-04-26 12:24:44 -0400
committerRich Felker <dalias@aerifal.cx>2012-04-26 12:24:44 -0400
commit2b87a5db82833c6d148b70d29a33cd51fff491e3 (patch)
tree52983138a2f743eb652386367b5f8313f7317b50 /src
parent0bd7ac05d1c6691a7ff33c0145adcafb4f4803df (diff)
downloadmusl-2b87a5db82833c6d148b70d29a33cd51fff491e3.tar.gz
update fnmatch to POSIX 2008 semantics
an invalid bracket expression must be treated as if the opening bracket were just a literal character. this is to fix a bug whereby POSIX left the behavior of the "[" shell command undefined due to it being an invalid bracket expression.
Diffstat (limited to 'src')
-rw-r--r--src/regex/fnmatch.c15
1 files changed, 11 insertions, 4 deletions
diff --git a/src/regex/fnmatch.c b/src/regex/fnmatch.c
index c0856f99..81f0c7bd 100644
--- a/src/regex/fnmatch.c
+++ b/src/regex/fnmatch.c
@@ -53,6 +53,7 @@ int fnmatch(const char *p, const char *s, int flags)
int first;
int no_slash = (flags & FNM_PATHNAME) ? '/' : 0;
int no_period = (flags & FNM_PERIOD) && !(flags & __FNM_CONT) ? '.' : 0x100;
+ const char *p1;
flags |= __FNM_CONT;
@@ -84,6 +85,7 @@ int fnmatch(const char *p, const char *s, int flags)
break;
return FNM_NOMATCH;
case '[':
+ p1 = p-1;
not = (*p == '!' || *p == '^');
if (not) p++;
k = next(&s);
@@ -92,7 +94,7 @@ int fnmatch(const char *p, const char *s, int flags)
match = 0;
first = 1;
for (;;) {
- if (!*p) return FNM_NOMATCH;
+ if (!*p) goto literal_bracket;
if (*p == ']' && !first) break;
first = 0;
if (*p == '[' && *(p+1) == ':') {
@@ -112,15 +114,20 @@ int fnmatch(const char *p, const char *s, int flags)
continue;
}
c = bracket_next(&p);
- if (c == BRACKET_ERROR)
- return FNM_NOMATCH;
+ if (c == BRACKET_ERROR) {
+literal_bracket:
+ match = (k=='[');
+ p = p1;
+ not = 0;
+ break;
+ }
if (c == BRACKET_NOCHAR)
continue;
if (*p == '-' && *(p+1) != ']') {
p++;
d = bracket_next(&p);
if (d == BRACKET_ERROR)
- return FNM_NOMATCH;
+ goto literal_bracket;
if (d == BRACKET_NOCHAR)
continue;
if (k >= c && k <= d)