aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--shell/ash.c71
1 files changed, 54 insertions, 17 deletions
diff --git a/shell/ash.c b/shell/ash.c
index e07b81c05..6be3ec600 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -7160,6 +7160,57 @@ addfname(const char *name)
exparg.lastp = &sp->next;
}
+/* Avoid glob() (and thus, stat() et al) for words like "echo" */
+static int
+hasmeta(const char *p)
+{
+ static const char chars[] ALIGN1 = {
+ '*', '?', '[', '\\', CTLQUOTEMARK, CTLESC, 0
+ };
+
+ for (;;) {
+ p = strpbrk(p, chars);
+ if (!p)
+ break;
+ switch ((unsigned char) *p) {
+ case CTLQUOTEMARK:
+ for (;;) {
+ p++;
+ if (*p == CTLQUOTEMARK)
+ break;
+ if (*p == CTLESC)
+ p++;
+ if (*p == '\0') /* huh? */
+ return 0;
+ }
+ break;
+ case '\\':
+ case CTLESC:
+ p++;
+ if (*p == '\0')
+ return 0;
+ break;
+ case '[':
+ if (!strchr(p + 1, ']')) {
+ /* It's not a properly closed [] pattern,
+ * but other metas may follow. Continue checking.
+ * my[file* _is_ globbed by bash
+ * and matches filenames like "my[file1".
+ */
+ break;
+ }
+ /* fallthrough */
+ default:
+ /* case '*': */
+ /* case '?': */
+ return 1;
+ }
+ p++;
+ }
+
+ return 0;
+}
+
/* If we want to use glob() from libc... */
#if !ENABLE_ASH_INTERNAL_GLOB
@@ -7186,20 +7237,9 @@ expandmeta(struct strlist *str /*, int flag*/)
if (fflag)
goto nometa;
- /* Avoid glob() (and thus, stat() et al) for words like "echo" */
- p = str->text;
- while (*p) {
- if (*p == '*')
- goto need_glob;
- if (*p == '?')
- goto need_glob;
- if (*p == '[')
- goto need_glob;
- p++;
- }
- goto nometa;
+ if (!hasmeta(str->text))
+ goto nometa;
- need_glob:
INT_OFF;
p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
// GLOB_NOMAGIC (GNU): if no *?[ chars in pattern, return it even if no match
@@ -7436,9 +7476,6 @@ expsort(struct strlist *str)
static void
expandmeta(struct strlist *str /*, int flag*/)
{
- static const char metachars[] ALIGN1 = {
- '*', '?', '[', 0
- };
/* TODO - EXP_REDIR */
while (str) {
@@ -7449,7 +7486,7 @@ expandmeta(struct strlist *str /*, int flag*/)
if (fflag)
goto nometa;
- if (!strpbrk(str->text, metachars))
+ if (!hasmeta(str->text))
goto nometa;
savelastp = exparg.lastp;