Front page | perl.perl5.porters |
Postings from December 2013
Re: [perl #72406] Segmentation fault v5.10.1
Thread Next
From:
Father Chrysostomos
Date:
December 15, 2013 06:39
Subject:
Re: [perl #72406] Segmentation fault v5.10.1
Message ID:
20131215063938.1432.qmail@lists-nntp.develooper.com
I wrote:
> This line, which back then (I checked 8350df422c) was 4905, but is now
> (4cb2d3f84a) 6493,
>
> o->op_next = ((LOGOP*)cUNOPo->op_first)->op_other;
>
> tries to read the op_other field of a const op.
"foo while bar" and "foo until bar" make their way through newLOOPOP,
which then usually calls S_new_logop, to create and AND or OR op with
special pointers that turn it into a loop.
Because S_new_logop knows about folding "$x if 1" down to a simple $x,
and because "do{foo()} while 0" should still execute the do block,
newLOOPOP skips the call to S_new_logop in that case.
Hence, it assumes that if it has seen a do block on its lhs, then
S_new_logop must return an AND or OR op.
"foo until bar" is actually changed early on to "foo while !bar",
before it reaches newLOOPOP. Constant folding usually folds !0 down
to a simple 1 (actually &PL_sv_yes), so newLOOPOP sees "foo while 0".
If constant folding fails (e.g., because the parser has seen an
unmatched } and constant folding is skipped after such errors), then
newLOOPOP will see the unfolded !1.
S_new_logop has a special optimisation that changes "!foo && bar" to
"foo || bar", etc.
That optimisation allows it to "see through" the unoptimised !1 (a NOT
with a CONST kid) and get to the constant, folding the resulting op
and returning something that newLOOPOP is not expecting to be folded.
In the case of 'do{print("foobar");}until(1)}', it optimises the do
block away, which is wrong.
So newLOOPOP reads past the end of the op.
I can trigger this condition by defeating constant folding some
other way. Croaking in boolean overloading, but just the first time,
will do that:
{ package o; use overload bool => sub { die unless $::ok++; return 1 } }
use constant OK => bless [], o::;
do{print("foobar");}until OK;
__END__
Bus error: 10
So, yes, we definitely still have a bug here. :-)
And I suspect it is a regression, too.
Thread Next