Tue Oct 8 03:52:44 2019 UTC ()
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


(kre)
diff -r1.132 -r1.133 src/bin/sh/expand.c

cvs diff -r1.132 -r1.133 src/bin/sh/expand.c (expand / switch to unified diff)

--- src/bin/sh/expand.c 2019/04/10 08:13:11 1.132
+++ src/bin/sh/expand.c 2019/10/08 03:52:44 1.133
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: expand.c,v 1.132 2019/04/10 08:13:11 kre Exp $ */ 1/* $NetBSD: expand.c,v 1.133 2019/10/08 03:52:44 kre Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 1991, 1993 4 * Copyright (c) 1991, 1993
5 * The Regents of the University of California. All rights reserved. 5 * The Regents of the University of California. All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to Berkeley by 7 * This code is derived from software contributed to Berkeley by
8 * Kenneth Almquist. 8 * Kenneth Almquist.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
@@ -27,27 +27,27 @@ @@ -27,27 +27,27 @@
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE. 32 * SUCH DAMAGE.
33 */ 33 */
34 34
35#include <sys/cdefs.h> 35#include <sys/cdefs.h>
36#ifndef lint 36#ifndef lint
37#if 0 37#if 0
38static char sccsid[] = "@(#)expand.c 8.5 (Berkeley) 5/15/95"; 38static char sccsid[] = "@(#)expand.c 8.5 (Berkeley) 5/15/95";
39#else 39#else
40__RCSID("$NetBSD: expand.c,v 1.132 2019/04/10 08:13:11 kre Exp $"); 40__RCSID("$NetBSD: expand.c,v 1.133 2019/10/08 03:52:44 kre Exp $");
41#endif 41#endif
42#endif /* not lint */ 42#endif /* not lint */
43 43
44#include <sys/types.h> 44#include <sys/types.h>
45#include <sys/time.h> 45#include <sys/time.h>
46#include <sys/stat.h> 46#include <sys/stat.h>
47#include <errno.h> 47#include <errno.h>
48#include <dirent.h> 48#include <dirent.h>
49#include <unistd.h> 49#include <unistd.h>
50#include <pwd.h> 50#include <pwd.h>
51#include <limits.h> 51#include <limits.h>
52#include <stdlib.h> 52#include <stdlib.h>
53#include <stdio.h> 53#include <stdio.h>
@@ -1782,44 +1782,64 @@ msort(struct strlist *list, int len) @@ -1782,44 +1782,64 @@ msort(struct strlist *list, int len)
1782/* 1782/*
1783 * See if a character matches a character class, starting at the first colon 1783 * See if a character matches a character class, starting at the first colon
1784 * of "[:class:]". 1784 * of "[:class:]".
1785 * If a valid character class is recognized, a pointer to the next character 1785 * If a valid character class is recognized, a pointer to the next character
1786 * after the final closing bracket is stored into *end, otherwise a null 1786 * after the final closing bracket is stored into *end, otherwise a null
1787 * pointer is stored into *end. 1787 * pointer is stored into *end.
1788 */ 1788 */
1789static int 1789static int
1790match_charclass(const char *p, wchar_t chr, const char **end) 1790match_charclass(const char *p, wchar_t chr, const char **end)
1791{ 1791{
1792 char name[20]; 1792 char name[20];
1793 char *nameend; 1793 char *nameend;
1794 wctype_t cclass; 1794 wctype_t cclass;
 1795 char *q;
1795 1796
1796 *end = NULL; 1797 *end = NULL;
1797 p++; 1798 p++;
 1799 q = &name[0];
1798 nameend = strstr(p, ":]"); 1800 nameend = strstr(p, ":]");
1799 if (nameend == NULL || nameend == p) /* not a valid class */ 1801 if (nameend == NULL || nameend == p) /* not a valid class */
1800 return 0; 1802 return 0;
1801 1803
1802 if (!is_alpha(*p) || strspn(p, /* '_' is a local extension */ 1804 if (*p == CTLESC) {
1803 "0123456789" "_" 1805 if (*++p == CTLESC)
1804 "abcdefghijklmnopqrstuvwxyz" 1806 return 0;
1805 "ABCDEFGHIJKLMNOPQRSTUVWXYZ") != (size_t)(nameend - p)) 1807 if (p == nameend)
 1808 return 0;
 1809 }
 1810 if (!is_alpha(*p))
1806 return 0; 1811 return 0;
 1812 while (p < nameend) {
 1813 if (*p == CTLESC) {
 1814 p++;
 1815 if (p == nameend)
 1816 return 0;
 1817 }
 1818 if (!is_in_name(*p)) /* '_' is a local extension */
 1819 return 0;
 1820 if (q < &name[sizeof name])
 1821 *q++ = *p++;
 1822 else
 1823 p++;
 1824 }
1807 1825
1808 *end = nameend + 2; /* committed to it being a char class */ 1826 *end = nameend + 2; /* committed to it being a char class */
1809 if ((size_t)(nameend - p) >= sizeof(name)) /* but too long */ 1827
1810 return 0; /* so no match */ 1828 if (q < &name[sizeof name]) /* a usable name found */
1811 memcpy(name, p, nameend - p); 1829 *q++ = '\0';
1812 name[nameend - p] = '\0'; 1830 else /* too long, valid, but no match */
 1831 return 0;
 1832
1813 cclass = wctype(name); 1833 cclass = wctype(name);
1814 /* An unknown class matches nothing but is valid nevertheless. */ 1834 /* An unknown class matches nothing but is valid nevertheless. */
1815 if (cclass == 0) 1835 if (cclass == 0)
1816 return 0; 1836 return 0;
1817 return iswctype(chr, cclass); 1837 return iswctype(chr, cclass);
1818} 1838}
1819 1839
1820 1840
1821/* 1841/*
1822 * Returns true if the pattern matches the string. 1842 * Returns true if the pattern matches the string.
1823 */ 1843 */
1824 1844
1825STATIC int 1845STATIC int