summaryrefslogtreecommitdiff
path: root/t
diff options
context:
space:
mode:
authorDavid Mitchell <davem@iabyn.com>2010-03-21 00:01:09 +0000
committerDavid Mitchell <davem@iabyn.com>2010-03-21 00:10:11 +0000
commit3e6bd4bfcd175c613d32ccb2eb2fde8ff580206a (patch)
treed201dbf1dcf2006795c2d1a70019879e157cd1e6 /t
parentb112cff9879ef9e20ee30b1a9ec813b1336a3093 (diff)
downloadperl-3e6bd4bfcd175c613d32ccb2eb2fde8ff580206a.tar.gz
[perl #45167] Taint removal by sprintf
Under some circumstances the value returned by sprintf wasn't tainted, even though its args were. While trying to fix this, I also came across a second bug (which made fixing the first bug very confusing!) where the TARG of the sprintf op, after getting tainted once, permanently retained taint magic, which depending on circumstances, wasn't always set to untainted (mg_len =0) The original bug basically boiled down to parts of Perl_sv_vcatpvfn() directly manipulating the target with SvGROW() / Copy(), which failed to taint the target. Other parts used sv_catsv(), which did. So for example: "%s%s" failed, (only SvGROW) "%s %s" worked (the space char was appended using sv_catsv).
Diffstat (limited to 't')
-rw-r--r--t/op/taint.t29
1 files changed, 28 insertions, 1 deletions
diff --git a/t/op/taint.t b/t/op/taint.t
index c947044568..b4c8bfea53 100644
--- a/t/op/taint.t
+++ b/t/op/taint.t
@@ -17,7 +17,7 @@ use Config;
use File::Spec::Functions;
BEGIN { require './test.pl'; }
-plan tests => 307;
+plan tests => 319;
$| = 1;
@@ -1347,6 +1347,33 @@ foreach my $ord (78, 163, 256) {
ok $i == 2, "tied STORE called correct number of times";
}
+# Bug RT #45167 the return value of sprintf sometimes wasn't tainted
+# when the args were tainted. This only occured on the first use of
+# sprintf; after that, its TARG has taint magic attached, so setmagic
+# at the end works. That's why there are multiple sprintf's below, rather
+# than just one wrapped in an inner loop. Also, any plantext betwerrn
+# fprmat entires would correctly cause tainting to get set. so test with
+# "%s%s" rather than eg "%s %s".
+
+{
+ for my $var1 ($TAINT, "123") {
+ for my $var2 ($TAINT0, "456") {
+ my @s;
+ push @s, sprintf '%s', $var1, $var2;
+ push @s, sprintf ' %s', $var1, $var2;
+ push @s, sprintf '%s%s', $var1, $var2;
+ for (0..2) {
+ ok( !(
+ tainted($s[$_]) xor
+ (tainted($var1) || ($_==2 && tainted($var2)))
+ ),
+ "sprintf fmt$_, '$var1', '$var2'");
+ }
+ }
+ }
+}
+
+
# This may bomb out with the alarm signal so keep it last
SKIP: {