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

Re: [perl #72406] Segmentation fault v5.10.1

Thread Previous | Thread Next
From:
Brian Fraser
Date:
December 15, 2013 08:11
Subject:
Re: [perl #72406] Segmentation fault v5.10.1
Message ID:
CA+nL+naDn81wsBJyFiC6G8aywVJp5E8n0oUtCmqRrd0aBcZhNg@mail.gmail.com
On Sun, Dec 15, 2013 at 3:39 AM, Father Chrysostomos <sprout@cpan.org>wrote:

> 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
>

Mildly off topic but, Father C, you're an evil genius. Bravo :)

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