Module Name:    src
Committed By:   kre
Date:           Fri Jun 22 18:19:41 UTC 2018

Modified Files:
        src/bin/sh: expand.c

Log Message:
When processing character classes ([:xxx:] inside []), treat a class name
that is longer than we can handle the same way we treat an unknown
class name (as a valid char class which contains nothing, so never
matches).   Previously a "too long" class name invalidated the
class, so [:very-long-name:] would match any of  '[' ':' 'v'  ...
(note: "very-long-name" is not long enough to trigger this, but you
get the idea!)

However, the name itself has a restricted syntax ([[:***:]] is not a
character class, it is a match for one of a '[' ':' or '*', followed by
a ']') which we did not implement - check the syntax of the name before
treating it as a character class (but we do add '_' to alphanumerics
as legal class name characters).


To generate a diff of this commit:
cvs rdiff -u -r1.122 -r1.123 src/bin/sh/expand.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/bin/sh/expand.c
diff -u src/bin/sh/expand.c:1.122 src/bin/sh/expand.c:1.123
--- src/bin/sh/expand.c:1.122	Fri Jun 22 17:22:34 2018
+++ src/bin/sh/expand.c	Fri Jun 22 18:19:41 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: expand.c,v 1.122 2018/06/22 17:22:34 kre Exp $	*/
+/*	$NetBSD: expand.c,v 1.123 2018/06/22 18:19:41 kre 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.122 2018/06/22 17:22:34 kre Exp $");
+__RCSID("$NetBSD: expand.c,v 1.123 2018/06/22 18:19:41 kre Exp $");
 #endif
 #endif /* not lint */
 
@@ -1659,12 +1659,20 @@ match_charclass(const char *p, wchar_t c
 	*end = NULL;
 	p++;
 	nameend = strstr(p, ":]");
-	if (nameend == NULL || (size_t)(nameend - p) >= sizeof(name) ||
-	    nameend == 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))
+		return 0;
+
+	*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';
-	*end = nameend + 2;
 	cclass = wctype(name);
 	/* An unknown class matches nothing but is valid nevertheless. */
 	if (cclass == 0)
@@ -1673,7 +1681,6 @@ match_charclass(const char *p, wchar_t c
 }
 
 
-
 /*
  * Returns true if the pattern matches the string.
  */

Reply via email to