34484a
From 3f8a98327dfdb171bd6e447fec23721b0e74c7a6 Mon Sep 17 00:00:00 2001
34484a
From: Zefram <zefram@fysh.org>
34484a
Date: Sun, 19 Nov 2017 09:15:53 +0000
34484a
Subject: [PATCH] fix tainting of s/// with overloaded replacement
34484a
MIME-Version: 1.0
34484a
Content-Type: text/plain; charset=UTF-8
34484a
Content-Transfer-Encoding: 8bit
34484a
34484a
The substitution code was trying to track the taintedness of the
34484a
replacement string itself, but it didn't account for the replacement
34484a
being an untainted object with overloading that returns a tainted
34484a
stringification.  It looked at the taintedness of the object value, not
34484a
realising that taint could arise during the string concatenation per se.
34484a
Change the taint checks to look at the actual TAINT_get flag after string
34484a
concatenation.  This may falsely ascribe to the replacement taint that
34484a
actually came from somewhere else, but the end result is the same anyway:
34484a
there's no visible behaviour that distinguishes taint specifically from
34484a
the replacement.  Also remove a related taint check that seems to be
34484a
not needed at all.  Fixes [perl #115266].
34484a
34484a
Petr Písař: Ported to 5.26.1.
34484a
34484a
Signed-off-by: Petr Písař <ppisar@redhat.com>
34484a
---
34484a
 pp_ctl.c     |   4 +-
34484a
 pp_hot.c     |   4 +-
34484a
 t/op/taint.t | 428 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
34484a
 3 files changed, 422 insertions(+), 14 deletions(-)
34484a
34484a
diff --git a/pp_ctl.c b/pp_ctl.c
34484a
index f136f91..15c193b 100644
34484a
--- a/pp_ctl.c
34484a
+++ b/pp_ctl.c
34484a
@@ -219,9 +219,9 @@ PP(pp_substcont)
34484a
 	SvGETMAGIC(TOPs); /* possibly clear taint on $1 etc: #67962 */
34484a
 
34484a
     	/* See "how taint works" above pp_subst() */
34484a
-	if (SvTAINTED(TOPs))
34484a
-	    cx->sb_rxtainted |= SUBST_TAINT_REPL;
34484a
 	sv_catsv_nomg(dstr, POPs);
34484a
+	if (UNLIKELY(TAINT_get))
34484a
+	    cx->sb_rxtainted |= SUBST_TAINT_REPL;
34484a
 	if (CxONCE(cx) || s < orig ||
34484a
                 !CALLREGEXEC(rx, s, cx->sb_strend, orig,
34484a
 			     (s == m), cx->sb_targ, NULL,
34484a
diff --git a/pp_hot.c b/pp_hot.c
34484a
index f445fd9..5899413 100644
34484a
--- a/pp_hot.c
34484a
+++ b/pp_hot.c
34484a
@@ -3250,7 +3250,7 @@ PP(pp_subst)
34484a
 	    doutf8 = DO_UTF8(dstr);
34484a
 	}
34484a
 
34484a
-	if (SvTAINTED(dstr))
34484a
+	if (UNLIKELY(TAINT_get))
34484a
 	    rxtainted |= SUBST_TAINT_REPL;
34484a
     }
34484a
     else {
34484a
@@ -3421,8 +3421,6 @@ PP(pp_subst)
34484a
 	    }
34484a
 	    else {
34484a
 		sv_catsv(dstr, repl);
34484a
-		if (UNLIKELY(SvTAINTED(repl)))
34484a
-		    rxtainted |= SUBST_TAINT_REPL;
34484a
 	    }
34484a
 	    if (once)
34484a
 		break;
34484a
diff --git a/t/op/taint.t b/t/op/taint.t
34484a
index c13eaf6..be5eaa8 100644
34484a
--- a/t/op/taint.t
34484a
+++ b/t/op/taint.t
34484a
@@ -17,7 +17,7 @@ BEGIN {
34484a
 use strict;
34484a
 use Config;
34484a
 
34484a
-plan tests => 828;
34484a
+plan tests => 1040;
34484a
 
34484a
 $| = 1;
34484a
 
34484a
@@ -83,6 +83,8 @@ EndOfCleanup
34484a
 # Sources of taint:
34484a
 #   The empty tainted value, for tainting strings
34484a
 my $TAINT = substr($^X, 0, 0);
34484a
+#   A tainted non-empty string
34484a
+my $TAINTXYZ = "xyz".$TAINT;
34484a
 #   A tainted zero, useful for tainting numbers
34484a
 my $TAINT0;
34484a
 {
34484a
@@ -565,7 +567,7 @@ my $TEST = 'TEST';
34484a
         is($one, 'abcd',   "$desc: \$1 value");
34484a
     }
34484a
 
34484a
-    $desc = "substitution with replacement tainted";
34484a
+    $desc = "substitution with partial replacement tainted";
34484a
 
34484a
     $s = 'abcd';
34484a
     $res = $s =~ s/(.+)/xyz$TAINT/;
34484a
@@ -577,7 +579,7 @@ my $TEST = 'TEST';
34484a
     is($res, 1,        "$desc: res value");
34484a
     is($one, 'abcd',   "$desc: \$1 value");
34484a
 
34484a
-    $desc = "substitution /g with replacement tainted";
34484a
+    $desc = "substitution /g with partial replacement tainted";
34484a
 
34484a
     $s = 'abcd';
34484a
     $res = $s =~ s/(.)/x$TAINT/g;
34484a
@@ -589,7 +591,7 @@ my $TEST = 'TEST';
34484a
     is($res, 4,        "$desc: res value");
34484a
     is($one, 'd',      "$desc: \$1 value");
34484a
 
34484a
-    $desc = "substitution /ge with replacement tainted";
34484a
+    $desc = "substitution /ge with partial replacement tainted";
34484a
 
34484a
     $s = 'abc';
34484a
     {
34484a
@@ -618,7 +620,7 @@ my $TEST = 'TEST';
34484a
     is($res, 3,        "$desc: res value");
34484a
     is($one, 'c',      "$desc: \$1 value");
34484a
 
34484a
-    $desc = "substitution /r with replacement tainted";
34484a
+    $desc = "substitution /r with partial replacement tainted";
34484a
 
34484a
     $s = 'abcd';
34484a
     $res = $s =~ s/(.+)/xyz$TAINT/r;
34484a
@@ -630,6 +632,71 @@ my $TEST = 'TEST';
34484a
     is($res, 'xyz',    "$desc: res value");
34484a
     is($one, 'abcd',   "$desc: \$1 value");
34484a
 
34484a
+    $desc = "substitution with whole replacement tainted";
34484a
+
34484a
+    $s = 'abcd';
34484a
+    $res = $s =~ s/(.+)/$TAINTXYZ/;
34484a
+    $one = $1;
34484a
+    is_tainted($s,     "$desc: s tainted");
34484a
+    isnt_tainted($res, "$desc: res not tainted");
34484a
+    isnt_tainted($one, "$desc: \$1 not tainted");
34484a
+    is($s,  'xyz',     "$desc: s value");
34484a
+    is($res, 1,        "$desc: res value");
34484a
+    is($one, 'abcd',   "$desc: \$1 value");
34484a
+
34484a
+    $desc = "substitution /g with whole replacement tainted";
34484a
+
34484a
+    $s = 'abcd';
34484a
+    $res = $s =~ s/(.)/$TAINTXYZ/g;
34484a
+    $one = $1;
34484a
+    is_tainted($s,     "$desc: s tainted");
34484a
+    isnt_tainted($res, "$desc: res not tainted");
34484a
+    isnt_tainted($one, "$desc: \$1 not tainted");
34484a
+    is($s,  'xyz' x 4, "$desc: s value");
34484a
+    is($res, 4,        "$desc: res value");
34484a
+    is($one, 'd',      "$desc: \$1 value");
34484a
+
34484a
+    $desc = "substitution /ge with whole replacement tainted";
34484a
+
34484a
+    $s = 'abc';
34484a
+    {
34484a
+	my $i = 0;
34484a
+	my $j;
34484a
+	$res = $s =~ s{(.)}{
34484a
+		    $j = $i; # make sure code not tainted
34484a
+		    $one = $1;
34484a
+		    isnt_tainted($j, "$desc: code not tainted within /e");
34484a
+		    $i++;
34484a
+		    if ($i == 1) {
34484a
+			isnt_tainted($s,   "$desc: s not tainted loop 1");
34484a
+		    }
34484a
+		    else {
34484a
+			is_tainted($s,     "$desc: s tainted loop $i");
34484a
+		    }
34484a
+		    isnt_tainted($one, "$desc: \$1 not tainted within /e");
34484a
+		    $TAINTXYZ;
34484a
+		}ge;
34484a
+	$one = $1;
34484a
+    }
34484a
+    is_tainted($s,     "$desc: s tainted");
34484a
+    isnt_tainted($res, "$desc: res tainted");
34484a
+    isnt_tainted($one, "$desc: \$1 not tainted");
34484a
+    is($s,  'xyz' x 3, "$desc: s value");
34484a
+    is($res, 3,        "$desc: res value");
34484a
+    is($one, 'c',      "$desc: \$1 value");
34484a
+
34484a
+    $desc = "substitution /r with whole replacement tainted";
34484a
+
34484a
+    $s = 'abcd';
34484a
+    $res = $s =~ s/(.+)/$TAINTXYZ/r;
34484a
+    $one = $1;
34484a
+    isnt_tainted($s,   "$desc: s not tainted");
34484a
+    is_tainted($res,   "$desc: res tainted");
34484a
+    isnt_tainted($one, "$desc: \$1 not tainted");
34484a
+    is($s,   'abcd',   "$desc: s value");
34484a
+    is($res, 'xyz',    "$desc: res value");
34484a
+    is($one, 'abcd',   "$desc: \$1 value");
34484a
+
34484a
     {
34484a
 	# now do them all again with "use re 'taint"
34484a
 
34484a
@@ -955,7 +1022,7 @@ my $TEST = 'TEST';
34484a
         is($one, 'abcd',   "$desc: \$1 value");
34484a
     }
34484a
 
34484a
-	$desc = "use re 'taint': substitution with replacement tainted";
34484a
+	$desc = "use re 'taint': substitution with partial replacement tainted";
34484a
 
34484a
 	$s = 'abcd';
34484a
 	$res = $s =~ s/(.+)/xyz$TAINT/;
34484a
@@ -967,7 +1034,7 @@ my $TEST = 'TEST';
34484a
 	is($res, 1,        "$desc: res value");
34484a
 	is($one, 'abcd',   "$desc: \$1 value");
34484a
 
34484a
-	$desc = "use re 'taint': substitution /g with replacement tainted";
34484a
+	$desc = "use re 'taint': substitution /g with partial replacement tainted";
34484a
 
34484a
 	$s = 'abcd';
34484a
 	$res = $s =~ s/(.)/x$TAINT/g;
34484a
@@ -979,7 +1046,7 @@ my $TEST = 'TEST';
34484a
 	is($res, 4,        "$desc: res value");
34484a
 	is($one, 'd',      "$desc: \$1 value");
34484a
 
34484a
-	$desc = "use re 'taint': substitution /ge with replacement tainted";
34484a
+	$desc = "use re 'taint': substitution /ge with partial replacement tainted";
34484a
 
34484a
 	$s = 'abc';
34484a
 	{
34484a
@@ -1008,7 +1075,7 @@ my $TEST = 'TEST';
34484a
 	is($res, 3,        "$desc: res value");
34484a
 	is($one, 'c',      "$desc: \$1 value");
34484a
 
34484a
-	$desc = "use re 'taint': substitution /r with replacement tainted";
34484a
+	$desc = "use re 'taint': substitution /r with partial replacement tainted";
34484a
 
34484a
 	$s = 'abcd';
34484a
 	$res = $s =~ s/(.+)/xyz$TAINT/r;
34484a
@@ -1020,6 +1087,71 @@ my $TEST = 'TEST';
34484a
 	is($res, 'xyz',    "$desc: res value");
34484a
 	is($one, 'abcd',   "$desc: \$1 value");
34484a
 
34484a
+	$desc = "use re 'taint': substitution with whole replacement tainted";
34484a
+
34484a
+	$s = 'abcd';
34484a
+	$res = $s =~ s/(.+)/$TAINTXYZ/;
34484a
+	$one = $1;
34484a
+	is_tainted($s,     "$desc: s tainted");
34484a
+	isnt_tainted($res, "$desc: res not tainted");
34484a
+	isnt_tainted($one, "$desc: \$1 not tainted");
34484a
+	is($s,  'xyz',     "$desc: s value");
34484a
+	is($res, 1,        "$desc: res value");
34484a
+	is($one, 'abcd',   "$desc: \$1 value");
34484a
+
34484a
+	$desc = "use re 'taint': substitution /g with whole replacement tainted";
34484a
+
34484a
+	$s = 'abcd';
34484a
+	$res = $s =~ s/(.)/$TAINTXYZ/g;
34484a
+	$one = $1;
34484a
+	is_tainted($s,     "$desc: s tainted");
34484a
+	isnt_tainted($res, "$desc: res not tainted");
34484a
+	isnt_tainted($one, "$desc: \$1 not tainted");
34484a
+	is($s,  'xyz' x 4, "$desc: s value");
34484a
+	is($res, 4,        "$desc: res value");
34484a
+	is($one, 'd',      "$desc: \$1 value");
34484a
+
34484a
+	$desc = "use re 'taint': substitution /ge with whole replacement tainted";
34484a
+
34484a
+	$s = 'abc';
34484a
+	{
34484a
+	    my $i = 0;
34484a
+	    my $j;
34484a
+	    $res = $s =~ s{(.)}{
34484a
+			$j = $i; # make sure code not tainted
34484a
+			$one = $1;
34484a
+			isnt_tainted($j, "$desc: code not tainted within /e");
34484a
+			$i++;
34484a
+			if ($i == 1) {
34484a
+			    isnt_tainted($s,   "$desc: s not tainted loop 1");
34484a
+			}
34484a
+			else {
34484a
+			    is_tainted($s,     "$desc: s tainted loop $i");
34484a
+			}
34484a
+			    isnt_tainted($one, "$desc: \$1 not tainted");
34484a
+			$TAINTXYZ;
34484a
+		    }ge;
34484a
+	    $one = $1;
34484a
+	}
34484a
+	is_tainted($s,     "$desc: s tainted");
34484a
+	isnt_tainted($res, "$desc: res tainted");
34484a
+	isnt_tainted($one, "$desc: \$1 not tainted");
34484a
+	is($s,  'xyz' x 3, "$desc: s value");
34484a
+	is($res, 3,        "$desc: res value");
34484a
+	is($one, 'c',      "$desc: \$1 value");
34484a
+
34484a
+	$desc = "use re 'taint': substitution /r with whole replacement tainted";
34484a
+
34484a
+	$s = 'abcd';
34484a
+	$res = $s =~ s/(.+)/$TAINTXYZ/r;
34484a
+	$one = $1;
34484a
+	isnt_tainted($s,   "$desc: s not tainted");
34484a
+	is_tainted($res,   "$desc: res tainted");
34484a
+	isnt_tainted($one, "$desc: \$1 not tainted");
34484a
+	is($s,   'abcd',   "$desc: s value");
34484a
+	is($res, 'xyz',    "$desc: res value");
34484a
+	is($one, 'abcd',   "$desc: \$1 value");
34484a
+
34484a
         # [perl #121854] match taintedness became sticky
34484a
         # when one match has a taintess result, subseqent matches
34484a
         # using the same pattern shouldn't necessarily be tainted
34484a
@@ -2448,6 +2580,284 @@ is eval { eval $::x.1 }, 1, 'reset does not taint undef';
34484a
     isnt_tainted $b, "list assign post tainted expression b";
34484a
 }
34484a
 
34484a
+# taint passing through overloading
34484a
+package OvTaint {
34484a
+    sub new { bless({ t => $_[1] }, $_[0]) }
34484a
+    use overload '""' => sub { $_[0]->{t} ? "hi".$TAINT : "hello" };
34484a
+}
34484a
+my $ovclean = OvTaint->new(0);
34484a
+my $ovtaint = OvTaint->new(1);
34484a
+isnt_tainted("$ovclean", "overload preserves cleanliness");
34484a
+is_tainted("$ovtaint", "overload preserves taint");
34484a
+
34484a
+# substitutions with overloaded replacement
34484a
+{
34484a
+    my ($desc, $s, $res, $one);
34484a
+
34484a
+    $desc = "substitution with partial replacement overloaded and clean";
34484a
+    $s = 'abcd';
34484a
+    $res = $s =~ s/(.+)/xyz$ovclean/;
34484a
+    $one = $1;
34484a
+    isnt_tainted($s,   "$desc: s not tainted");
34484a
+    isnt_tainted($res, "$desc: res not tainted");
34484a
+    isnt_tainted($one, "$desc: \$1 not tainted");
34484a
+    is($s, 'xyzhello', "$desc: s value");
34484a
+    is($res, 1,        "$desc: res value");
34484a
+    is($one, 'abcd',   "$desc: \$1 value");
34484a
+
34484a
+    $desc = "substitution with partial replacement overloaded and tainted";
34484a
+    $s = 'abcd';
34484a
+    $res = $s =~ s/(.+)/xyz$ovtaint/;
34484a
+    $one = $1;
34484a
+    is_tainted($s,     "$desc: s tainted");
34484a
+    isnt_tainted($res, "$desc: res not tainted");
34484a
+    isnt_tainted($one, "$desc: \$1 not tainted");
34484a
+    is($s, 'xyzhi',    "$desc: s value");
34484a
+    is($res, 1,        "$desc: res value");
34484a
+    is($one, 'abcd',   "$desc: \$1 value");
34484a
+
34484a
+    $desc = "substitution with whole replacement overloaded and clean";
34484a
+    $s = 'abcd';
34484a
+    $res = $s =~ s/(.+)/$ovclean/;
34484a
+    $one = $1;
34484a
+    isnt_tainted($s,   "$desc: s not tainted");
34484a
+    isnt_tainted($res, "$desc: res not tainted");
34484a
+    isnt_tainted($one, "$desc: \$1 not tainted");
34484a
+    is($s, 'hello',    "$desc: s value");
34484a
+    is($res, 1,        "$desc: res value");
34484a
+    is($one, 'abcd',   "$desc: \$1 value");
34484a
+
34484a
+    $desc = "substitution with whole replacement overloaded and tainted";
34484a
+    $s = 'abcd';
34484a
+    $res = $s =~ s/(.+)/$ovtaint/;
34484a
+    $one = $1;
34484a
+    is_tainted($s,     "$desc: s tainted");
34484a
+    isnt_tainted($res, "$desc: res not tainted");
34484a
+    isnt_tainted($one, "$desc: \$1 not tainted");
34484a
+    is($s, 'hi',       "$desc: s value");
34484a
+    is($res, 1,        "$desc: res value");
34484a
+    is($one, 'abcd',   "$desc: \$1 value");
34484a
+
34484a
+    $desc = "substitution /e with partial replacement overloaded and clean";
34484a
+    $s = 'abcd';
34484a
+    $res = $s =~ s/(.+)/"xyz".$ovclean/e;
34484a
+    $one = $1;
34484a
+    isnt_tainted($s,   "$desc: s not tainted");
34484a
+    isnt_tainted($res, "$desc: res not tainted");
34484a
+    isnt_tainted($one, "$desc: \$1 not tainted");
34484a
+    is($s, 'xyzhello', "$desc: s value");
34484a
+    is($res, 1,        "$desc: res value");
34484a
+    is($one, 'abcd',   "$desc: \$1 value");
34484a
+
34484a
+    $desc = "substitution /e with partial replacement overloaded and tainted";
34484a
+    $s = 'abcd';
34484a
+    $res = $s =~ s/(.+)/"xyz".$ovtaint/e;
34484a
+    $one = $1;
34484a
+    is_tainted($s,     "$desc: s tainted");
34484a
+    isnt_tainted($res, "$desc: res not tainted");
34484a
+    isnt_tainted($one, "$desc: \$1 not tainted");
34484a
+    is($s, 'xyzhi',    "$desc: s value");
34484a
+    is($res, 1,        "$desc: res value");
34484a
+    is($one, 'abcd',   "$desc: \$1 value");
34484a
+
34484a
+    $desc = "substitution /e with whole replacement overloaded and clean";
34484a
+    $s = 'abcd';
34484a
+    $res = $s =~ s/(.+)/$ovclean/e;
34484a
+    $one = $1;
34484a
+    isnt_tainted($s,   "$desc: s not tainted");
34484a
+    isnt_tainted($res, "$desc: res not tainted");
34484a
+    isnt_tainted($one, "$desc: \$1 not tainted");
34484a
+    is($s, 'hello',    "$desc: s value");
34484a
+    is($res, 1,        "$desc: res value");
34484a
+    is($one, 'abcd',   "$desc: \$1 value");
34484a
+
34484a
+    $desc = "substitution /e with whole replacement overloaded and tainted";
34484a
+    $s = 'abcd';
34484a
+    $res = $s =~ s/(.+)/$ovtaint/e;
34484a
+    $one = $1;
34484a
+    is_tainted($s,     "$desc: s tainted");
34484a
+    isnt_tainted($res, "$desc: res not tainted");
34484a
+    isnt_tainted($one, "$desc: \$1 not tainted");
34484a
+    is($s, 'hi',       "$desc: s value");
34484a
+    is($res, 1,        "$desc: res value");
34484a
+    is($one, 'abcd',   "$desc: \$1 value");
34484a
+
34484a
+    $desc = "substitution /e with extra code and partial replacement overloaded and clean";
34484a
+    $s = 'abcd';
34484a
+    $res = $s =~ s/(.+)/(my $z++), "xyz".$ovclean/e;
34484a
+    $one = $1;
34484a
+    isnt_tainted($s,   "$desc: s not tainted");
34484a
+    isnt_tainted($res, "$desc: res not tainted");
34484a
+    isnt_tainted($one, "$desc: \$1 not tainted");
34484a
+    is($s, 'xyzhello', "$desc: s value");
34484a
+    is($res, 1,        "$desc: res value");
34484a
+    is($one, 'abcd',   "$desc: \$1 value");
34484a
+
34484a
+    $desc = "substitution /e with extra code and partial replacement overloaded and tainted";
34484a
+    $s = 'abcd';
34484a
+    $res = $s =~ s/(.+)/(my $z++), "xyz".$ovtaint/e;
34484a
+    $one = $1;
34484a
+    is_tainted($s,     "$desc: s tainted");
34484a
+    isnt_tainted($res, "$desc: res not tainted");
34484a
+    isnt_tainted($one, "$desc: \$1 not tainted");
34484a
+    is($s, 'xyzhi',    "$desc: s value");
34484a
+    is($res, 1,        "$desc: res value");
34484a
+    is($one, 'abcd',   "$desc: \$1 value");
34484a
+
34484a
+    $desc = "substitution /e with extra code and whole replacement overloaded and clean";
34484a
+    $s = 'abcd';
34484a
+    $res = $s =~ s/(.+)/(my $z++), $ovclean/e;
34484a
+    $one = $1;
34484a
+    isnt_tainted($s,   "$desc: s not tainted");
34484a
+    isnt_tainted($res, "$desc: res not tainted");
34484a
+    isnt_tainted($one, "$desc: \$1 not tainted");
34484a
+    is($s, 'hello',    "$desc: s value");
34484a
+    is($res, 1,        "$desc: res value");
34484a
+    is($one, 'abcd',   "$desc: \$1 value");
34484a
+
34484a
+    $desc = "substitution /e with extra code and whole replacement overloaded and tainted";
34484a
+    $s = 'abcd';
34484a
+    $res = $s =~ s/(.+)/(my $z++), $ovtaint/e;
34484a
+    $one = $1;
34484a
+    is_tainted($s,     "$desc: s tainted");
34484a
+    isnt_tainted($res, "$desc: res not tainted");
34484a
+    isnt_tainted($one, "$desc: \$1 not tainted");
34484a
+    is($s, 'hi',       "$desc: s value");
34484a
+    is($res, 1,        "$desc: res value");
34484a
+    is($one, 'abcd',   "$desc: \$1 value");
34484a
+
34484a
+    $desc = "substitution /r with partial replacement overloaded and clean";
34484a
+    $s = 'abcd';
34484a
+    $res = $s =~ s/(.+)/xyz$ovclean/r;
34484a
+    $one = $1;
34484a
+    isnt_tainted($s,   "$desc: s not tainted");
34484a
+    isnt_tainted($res, "$desc: res not tainted");
34484a
+    isnt_tainted($one, "$desc: \$1 not tainted");
34484a
+    is($s, 'abcd',     "$desc: s value");
34484a
+    is($res, 'xyzhello', "$desc: res value");
34484a
+    is($one, 'abcd',   "$desc: \$1 value");
34484a
+
34484a
+    $desc = "substitution /r with partial replacement overloaded and tainted";
34484a
+    $s = 'abcd';
34484a
+    $res = $s =~ s/(.+)/xyz$ovtaint/r;
34484a
+    $one = $1;
34484a
+    isnt_tainted($s,   "$desc: s not tainted");
34484a
+    is_tainted($res,   "$desc: res tainted");
34484a
+    isnt_tainted($one, "$desc: \$1 not tainted");
34484a
+    is($s, 'abcd',     "$desc: s value");
34484a
+    is($res, 'xyzhi',  "$desc: res value");
34484a
+    is($one, 'abcd',   "$desc: \$1 value");
34484a
+
34484a
+    $desc = "substitution /r with whole replacement overloaded and clean";
34484a
+    $s = 'abcd';
34484a
+    $res = $s =~ s/(.+)/$ovclean/r;
34484a
+    $one = $1;
34484a
+    isnt_tainted($s,   "$desc: s not tainted");
34484a
+    isnt_tainted($res, "$desc: res not tainted");
34484a
+    isnt_tainted($one, "$desc: \$1 not tainted");
34484a
+    is($s, 'abcd',     "$desc: s value");
34484a
+    is($res, 'hello',  "$desc: res value");
34484a
+    is($one, 'abcd',   "$desc: \$1 value");
34484a
+
34484a
+    $desc = "substitution /r with whole replacement overloaded and tainted";
34484a
+    $s = 'abcd';
34484a
+    $res = $s =~ s/(.+)/$ovtaint/r;
34484a
+    $one = $1;
34484a
+    isnt_tainted($s,   "$desc: s not tainted");
34484a
+    is_tainted($res,   "$desc: res tainted");
34484a
+    isnt_tainted($one, "$desc: \$1 not tainted");
34484a
+    is($s, 'abcd',     "$desc: s value");
34484a
+    is($res, 'hi',     "$desc: res value");
34484a
+    is($one, 'abcd',   "$desc: \$1 value");
34484a
+
34484a
+    $desc = "substitution /g with partial replacement overloaded and clean";
34484a
+    $s = 'abcd';
34484a
+    $res = $s =~ s/(.)/x$ovclean/g;
34484a
+    $one = $1;
34484a
+    isnt_tainted($s,   "$desc: s not tainted");
34484a
+    isnt_tainted($res, "$desc: res not tainted");
34484a
+    isnt_tainted($one, "$desc: \$1 not tainted");
34484a
+    is($s, 'xhello' x 4, "$desc: s value");
34484a
+    is($res, 4,        "$desc: res value");
34484a
+    is($one, 'd',      "$desc: \$1 value");
34484a
+
34484a
+    $desc = "substitution /g with partial replacement overloaded and tainted";
34484a
+    $s = 'abcd';
34484a
+    $res = $s =~ s/(.)/x$ovtaint/g;
34484a
+    $one = $1;
34484a
+    is_tainted($s,     "$desc: s tainted");
34484a
+    isnt_tainted($res, "$desc: res not tainted");
34484a
+    isnt_tainted($one, "$desc: \$1 not tainted");
34484a
+    is($s, 'xhi' x 4,  "$desc: s value");
34484a
+    is($res, 4,        "$desc: res value");
34484a
+    is($one, 'd',      "$desc: \$1 value");
34484a
+
34484a
+    $desc = "substitution /g with whole replacement overloaded and clean";
34484a
+    $s = 'abcd';
34484a
+    $res = $s =~ s/(.)/$ovclean/g;
34484a
+    $one = $1;
34484a
+    isnt_tainted($s,   "$desc: s not tainted");
34484a
+    isnt_tainted($res, "$desc: res not tainted");
34484a
+    isnt_tainted($one, "$desc: \$1 not tainted");
34484a
+    is($s, 'hello' x 4, "$desc: s value");
34484a
+    is($res, 4,        "$desc: res value");
34484a
+    is($one, 'd',      "$desc: \$1 value");
34484a
+
34484a
+    $desc = "substitution /g with whole replacement overloaded and tainted";
34484a
+    $s = 'abcd';
34484a
+    $res = $s =~ s/(.)/$ovtaint/g;
34484a
+    $one = $1;
34484a
+    is_tainted($s,     "$desc: s tainted");
34484a
+    isnt_tainted($res, "$desc: res not tainted");
34484a
+    isnt_tainted($one, "$desc: \$1 not tainted");
34484a
+    is($s, 'hi' x 4,   "$desc: s value");
34484a
+    is($res, 4,        "$desc: res value");
34484a
+    is($one, 'd',      "$desc: \$1 value");
34484a
+
34484a
+    $desc = "substitution /ge with partial replacement overloaded and clean";
34484a
+    $s = 'abcd';
34484a
+    $res = $s =~ s/(.)/"x".$ovclean/ge;
34484a
+    $one = $1;
34484a
+    isnt_tainted($s,   "$desc: s not tainted");
34484a
+    isnt_tainted($res, "$desc: res not tainted");
34484a
+    isnt_tainted($one, "$desc: \$1 not tainted");
34484a
+    is($s, 'xhello' x 4, "$desc: s value");
34484a
+    is($res, 4,        "$desc: res value");
34484a
+    is($one, 'd',      "$desc: \$1 value");
34484a
+
34484a
+    $desc = "substitution /ge with partial replacement overloaded and tainted";
34484a
+    $s = 'abcd';
34484a
+    $res = $s =~ s/(.)/"x".$ovtaint/ge;
34484a
+    $one = $1;
34484a
+    is_tainted($s,     "$desc: s tainted");
34484a
+    isnt_tainted($res, "$desc: res not tainted");
34484a
+    isnt_tainted($one, "$desc: \$1 not tainted");
34484a
+    is($s, 'xhi' x 4,  "$desc: s value");
34484a
+    is($res, 4,        "$desc: res value");
34484a
+    is($one, 'd',      "$desc: \$1 value");
34484a
+
34484a
+    $desc = "substitution /ge with whole replacement overloaded and clean";
34484a
+    $s = 'abcd';
34484a
+    $res = $s =~ s/(.)/$ovclean/ge;
34484a
+    $one = $1;
34484a
+    isnt_tainted($s,   "$desc: s not tainted");
34484a
+    isnt_tainted($res, "$desc: res not tainted");
34484a
+    isnt_tainted($one, "$desc: \$1 not tainted");
34484a
+    is($s, 'hello' x 4, "$desc: s value");
34484a
+    is($res, 4,        "$desc: res value");
34484a
+    is($one, 'd',      "$desc: \$1 value");
34484a
+
34484a
+    $desc = "substitution /ge with whole replacement overloaded and tainted";
34484a
+    $s = 'abcd';
34484a
+    $res = $s =~ s/(.)/$ovtaint/ge;
34484a
+    $one = $1;
34484a
+    is_tainted($s,     "$desc: s tainted");
34484a
+    isnt_tainted($res, "$desc: res not tainted");
34484a
+    isnt_tainted($one, "$desc: \$1 not tainted");
34484a
+    is($s, 'hi' x 4,   "$desc: s value");
34484a
+    is($res, 4,        "$desc: res value");
34484a
+    is($one, 'd',      "$desc: \$1 value");
34484a
+}
34484a
 
34484a
 # This may bomb out with the alarm signal so keep it last
34484a
 SKIP: {
34484a
-- 
34484a
2.13.6
34484a