develooper Front page | perl.perl5.porters | Postings from October 2013

[perl #119797] lvalue sub shows "Bizarre copy of ARRAY in block exit" in very specific case.

Thread Previous | Thread Next
From:
Father Chrysostomos via RT
Date:
October 23, 2013 13:08
Subject:
[perl #119797] lvalue sub shows "Bizarre copy of ARRAY in block exit" in very specific case.
Message ID:
rt-3.6.HEAD-26210-1382533703-1828.119797-15-0@perl.org
On Sun Sep 15 11:26:14 2013, sprout wrote:
> On Sun Sep 15 09:10:35 2013, jkeenan wrote:
> > On Sun Sep 15 07:10:48 2013, sprout wrote:
> > > #!perl
> > > my @this = ();
> > > 
> > > (that()) = ();
> > > print "@this\n";
> > > 
> > > sub that :lvalue { if (@this) { } else { @this; } }
> > > __END__
> > > 
> > > That gives me a bizarre copy.

The bug is worse than that.  The cases that do not get a bizarre copy do
not return assignable arrays, either:

use Test::More 'no_plan';
sub if119797 : lvalue {
    if ($_[0]) {
	@119797
    }
}
eval { (if119797(1)) = 4..6 };
is $@, "", '$@ after writing to array returned by if';
is "@119797", "4 5 6", 'writing to array returned by if';

Output:

ok 1 - $@ after writing to array returned by if
not ok 2 - writing to array returned by if
#   Failed test 'writing to array returned by if'
#   at - line 9.
#          got: ''
#     expected: '4 5 6'
1..2
# Looks like you failed 1 test of 2.

> > 
> > 
> > Okay.  So now we should ask:  How significant is this bug?
> 
> It’s low priority, as the workaround (explicit return) is simple.
> 
> > What can we
> > do to fix it?
> 
> I suspect skipping the leave op when followed by leavesublv would work.
>  In fact, skipping it for any sub (not just lvalue) would probably make
> implicit return faster in general.
> 
> That would entail nulling it (via op_null(...)) in S_finalize_op in op.c.
> 
> (That’s without looking at the code, so it could be all wrong.)

It is wrong.  leavesub and leavesublv don’t pop scopes back to the
subroutine the way return does, so the op_leave preceding it is not
optional.

The problem here has also to do with op trees not getting flagged properly:

$ ./perl -Ilib -MO=Concise,if119797 -e 'sub if119797 : lvalue { if
($_[0]) { @119797 } }'
main::if119797:
6  <1> leavesublv[1 ref] K/REFC,1 ->(end)
-     <@> lineseq KP ->6
1        <;> nextstate(main 3 -e:1) v ->2
-        <1> null K/1 ->-
3           <|> and(other->4) K/1 ->6
-              <1> ex-aelem sK/2 ->3
-                 <1> ex-rv2av sKR/1 ->-
2                    <$> aelemfast(*_) s ->3
-                 <0> ex-const s ->-
-              <@> scope K ->-
-                 <0> ex-nextstate v ->4
5                 <1> rv2av[t1] K/1 ->6
4                    <$> gv(*119797) s ->5
-e syntax OK

Notice that the rv2av has no M indicating modifiable context.

And then S_adjust_stack_on_leave in pp_ctl.c probably also needs adjustment.

-- 

Father Chrysostomos


---
via perlbug:  queue: perl5 status: open
https://rt.perl.org:443/rt3/Ticket/Display.html?id=119797

Thread Previous | Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About