This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
[perl #84746] Accessing $2 causes the interpreter to crash
authorFather Chrysostomos <sprout@cpan.org>
Sat, 26 Feb 2011 04:45:08 +0000 (20:45 -0800)
committerFather Chrysostomos <sprout@cpan.org>
Sat, 26 Feb 2011 04:45:37 +0000 (20:45 -0800)
commitfd4be6f07df0e6a021290ef721c5d73550e0248c
tree723ee4c44ca9fbb6dd779c5520b1eafb209e78eb
parent84193928209d94622b4501beec2498f435ef3cbf
[perl #84746] Accessing $2 causes the interpreter to crash

Actually, it doesn’t. The original test case was:

#!/usr/bin/perl

my $rx = qr'\$ (?| {(.+?)} | (.+?); | (.+?)(\s) )'x;
my $test = '/home/$USERNAME ';
die unless $test =~ $rx;
print "1: $1\n";
print "2: $2\n" if defined $2;

This crashes even if I put an ‘exit’ right after the pattern match.

What’s happening is that regcomp miscounts the number of capturing
parenthesis pairs (cf. [perl #59734]), so the execution of the regular
expression causes a buffer overflow which overwrites the op_sibling
field of the regcreset op, causing a crash when the op is freed. (The
exact failure may differ between builds, platforms, etc., of course.)

S_reg in regcomp.c keeps a count of the parenthesised groups in a
(?|...) construct, which it updates after each branch, if that branch
has more captures than any previous branch. But it was not updating
the count after the last branch.

So this bug would occur if the last branch had more capturing paren-
theses than any previous branch.

Commit ee91d26, which fixed bug #59734, only solved the problem when
there was just one branch (by updating the count before the loop that
deals with subsequent branches was entered).

This commit changes the code at the end of S_reg to take into account
that RExC_npar (the current paren count) might have been increased by
the last branch.

Since the loop to deal with subsequent branches resets the count
*before* each branch, the code that commit ee91d26 added is no longer
necessary, so this commit removes it.
regcomp.c
t/re/re_tests