summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--pp_ctl.c35
-rw-r--r--pp_hot.c19
-rwxr-xr-xt/op/taint.t38
3 files changed, 77 insertions, 15 deletions
diff --git a/pp_ctl.c b/pp_ctl.c
index b05e13fa0c..009d636099 100644
--- a/pp_ctl.c
+++ b/pp_ctl.c
@@ -1316,6 +1316,7 @@ PP(pp_leaveloop)
mark = newsp;
POPLOOP1(cx); /* Delay POPLOOP2 until stack values are safe */
+ TAINT_NOT;
if (gimme == G_VOID)
; /* do nothing */
else if (gimme == G_SCALAR) {
@@ -1325,8 +1326,10 @@ PP(pp_leaveloop)
*++newsp = &sv_undef;
}
else {
- while (mark < SP)
+ while (mark < SP) {
*++newsp = sv_mortalcopy(*++mark);
+ TAINT_NOT; /* Each item is independent */
+ }
}
SP = newsp;
PUTBACK;
@@ -1389,6 +1392,7 @@ PP(pp_return)
DIE("panic: return");
}
+ TAINT_NOT;
if (gimme == G_SCALAR) {
if (MARK < SP)
*++newsp = (popsub2 && SvTEMP(*SP))
@@ -1397,9 +1401,11 @@ PP(pp_return)
*++newsp = &sv_undef;
}
else if (gimme == G_ARRAY) {
- while (++MARK <= SP)
+ while (++MARK <= SP) {
*++newsp = (popsub2 && SvTEMP(*MARK))
? *MARK : sv_mortalcopy(*MARK);
+ TAINT_NOT; /* Each item is independent */
+ }
}
stack_sp = newsp;
@@ -1461,6 +1467,7 @@ PP(pp_last)
DIE("panic: last");
}
+ TAINT_NOT;
if (gimme == G_SCALAR) {
if (MARK < SP)
*++newsp = ((pop2 == CXt_SUB) && SvTEMP(*SP))
@@ -1469,9 +1476,11 @@ PP(pp_last)
*++newsp = &sv_undef;
}
else if (gimme == G_ARRAY) {
- while (++MARK <= SP)
+ while (++MARK <= SP) {
*++newsp = ((pop2 == CXt_SUB) && SvTEMP(*MARK))
? *MARK : sv_mortalcopy(*MARK);
+ TAINT_NOT; /* Each item is independent */
+ }
}
SP = newsp;
PUTBACK;
@@ -2326,6 +2335,7 @@ PP(pp_leaveeval)
POPEVAL(cx);
retop = pop_return();
+ TAINT_NOT;
if (gimme == G_VOID)
MARK = newsp;
else if (gimme == G_SCALAR) {
@@ -2342,10 +2352,13 @@ PP(pp_leaveeval)
}
}
else {
- for (mark = newsp + 1; mark <= SP; mark++)
- if (!(SvFLAGS(*mark) & SVs_TEMP))
+ /* in case LEAVE wipes old return values */
+ for (mark = newsp + 1; mark <= SP; mark++) {
+ if (!(SvFLAGS(*mark) & SVs_TEMP)) {
*mark = sv_mortalcopy(*mark);
- /* in case LEAVE wipes old return values */
+ TAINT_NOT; /* Each item is independent */
+ }
+ }
}
curpm = newpm; /* Don't pop $1 et al till now */
@@ -2406,6 +2419,7 @@ PP(pp_leavetry)
POPEVAL(cx);
pop_return();
+ TAINT_NOT;
if (gimme == G_VOID)
SP = newsp;
else if (gimme == G_SCALAR) {
@@ -2423,10 +2437,13 @@ PP(pp_leavetry)
SP = MARK;
}
else {
- for (mark = newsp + 1; mark <= SP; mark++)
- if (!(SvFLAGS(*mark) & (SVs_PADTMP|SVs_TEMP)))
+ /* in case LEAVE wipes old return values */
+ for (mark = newsp + 1; mark <= SP; mark++) {
+ if (!(SvFLAGS(*mark) & (SVs_PADTMP|SVs_TEMP))) {
*mark = sv_mortalcopy(*mark);
- /* in case LEAVE wipes old return values */
+ TAINT_NOT; /* Each item is independent */
+ }
+ }
}
curpm = newpm; /* Don't pop $1 et al till now */
diff --git a/pp_hot.c b/pp_hot.c
index 8a301e50ee..d8b1976a23 100644
--- a/pp_hot.c
+++ b/pp_hot.c
@@ -602,8 +602,10 @@ PP(pp_aassign)
if (op->op_private & OPpASSIGN_COMMON) {
for (relem = firstrelem; relem <= lastrelem; relem++) {
/*SUPPRESS 560*/
- if (sv = *relem)
+ if (sv = *relem) {
+ TAINT_NOT; /* Each item is independent */
*relem = sv_mortalcopy(sv);
+ }
}
}
@@ -1313,6 +1315,7 @@ PP(pp_leave)
gimme = G_SCALAR;
}
+ TAINT_NOT;
if (gimme == G_VOID)
SP = newsp;
else if (gimme == G_SCALAR) {
@@ -1329,10 +1332,13 @@ PP(pp_leave)
SP = MARK;
}
else if (gimme == G_ARRAY) {
- for (mark = newsp + 1; mark <= SP; mark++)
- if (!(SvFLAGS(*mark) & (SVs_PADTMP|SVs_TEMP)))
+ /* in case LEAVE wipes old return values */
+ for (mark = newsp + 1; mark <= SP; mark++) {
+ if (!(SvFLAGS(*mark) & (SVs_PADTMP|SVs_TEMP))) {
*mark = sv_mortalcopy(*mark);
- /* in case LEAVE wipes old return values */
+ TAINT_NOT; /* Each item is independent */
+ }
+ }
}
curpm = newpm; /* Don't pop $1 et al till now */
@@ -1693,6 +1699,7 @@ PP(pp_leavesub)
POPBLOCK(cx,newpm);
POPSUB1(cx); /* Delay POPSUB2 until stack values are safe */
+ TAINT_NOT;
if (gimme == G_SCALAR) {
MARK = newsp + 1;
if (MARK <= SP)
@@ -1705,8 +1712,10 @@ PP(pp_leavesub)
}
else if (gimme == G_ARRAY) {
for (MARK = newsp + 1; MARK <= SP; MARK++) {
- if (!SvTEMP(*MARK))
+ if (!SvTEMP(*MARK)) {
*MARK = sv_mortalcopy(*MARK);
+ TAINT_NOT; /* Each item is independent */
+ }
}
}
PUTBACK;
diff --git a/t/op/taint.t b/t/op/taint.t
index 81d698ae8b..8639fd60f5 100755
--- a/t/op/taint.t
+++ b/t/op/taint.t
@@ -79,7 +79,7 @@ print PROG 'print "@ARGV\n"', "\n";
close PROG;
my $echo = "$Invoke_Perl $ECHO";
-print "1..112\n";
+print "1..136\n";
# First, let's make sure that Perl is checking the dangerous
# environment variables. Maybe they aren't set yet, so we'll
@@ -469,3 +469,39 @@ print "1..112\n";
test 111, tainted($bar--);
test 112, $bar == 0;
}
+
+# Test assignment and return of lists
+{
+ my @foo = ("A", "tainted" . $TAINT, "B");
+ test 113, not tainted $foo[0];
+ test 114, tainted $foo[1];
+ test 115, not tainted $foo[2];
+ my @bar = @foo;
+ test 116, not tainted $bar[0];
+ test 117, tainted $bar[1];
+ test 118, not tainted $bar[2];
+ my @baz = eval { "A", "tainted" . $TAINT, "B" };
+ test 119, not tainted $baz[0];
+ test 120, tainted $baz[1];
+ test 121, not tainted $baz[2];
+ my @plugh = eval q[ "A", "tainted" . $TAINT, "B" ];
+ test 122, not tainted $plugh[0];
+ test 123, tainted $plugh[1];
+ test 124, not tainted $plugh[2];
+ my $nautilus = sub { "A", "tainted" . $TAINT, "B" };
+ test 125, not tainted ((&$nautilus)[0]);
+ test 126, tainted ((&$nautilus)[1]);
+ test 127, not tainted ((&$nautilus)[2]);
+ my @xyzzy = &$nautilus;
+ test 128, not tainted $xyzzy[0];
+ test 129, tainted $xyzzy[1];
+ test 130, not tainted $xyzzy[2];
+ my $red_october = sub { return "A", "tainted" . $TAINT, "B" };
+ test 131, not tainted ((&$red_october)[0]);
+ test 132, tainted ((&$red_october)[1]);
+ test 133, not tainted ((&$red_october)[2]);
+ my @corge = &$red_october;
+ test 134, not tainted $corge[0];
+ test 135, tainted $corge[1];
+ test 136, not tainted $corge[2];
+}