Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F111018680
D10551.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
6 KB
Referenced Files
None
Subscribers
None
D10551.diff
View Options
Index: lib/libc/gen/glob.c
===================================================================
--- lib/libc/gen/glob.c
+++ lib/libc/gen/glob.c
@@ -903,61 +903,73 @@
}
/*
- * pattern matching function for filenames. Each occurrence of the *
- * pattern causes a recursion level.
+ * pattern matching function for filenames.
*/
static int
match(Char *name, Char *pat, Char *patend)
{
int ok, negate_range;
- Char c, k;
+ Char c, k, *nextp, *nextn;
struct xlocale_collate *table =
(struct xlocale_collate*)__get_locale()->components[XLC_COLLATE];
- while (pat < patend) {
- c = *pat++;
- switch (c & M_MASK) {
- case M_ALL:
- if (pat == patend)
- return (1);
- do
- if (match(name, pat, patend))
- return (1);
- while (*name++ != EOS);
- return (0);
- case M_ONE:
- if (*name++ == EOS)
- return (0);
- break;
- case M_SET:
- ok = 0;
- if ((k = *name++) == EOS)
- return (0);
- if ((negate_range = ((*pat & M_MASK) == M_NOT)) != 0)
- ++pat;
- while (((c = *pat++) & M_MASK) != M_END)
- if ((*pat & M_MASK) == M_RNG) {
- if (table->__collate_load_error ?
- CHAR(c) <= CHAR(k) &&
- CHAR(k) <= CHAR(pat[1]) :
- __wcollate_range_cmp(CHAR(c),
- CHAR(k)) <= 0 &&
- __wcollate_range_cmp(CHAR(k),
- CHAR(pat[1])) <= 0)
+ nextn = NULL;
+ nextp = NULL;
+
+ while (1) {
+ while (pat < patend) {
+ c = *pat++;
+ switch (c & M_MASK) {
+ case M_ALL:
+ if (pat == patend)
+ return (1);
+ if (*name == EOS)
+ return (0);
+ nextn = name + 1;
+ nextp = pat - 1;
+ break;
+ case M_ONE:
+ if (*name++ == EOS)
+ goto fail;
+ break;
+ case M_SET:
+ ok = 0;
+ if ((k = *name++) == EOS)
+ goto fail;
+ if ((negate_range = ((*pat & M_MASK) == M_NOT)) != 0)
+ ++pat;
+ while (((c = *pat++) & M_MASK) != M_END)
+ if ((*pat & M_MASK) == M_RNG) {
+ if (table->__collate_load_error ?
+ CHAR(c) <= CHAR(k) &&
+ CHAR(k) <= CHAR(pat[1]) :
+ __wcollate_range_cmp(CHAR(c),
+ CHAR(k)) <= 0 &&
+ __wcollate_range_cmp(CHAR(k),
+ CHAR(pat[1])) <= 0)
+ ok = 1;
+ pat += 2;
+ } else if (c == k)
ok = 1;
- pat += 2;
- } else if (c == k)
- ok = 1;
- if (ok == negate_range)
- return (0);
- break;
- default:
- if (*name++ != c)
- return (0);
- break;
+ if (ok == negate_range)
+ goto fail;
+ break;
+ default:
+ if (*name++ != c)
+ goto fail;
+ break;
+ }
}
+ if (*name == EOS)
+ return (1);
+
+ fail:
+ if (nextn == NULL)
+ break;
+ pat = nextp;
+ name = nextn;
}
- return (*name == EOS);
+ return (0);
}
/* Free allocated data belonging to a glob_t structure. */
Index: lib/libc/tests/gen/Makefile
===================================================================
--- lib/libc/tests/gen/Makefile
+++ lib/libc/tests/gen/Makefile
@@ -8,6 +8,7 @@
ATF_TESTS_C+= fnmatch2_test
ATF_TESTS_C+= fpclassify2_test
ATF_TESTS_C+= ftw_test
+ATF_TESTS_C+= glob2_test
ATF_TESTS_C+= popen_test
ATF_TESTS_C+= posix_spawn_test
ATF_TESTS_C+= wordexp_test
Index: lib/libc/tests/gen/glob2_test.c
===================================================================
--- /dev/null
+++ lib/libc/tests/gen/glob2_test.c
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2017 Dell EMC Isilon
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <glob.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <atf-c.h>
+
+/*
+ * Derived from Russ Cox' pathological case test program used for the
+ * https://research.swtch.com/glob article.
+ */
+ATF_TC_WITHOUT_HEAD(glob_pathological_test);
+ATF_TC_BODY(glob_pathological_test, tc)
+{
+ struct timespec t, t2;
+ glob_t g;
+ const char *longname = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
+ char pattern[1000], *p;
+ double dt;
+ unsigned i, j, k, mul;
+ int fd, rc;
+
+ fd = open(longname, O_CREAT | O_RDWR, 0666);
+ ATF_REQUIRE(fd >= 0);
+
+ /*
+ * Test up to 100 a* groups. Exponential implementations typically go
+ * bang at i=7 or 8.
+ */
+ for (i = 0; i < 100; i++) {
+ /*
+ * Create a*...b pattern with i 'a*' groups.
+ */
+ p = pattern;
+ for (k = 0; k < i; k++) {
+ *p++ = 'a';
+ *p++ = '*';
+ }
+ *p++ = 'b';
+ *p = '\0';
+
+ clock_gettime(CLOCK_REALTIME, &t);
+ for (j = 0; j < mul; j++) {
+ memset(&g, 0, sizeof g);
+ rc = glob(pattern, 0, 0, &g);
+ if (rc == GLOB_NOSPACE || rc == GLOB_ABORTED) {
+ ATF_REQUIRE_MSG(rc == GLOB_NOMATCH,
+ "an unexpected error occurred: "
+ "rc=%d errno=%d", rc, errno);
+ /* NORETURN */
+ }
+
+ ATF_CHECK_MSG(rc == GLOB_NOMATCH,
+ "A bogus match occurred: '%s' ~ '%s'", pattern,
+ g.gl_pathv[0]);
+ globfree(&g);
+ }
+ clock_gettime(CLOCK_REALTIME, &t2);
+
+ t2.tv_sec -= t.tv_sec;
+ t2.tv_nsec -= t.tv_nsec;
+ dt = t2.tv_sec + (double)t2.tv_nsec/1e9;
+ dt /= mul;
+
+ ATF_CHECK_MSG(dt < 1, "glob(3) took far too long: %d %.9f", i,
+ dt);
+
+ if (dt >= 0.0001)
+ mul = 1;
+ }
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, glob_pathological_test);
+
+ return (atf_no_error());
+}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Thu, Feb 27, 7:14 AM (15 h, 25 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
16864221
Default Alt Text
D10551.diff (6 KB)
Attached To
Mode
D10551: libc glob: Avoid pathological exponential behavior
Attached
Detach File
Event Timeline
Log In to Comment