diff options
Diffstat (limited to 'Src/lex.c')
-rw-r--r-- | Src/lex.c | 28 |
1 files changed, 22 insertions, 6 deletions
diff --git a/Src/lex.c b/Src/lex.c index 89af96123..81904c171 100644 --- a/Src/lex.c +++ b/Src/lex.c @@ -1617,7 +1617,7 @@ parsestrnoerr(char **s) mod_export char * parse_subscript(char *s, int sub, int endchar) { - int l = strlen(s), err; + int l = strlen(s), err, toklen; char *t; if (!*s || *s == endchar) @@ -1626,18 +1626,34 @@ parse_subscript(char *s, int sub, int endchar) untokenize(t = dupstring(s)); inpush(t, 0, NULL); strinbeg(0); + /* + * Warning to Future Generations: + * + * This way of passing the subscript through the lexer is brittle. + * Code above this for several layers assumes that when we tokenise + * the input it goes into the same place as the original string. + * However, the lexer may overwrite later bits of the string or + * reallocate it, in particular when expanding aliaes. To get + * around this, we copy the string and then copy it back. This is a + * bit more robust but still relies on the underlying assumption of + * length preservation. + */ lexbuf.len = 0; - lexbuf.ptr = tokstr = s; + lexbuf.ptr = tokstr = dupstring(s); lexbuf.siz = l + 1; err = dquote_parse(endchar, sub); + toklen = (int)(lexbuf.ptr - tokstr); + DPUTS(toklen > l, "Bad length for parsed subscript"); + memcpy(s, tokstr, toklen); if (err) { - err = *lexbuf.ptr; - *lexbuf.ptr = '\0'; + char *strend = s + toklen; + err = *strend; + *strend = '\0'; untokenize(s); - *lexbuf.ptr = err; + *strend = err; s = NULL; } else { - s = lexbuf.ptr; + s += toklen; } strinend(); inpop(); |