$tainted ~~ [...] failing
authorFather Chrysostomos <sprout@cpan.org>
Tue, 20 Sep 2011 15:55:09 +0000 (08:55 -0700)
committerDominic Hargreaves <dom@earth.li>
Sun, 28 Oct 2012 18:02:54 +0000 (18:02 +0000)
commit667d751ea1f833c15e2e9180d147f052a8b3be04
treedbb06bb73572a2f2318cc63319016f67d7c41b35
parentfed0a1f9be8a538697f6b18597762d1a62b6acd5
$tainted ~~ [...] failing

When smartmatch is about to start, to avoid calling get-magic (e.g.,
FETCH methods) more than once, it copies any argument that has
get-magic.

Tainting uses get-magic to taint the expression.  Calling mg_get(sv)
on a tainted scalar causes PL_tainted to be set, causing any scalars
modified by sv_setsv_flags to be tainted.  That means that tainting
magic gets copied from one scalar to another.

So when smartmatch tries to copy the variable to avoid repeated calls
to magic, it still copies taint magic to the new variable.

For $scalar ~~ @array (or ~~ [...]), S_do_smartmatch calls itself
recursively for each element of @array, with $scalar (on the suppos-
edly non-magical copy of $scalar) on the left and the element on
the right.

In that recursive call, it again does the get-magic check and copies
the argument.  Since the copied of a tainted variable on the LHS is
magical, it gets copied again.  Since the first copy is a mortal
(marked TEMP) with a refcount of one, the second copy steal its
string buffer.

The outer call to S_do_smartmatch then proceeds with the second ele-
ment of @array, without realising that its copy of $scalar has lost
its string buffer and is now undefined.

So these produce incorrect results under -T (where $^X is ‘perl’):

    $^X =~ ["whatever", undef]  # matches
    $^X =~ ["whatever", "perl"] # fails

This problem did not start occurring until this commit:

commit 8985fe98dcc5c0af2fadeac15dfbc13f553ee7fc
Author: David Mitchell <davem@iabyn.com>
Date:   Thu Dec 30 10:32:44 2010 +0000

    Better handling of magic methods freeing the SV

mg_get used to increase the refcount unconditionally, pushing it on to
the mortals stack.  So the magical copy would have had a refcount of
2, preventing its string buffer from being stolen.  Now it has a ref-
erence count of 1.

This commit solves it by adding a new parameter to S_do_smartmatch
telling it that the variable has already been copied and does not even
need to be checked.  The $scalar~~@array case sets that parameter for
the recursive calls.  That avoids the whole string-stealing problem
*and* avoids extra unnecessary SVs.

Origin: upstream, http://perl5.git.perl.org/perl.git/commit/be88a5c3cc8efc0dbee86240eabf0050554fc717
Bug: http://rt.perl.org/rt3/Public/Bug/Display.html?id=93590
Bug-Debian: http://bugs.debian.org/690571

(Backported to 5.14 by Niko Tyni.)
embed.fnc
embed.h
pp_ctl.c
proto.h
t/op/taint.t