diff --git a/ChangeLog b/ChangeLog index 13ef6b06b..c57658564 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2012-06-19 Vladimir Serbinenko + + Fix wildcard regexp dot and other special characters handling. + Reported by: Robert Mabee. + + * grub-core/commands/wildcard.c (isregexop): Add "|+{}[]?". + (make_regex): Escape "|+{}[]". Transform '?' to '.?'. + (split_path): Trigger expansion on '?'. + (unescape): New function. + (wildcard_expand): Unescape parts copied without globbing. + * grub-core/script/execute.c (wildcard_escape): Escape '?'. + (grub_script_arglist_to_argv): Don't unescape expansions. + 2012-06-19 Vladimir Serbinenko * include/grub/net.h (grub_net_card): New member txbufsize. diff --git a/grub-core/commands/wildcard.c b/grub-core/commands/wildcard.c index 2883b2096..56eea10b7 100644 --- a/grub-core/commands/wildcard.c +++ b/grub-core/commands/wildcard.c @@ -80,7 +80,7 @@ merge (char **dest, char **ps) static inline int isregexop (char ch) { - return grub_strchr ("*.\\", ch) ? 1 : 0; + return grub_strchr ("*.\\|+{}[]?", ch) ? 1 : 0; } static char * @@ -123,7 +123,7 @@ make_regex (const char *start, const char *end, regex_t *regexp) buffer[i++] = '^'; while (start < end) { - /* XXX Only * expansion for now. */ + /* XXX Only * and ? expansion for now. */ switch ((ch = *start++)) { case '\\': @@ -136,6 +136,12 @@ make_regex (const char *start, const char *end, regex_t *regexp) case '(': case ')': case '@': + case '+': + case '|': + case '{': + case '}': + case '[': + case ']': buffer[i++] = '\\'; buffer[i++] = ch; break; @@ -145,6 +151,10 @@ make_regex (const char *start, const char *end, regex_t *regexp) buffer[i++] = '*'; break; + case '?': + buffer[i++] = '.'; + break; + default: buffer[i++] = ch; } @@ -181,7 +191,7 @@ split_path (const char *str, const char **noregexop, const char **regexop) if (ch == '\\' && end[1]) end++; - else if (isregexop (ch)) + else if (ch == '*' || ch == '?') regex = 1; else if (ch == '/' && ! regex) @@ -410,6 +420,27 @@ check_file (const char *dir, const char *basename) return found; } +static void +unescape (char *out, const char *in, const char *end) +{ + char *optr; + const char *iptr; + + for (optr = out, iptr = in; iptr < end;) + { + if (*iptr == '\\' && iptr + 1 < end) + { + *optr++ = iptr[1]; + iptr += 2; + continue; + } + if (*iptr == '\\') + break; + *optr++ = *iptr++; + } + *optr = 0; +} + static grub_err_t wildcard_expand (const char *s, char ***strs) { @@ -442,8 +473,7 @@ wildcard_expand (const char *s, char ***strs) paths[0] = grub_malloc (regexop - start + 1); if (!paths[0]) goto fail; - grub_memcpy (paths[0], start, regexop - start); - paths[0][regexop - start] = '\0'; + unescape (paths[0], start, regexop); paths[1] = 0; } else @@ -460,8 +490,8 @@ wildcard_expand (const char *s, char ***strs) if (!n) goto fail; grub_memcpy (n, o, oend - o); - grub_memcpy (n + (oend - o), start, regexop - start); - n[(oend - o) + (regexop - start)] = '\0'; + + unescape (n + (oend - o), start, regexop); if (had_regexp) p = grub_strrchr (n, '/'); else diff --git a/grub-core/script/execute.c b/grub-core/script/execute.c index 0331a9501..8855bc126 100644 --- a/grub-core/script/execute.c +++ b/grub-core/script/execute.c @@ -68,7 +68,7 @@ wildcard_escape (const char *s) i = 0; while ((ch = *s++)) { - if (ch == '*' || ch == '\\') + if (ch == '*' || ch == '\\' || ch == '?') p[i++] = '\\'; p[i++] = ch; } @@ -706,7 +706,7 @@ grub_script_arglist_to_argv (struct grub_script_arglist *arglist, for (j = 0; expansions[j]; j++) { failed = (failed || grub_script_argv_next (&result) || - append (expansions[j], -1)); + append (expansions[j], 0)); grub_free (expansions[j]); } grub_free (expansions);