This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
save_re_context(): do "local $n" with no PL_curpm
authorDavid Mitchell <davem@iabyn.com>
Wed, 25 Mar 2015 16:59:04 +0000 (16:59 +0000)
committerDavid Mitchell <davem@iabyn.com>
Mon, 30 Mar 2015 11:05:23 +0000 (12:05 +0100)
commit3553f4fa11fd9e8bb0797ace43605cc33ebf32fa
treed85f6d91db8b2b0b4cfd0fb53668e24fd2884b5d
parente8d8f801f452fb6a459fa7375ce32ec55300a01d
save_re_context(): do "local $n" with no PL_curpm

RT #124109.

2c1f00b9036 localised PL_curpm to NULL when calling swash init code
(i.e. perl-level code that is loaded and executed when something
like "lc $large_codepoint" is executed).

b4fa55d3f1 followed this up by gutting Perl_save_re_context(), since
that function did, basically,

    if (PL_curpm) {
        for (i = 1; i <= RX_NPARENS(PM_GETRE(PL_curpm))) {
            do the C equivalent of the perl code "local ${i}";
        }
    }

and now that PL_curpm was null, the code wasn't called any more.  However,
it turns out that the localisation *was* still needed, it's just that
nothing in the test suite actually tested for it.

In something like the following:

    $x = "\x{41c}";
    $x =~ /(.*)/;
    $s = lc $1;

pp_lc() calls get magic on $1, which sets $1's PV value to a copy of the
substring captured by the current pattern match.
Then pp_lc() calls a function to convert the string to upper case, which
triggers a swash load, which calls perl code that does a pattern match
and, most importantly, uses the value of $1. This triggers get magic on
$1, which overwrites $1's PV value with a new value. When control returns
to pp_lc(), $1 now holds the wrong string value.

Hence $1, $2 etc need localising as well as PL_curpm.

The old way that Perl_save_re_context() used to work (localising
$1..${RX_NPARENS}) won't work directly when PL_curpm is NULL (as in the
swash case), since we don't know how many vars to localise.

In this case, hard-code it as localising $1,$2,$3 and add a porting
test file that checks that the utf8.pm code and dependences don't
use anything outside those 3 vars.
MANIFEST
regcomp.c
t/porting/re_context.t [new file with mode: 0644]
t/re/pat_advanced.t