diff options
| author | martin <martin@NetBSD.org> | 2019-11-24 08:24:06 +0000 |
|---|---|---|
| committer | martin <martin@NetBSD.org> | 2019-11-24 08:24:06 +0000 |
| commit | 2cae8b20adc0acb8159e7940d9f71265a4223e3e (patch) | |
| tree | 719a3db356d914505fbaf5e83acee9d02de20a66 /bin | |
| parent | acad727ebbed93f2ee6b87ae0748f6059c6f219a (diff) | |
Pull up following revision(s) (requested by kre in ticket #467):
bin/sh/expand.c: revision 1.133
Open code the validity test & copy of the character class name in
a bracket expression in a pattern (ie: [[:THISNAME:]]). Previously
the code used strspn() to look for invalid chars in the name, and
then memcpy(), now we do the test and copy a character at a time.
This might, or might not, be faster, but it now correctly handles
\ quoted characters in the name (' and " quoting were already
dealt with, \ was too in an earlier version, but when the \ handling
changes were made, this piece of code broke).
Not exactly a vital bug fix (who writes [[:\alpha:]] or similar?)
but it should work correctly regardless of how obscure the usage is.
Problem noted by Harald van Dijk
XXX pullup -9
Diffstat (limited to 'bin')
| -rw-r--r-- | bin/sh/expand.c | 40 |
1 files changed, 30 insertions, 10 deletions
diff --git a/bin/sh/expand.c b/bin/sh/expand.c index c9f91c6a655..ae0d949145a 100644 --- a/bin/sh/expand.c +++ b/bin/sh/expand.c @@ -1,4 +1,4 @@ -/* $NetBSD: expand.c,v 1.132 2019/04/10 08:13:11 kre Exp $ */ +/* $NetBSD: expand.c,v 1.132.2.1 2019/11/24 08:24:06 martin Exp $ */ /*- * Copyright (c) 1991, 1993 @@ -37,7 +37,7 @@ #if 0 static char sccsid[] = "@(#)expand.c 8.5 (Berkeley) 5/15/95"; #else -__RCSID("$NetBSD: expand.c,v 1.132 2019/04/10 08:13:11 kre Exp $"); +__RCSID("$NetBSD: expand.c,v 1.132.2.1 2019/11/24 08:24:06 martin Exp $"); #endif #endif /* not lint */ @@ -1792,24 +1792,44 @@ match_charclass(const char *p, wchar_t chr, const char **end) char name[20]; char *nameend; wctype_t cclass; + char *q; *end = NULL; p++; + q = &name[0]; nameend = strstr(p, ":]"); if (nameend == NULL || nameend == p) /* not a valid class */ return 0; - if (!is_alpha(*p) || strspn(p, /* '_' is a local extension */ - "0123456789" "_" - "abcdefghijklmnopqrstuvwxyz" - "ABCDEFGHIJKLMNOPQRSTUVWXYZ") != (size_t)(nameend - p)) + if (*p == CTLESC) { + if (*++p == CTLESC) + return 0; + if (p == nameend) + return 0; + } + if (!is_alpha(*p)) return 0; + while (p < nameend) { + if (*p == CTLESC) { + p++; + if (p == nameend) + return 0; + } + if (!is_in_name(*p)) /* '_' is a local extension */ + return 0; + if (q < &name[sizeof name]) + *q++ = *p++; + else + p++; + } *end = nameend + 2; /* committed to it being a char class */ - if ((size_t)(nameend - p) >= sizeof(name)) /* but too long */ - return 0; /* so no match */ - memcpy(name, p, nameend - p); - name[nameend - p] = '\0'; + + if (q < &name[sizeof name]) /* a usable name found */ + *q++ = '\0'; + else /* too long, valid, but no match */ + return 0; + cclass = wctype(name); /* An unknown class matches nothing but is valid nevertheless. */ if (cclass == 0) |
