Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: "bad substitution" error for ${a[b]}



On Jul 15,  3:03pm, Jason L Tibbitts III wrote:
} Subject: "bad substitution" error for ${a[b]}
}
} I'm trying to understand the following:
} 
} > echo '$a[b]' | zsh -fn
} 
} > echo '${a[b]}' | zsh -fn
} zsh: bad substitution
} 
} Specifically, what's wrong with the second line?

Nothing; zsh is confused by trying to parse an interpreted language
without performing any real interpretation.


With NO_EXEC set, something goes wrong in getindex() called from subst.c
line 2433 (in the current git revision) such that the pointer to "s" is
not advanced past the subscript expression.  Less specifically, zsh sees
a '[' where it expects to find a '}' and complains.

Amusingly the problem seems to be in getarg() right here:

   1118     /*
   1119      * If in NO_EXEC mode, the parameters won't be set up
   1120      * properly, so there's no point even doing any sanity checking.
   1121      * Just return 0 now.
   1122      */
   1123     if (unset(EXECOPT))
   1124         return 0;

This is a bit of a conundrum.  The subscript expression can't be parsed
correctly without knowing whether it is subscripting a plain array or an
associative array, but in NO_EXEC mode the variable is neither set nor
declared so the type can't be known.

When there are no braces, NO_EXEC treats $a[b] as ${a}'[b]' and silently
ignores the whole issue.  Leaving aside that particular weirdness, the
following seems to do the trick; objections?  Grotesque nested expansion
cases that are going to go horribly awry?


diff --git a/Src/params.c b/Src/params.c
index 3b75735..7d0c852 100644
--- a/Src/params.c
+++ b/Src/params.c
@@ -1116,14 +1116,12 @@ getarg(char **str, int *inv, Value v, int a2, zlong *w,
     Patprog pprog = NULL;
 
     /*
-     * If in NO_EXEC mode, the parameters won't be set up
-     * properly, so there's no point even doing any sanity checking.
-     * Just return 0 now.
+     * If in NO_EXEC mode, the parameters won't be set up properly,
+     * so just pretend everything is a hash for subscript parsing
      */
-    if (unset(EXECOPT))
-	return 0;
 
-    ishash = (v->pm && PM_TYPE(v->pm->node.flags) == PM_HASHED);
+    ishash = (unset(EXECOPT) ||
+	      (v->pm && PM_TYPE(v->pm->node.flags) == PM_HASHED));
     if (prevcharlen)
 	*prevcharlen = 1;
     if (nextcharlen)
@@ -1278,8 +1276,18 @@ getarg(char **str, int *inv, Value v, int a2, zlong *w,
     }
     if (!c)
 	return 0;
-    s = dupstrpfx(s, t - s);
     *str = tt = t;
+
+    /*
+     * If in NO_EXEC mode, the parameters won't be set up properly,
+     * so there's no additional sanity checking we can do.
+     * Just return 0 now.
+     */
+    if (unset(EXECOPT))
+	return 0;
+
+    s = dupstrpfx(s, t - s);
+
     /* If we're NOT reverse subscripting, strip the inull()s so brackets *
      * are not backslashed after parsestr().  Otherwise leave them alone *
      * so that the brackets will be escaped when we patcompile() or when *

-- 
Barton E. Schaefer



Messages sorted by: Reverse Date, Date, Thread, Author