Pseudo-fork dups arg array on argless calls
authorDavid Mitchell <davem@iabyn.com>
Mon, 28 Apr 2014 10:50:20 +0000 (11:50 +0100)
committerDavid Mitchell <davem@iabyn.com>
Mon, 28 Apr 2014 11:06:37 +0000 (12:06 +0100)
RT #121721.

A subroutine call like &foo; pushes a SUB context with the savearray field
unassigned, and with CxHASARGS() false. Most of the core knows not to use
this field without CxHASARGS() being true: except for Perl_cx_dup(),
which was still trying to dup it. This could lead to SEGVs on a fresh CX
stack, or possibly duping some other sub's @_ on a reused stack entry.

The fix is simple; don't dup this field unless CxHASARGS() is set.
Note that a similar test is already in place for the argarray field.

sv.c
t/op/fork.t

diff --git a/sv.c b/sv.c
index 087606b..85f91f1 100644 (file)
--- a/sv.c
+++ b/sv.c
@@ -12778,8 +12778,10 @@ Perl_cx_dup(pTHX_ PERL_CONTEXT *cxs, I32 ix, I32 max, CLONE_PARAMS* param)
                                           ? av_dup_inc(ncx->blk_sub.argarray,
                                                        param)
                                           : NULL);
-               ncx->blk_sub.savearray  = av_dup_inc(ncx->blk_sub.savearray,
-                                                    param);
+               ncx->blk_sub.savearray  =  (CxHASARGS(ncx)
+                                            ? av_dup_inc(ncx->blk_sub.savearray,
+                                                    param)
+                                          : NULL);
                ncx->blk_sub.oldcomppad = (PAD*)ptr_table_fetch(PL_ptr_table,
                                           ncx->blk_sub.oldcomppad);
                break;
index 0d93f5f..60c991b 100644 (file)
@@ -505,3 +505,17 @@ EXPECT
 2
 3
 4
+########
+# this used to SEGV. RT # 121721
+$|=1;
+&main;
+sub main {
+    if (my $pid = fork) {
+       waitpid($pid, 0);
+    }
+    else {
+        print "foo\n";
+    }
+}
+EXPECT
+foo