This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
[perl #123452] Fix crash with s/${<>{})//
authorFather Chrysostomos <sprout@cpan.org>
Thu, 8 Jan 2015 03:33:39 +0000 (19:33 -0800)
committerFather Chrysostomos <sprout@cpan.org>
Thu, 8 Jan 2015 03:35:06 +0000 (19:35 -0800)
commit08b999a9d7e845b758c38568f45f6b2b8d552ed9
treeb5f5e0677ab5889775469cf83974da12e95f663d
parente7368224f1884f08b01b3cedcf693510ca964712
[perl #123452] Fix crash with s/${<>{})//

s/foo/bar/ tokenizes as something akin to subst("foo","bar") and the
resulting list op representing the contents of the parentheses is
passed to pmruntime as its expr argument.

If we have invalid code like s/${<>{})//, the bison parser will dis-
card invalid tokens until it finds something it can fall back to, in
an attempt to keep parsing (to report as many errors as possible).

In the process of discarding tokens, it may convert s/${<>{})//, which
the lexer emits like this:

    PMFUNC ( $ { THING(readline) { } ) , "" )

into this:

    PMFUNC ( $ { THING(readline) } ) , "" )

(or something similar).  So when the parser sees the first closing
parentheses, it decides it has a complete PMFUNC(...), and the expr
argument to pmruntime ends up being an rv2sv op (the ${...}), not
a list op.

pmruntime assumes it is a list op, and tries to access its op_last
field, to find the replacement part; but rv2sv has no op_last field,
so this reads past the end of the op struct, usually into the first
pointer in the next op slot, which itself is an opslot pointer, not an
op pointer, so things really screw up.

If we check that the arguments to subst are indeed a list op first
before trying to extract the replacement part, everything works.  We
get the syntax errors reported as expected, but no crash.
op.c
t/comp/parser.t