From 36992251c369a3e9ce227a1ea6476a5a8acccbe8 Mon Sep 17 00:00:00 2001 From: nobu Date: Thu, 5 Aug 2010 07:57:26 +0000 Subject: * dir.c (glob_make_pattern): fold continuous PLAINs to get rid of snail at too deep path. [ruby-dev:41871] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@28866 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 5 +++++ dir.c | 34 ++++++++++++++++++++-------------- 2 files changed, 25 insertions(+), 14 deletions(-) diff --git a/ChangeLog b/ChangeLog index 7a9a9376bc..bf615e503c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +Thu Aug 5 16:57:20 2010 Nobuyoshi Nakada + + * dir.c (glob_make_pattern): fold continuous PLAINs to get rid of + snail at too deep path. [ruby-dev:41871] + Thu Aug 5 16:42:41 2010 Nobuyoshi Nakada * string.c (rb_str_set_len): should fail to modify shared string. diff --git a/dir.c b/dir.c index 14317a4ba2..5c972898de 100644 --- a/dir.c +++ b/dir.c @@ -1045,16 +1045,14 @@ do_opendir(const char *path, int flags) /* Return nonzero if S has any special globbing chars in it. */ static int -has_magic(const char *s, int flags, rb_encoding *enc) +has_magic(const char *p, const char *pend, int flags, rb_encoding *enc) { const int escape = !(flags & FNM_NOESCAPE); const int nocase = flags & FNM_CASEFOLD; - register const char *p = s; - register const char *pend = p + strlen(p); register char c; - while ((c = *p++) != 0) { + while (p < pend && (c = *p++) != 0) { switch (c) { case '*': case '?': @@ -1079,12 +1077,10 @@ has_magic(const char *s, int flags, rb_encoding *enc) /* Find separator in globbing pattern. */ static char * -find_dirsep(const char *s, int flags, rb_encoding *enc) +find_dirsep(const char *p, const char *pend, int flags, rb_encoding *enc) { const int escape = !(flags & FNM_NOESCAPE); - register const char *p = s; - register const char *pend = p + strlen(p); register char c; int open = 0; @@ -1151,31 +1147,41 @@ struct glob_pattern { static void glob_free_pattern(struct glob_pattern *list); static struct glob_pattern * -glob_make_pattern(const char *p, int flags, rb_encoding *enc) +glob_make_pattern(const char *p, const char *e, int flags, rb_encoding *enc) { struct glob_pattern *list, *tmp, **tail = &list; int dirsep = 0; /* pattern is terminated with '/' */ - while (*p) { + while (p < e && *p) { tmp = GLOB_ALLOC(struct glob_pattern); if (!tmp) goto error; if (p[0] == '*' && p[1] == '*' && p[2] == '/') { /* fold continuous RECURSIVEs (needed in glob_helper) */ - do { p += 3; } while (p[0] == '*' && p[1] == '*' && p[2] == '/'); + do { p += 3; while (*p == '/') p++; } while (p[0] == '*' && p[1] == '*' && p[2] == '/'); tmp->type = RECURSIVE; tmp->str = 0; dirsep = 1; } else { - const char *m = find_dirsep(p, flags, enc); - char *buf = GLOB_ALLOC_N(char, m-p+1); + const char *m = find_dirsep(p, e, flags, enc); + int magic = has_magic(p, m, flags, enc); + char *buf; + + if (!magic && *m) { + const char *m2; + while (!has_magic(m+1, m2 = find_dirsep(m+1, e, flags, enc), flags, enc) && + *m2) { + m = m2; + } + } + buf = GLOB_ALLOC_N(char, m-p+1); if (!buf) { GLOB_FREE(tmp); goto error; } memcpy(buf, p, m-p); buf[m-p] = '\0'; - tmp->type = has_magic(buf, flags, enc) ? MAGICAL : PLAIN; + tmp->type = magic ? MAGICAL : PLAIN; tmp->str = buf; if (*m) { dirsep = 1; @@ -1480,7 +1486,7 @@ ruby_glob0(const char *path, int flags, ruby_glob_func *func, VALUE arg, rb_enco MEMCPY(buf, start, char, n); buf[n] = '\0'; - list = glob_make_pattern(root, flags, enc); + list = glob_make_pattern(root, root + strlen(root), flags, enc); if (!list) { GLOB_FREE(buf); return -1; -- cgit v1.2.3