Assignment to a tainted variable was causing confusion if the source
Nicholas Clark [Tue, 2 Jan 2007 21:10:13 +0000 (21:10 +0000)]
value was an NV too large for an IV (bug #40708). Fix the confusion
by not promoting private flags to public flags in S_save_magic if
there are already public flags.

p4raw-id: //depot/perl@29669

mg.c
t/op/taint.t

diff --git a/mg.c b/mg.c
index a0877c5..c5566dc 100644 (file)
--- a/mg.c
+++ b/mg.c
@@ -100,7 +100,10 @@ S_save_magic(pTHX_ I32 mgs_ix, SV *sv)
 
     SvMAGICAL_off(sv);
     SvREADONLY_off(sv);
-    SvFLAGS(sv) |= (SvFLAGS(sv) & (SVp_IOK|SVp_NOK|SVp_POK)) >> PRIVSHIFT;
+    if (!(SvFLAGS(sv) & (SVf_IOK|SVf_NOK|SVf_POK))) {
+       /* No public flags are set, so promote any private flags to public.  */
+       SvFLAGS(sv) |= (SvFLAGS(sv) & (SVp_IOK|SVp_NOK|SVp_POK)) >> PRIVSHIFT;
+    }
 }
 
 /*
index 9e4bba2..5337332 100755 (executable)
@@ -17,7 +17,7 @@ use Config;
 use File::Spec::Functions;
 
 BEGIN { require './test.pl'; }
-plan tests => 255;
+plan tests => 257;
 
 $| = 1;
 
@@ -1218,3 +1218,15 @@ SKIP:
     eval { sprintf("# %s\n", $TAINT . "foo") };
     ok(!$@, q/sprintf accepts other tainted args/);
 }
+
+{
+    # 40708
+    my $n  = 7e9;
+    8e9 - $n;
+
+    my $val = $n;
+    is ($val, '7000000000', 'Assignment to untainted variable');
+    $val = $TAINT;
+    $val = $n;
+    is ($val, '7000000000', 'Assignment to tainted variable');
+}