summaryrefslogtreecommitdiff
path: root/bin
diff options
context:
space:
mode:
authormartin <martin@NetBSD.org>2019-11-24 08:24:06 +0000
committermartin <martin@NetBSD.org>2019-11-24 08:24:06 +0000
commit2cae8b20adc0acb8159e7940d9f71265a4223e3e (patch)
tree719a3db356d914505fbaf5e83acee9d02de20a66 /bin
parentacad727ebbed93f2ee6b87ae0748f6059c6f219a (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.c40
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)