On Fri, Jun 17, 2005 at 12:00:07AM +0100, [EMAIL PROTECTED] wrote:
> Rafael Garcia-Suarez <[EMAIL PROTECTED]> wrote:
> :
> :Note that other kinds of similar code segfaults too :
> :
> :$ perl -e 'if($[=0){print}'
> :Segmentation fault
> :
> :I'd rather solve all those cases once and for all.
> 
> It sounds like the bug is in the optimiser: if it acts on C< $[ = 0 >
> at compile time, it should substitute the resulting value (C< 0 >),
> and leave it to other optimisations to refine that further if it is
> in void context, or leads to a constant conditional.

This patch should do that.  It also fixes this:

    % perl -wle '($_, $[) = (42);print "$_:$["'
    Use of uninitialized value in concatenation (.) or string at -e line 1.
    :42

by disallowing it.  It now gives:

    That use of $[ is unsupported at -e line 1.

-- 
Rick Delaney
[EMAIL PROTECTED]


diff -ruN perl-current/op.c perl-current-dev/op.c
--- perl-current/op.c   2005-06-16 06:15:46.000000000 -0400
+++ perl-current-dev/op.c       2005-06-17 22:00:03.000000000 -0400
@@ -3274,14 +3274,15 @@
        OP *curop;
 
        PL_modcount = 0;
-       PL_eval_start = right;  /* Grandfathering $[ assignment here.  Bletch.*/
+       /* Grandfathering $[ assignment here.  Bletch.*/
+       /* Only simple assignments like C<< ($[) = 1 >> are allowed */
+       PL_eval_start = (left->op_type == OP_CONST) ? right : 0;
        left = mod(left, OP_AASSIGN);
        if (PL_eval_start)
            PL_eval_start = 0;
-       else {
-           op_free(left);
-           op_free(right);
-           return Nullop;
+       else if (left->op_type == OP_CONST) {
+           /* Result of assignment is always 1 (or we'd be dead already) */
+           return newSVOP(OP_CONST, 0, newSViv(1));
        }
        /* optimise C<my @x = ()> to C<my @x>, and likewise for hashes */
        if ((left->op_type == OP_PADAV || left->op_type == OP_PADHV)
@@ -3418,8 +3419,7 @@
        if (PL_eval_start)
            PL_eval_start = 0;
        else {
-           op_free(o);
-           return Nullop;
+           o = newSVOP(OP_CONST, 0, newSViv(PL_compiling.cop_arybase));
        }
     }
     return o;
diff -ruN perl-current/t/comp/parser.t perl-current-dev/t/comp/parser.t
--- perl-current/t/comp/parser.t        2004-06-24 12:47:01.000000000 -0400
+++ perl-current-dev/t/comp/parser.t    2005-06-17 22:02:54.074228248 -0400
@@ -9,7 +9,7 @@
 }
 
 require "./test.pl";
-plan( tests => 47 );
+plan( tests => 54 );
 
 eval '[EMAIL PROTECTED];';
 like( $@, qr/^Can't modify hash dereference in repeat \(x\)/, '[EMAIL 
PROTECTED]' );
@@ -168,3 +168,25 @@
     eval q{ sub _ __FILE__ {} };
     like($@, qr/Illegal declaration of subroutine main::_/, "__FILE__ as 
prototype");
 }
+
+# [perl #36313] perl -e "1for$[=0" crash
+{
+    my $x;
+    $x = 1 for $[ = 0;
+    pass('optimized assignment to $[ used to segfault in scalar context');
+    if (($[) = 0) { $x = 1 }
+    pass('optimized assignment to $[ used to segfault in list context');
+    $x = ($[=2.4);
+    is($x, 2, 'scalar assignment to $[ behaves like other variables');
+    $x = (($[) = 0);
+    is($x, 1, 'list assignment to $[ behaves like other variables');
+    $x = eval q{ ($[, $x) = (0) };
+    like($@, qr/That use of \$\[ is unsupported/,
+             'cannot assign to $[ in a list');
+    eval q{ ($[, $x) = (0, 1) };
+    like($@, qr/That use of \$\[ is unsupported/,
+             'cannot assign list of >1 elements to $[');
+    eval q{ ($[, $x) = () };
+    like($@, qr/That use of \$\[ is unsupported/,
+             'cannot assign list of <1 elements to $[');
+}

Reply via email to