develooper Front page | perl.perl5.porters | Postings from May 2015

Re: [perl #124385] null ptr deref -> Perl_cv_forget_slab (pad.c:500)

Thread Previous | Thread Next
From:
Dave Mitchell
Date:
May 5, 2015 10:27
Subject:
Re: [perl #124385] null ptr deref -> Perl_cv_forget_slab (pad.c:500)
Message ID:
20150505102743.GO4035@iabyn.com
On Sun, Apr 26, 2015 at 03:16:36PM -0700, Hugo van der Sanden via RT wrote:
> On Fri Apr 24 18:11:27 2015, brian.carpenter@gmail.com wrote:
> > 0;qq{@{sub{]]}}}}}
> 
> Bisecting with:
> 
>   Porting/bisect.pl --target=miniperl --crash -- ./miniperl -ce '0;qq{@{sub{]]}}}}}'
> 
> finds this:
> 
> commit 9ffcdca1f504cb09088413c074b35af4b7f247e3
> Author: Father Chrysostomos <sprout@cpan.org>
> Date:   Mon Nov 12 23:04:16 2012 -0800
> 
>     Don’t leak subs containing syntax errors
>     
>     I fixed this for BEGIN blocks earlier, but missed the fact that
>     all subs are affected.
>     
>     When called without an o argument (from newANONATTRSUB), newATTRSUB
>     is expected to return a CV with an unowned reference count of which
>     the caller will take ownership.  We cannot have newATTRSUB returning
>     a freed CV, so we have it return null instead.  But that means
>     ck_anoncode and pm_runtime have to account for that.

The following should be enough to remove this tikcet as a 5.22 blocker.

commit de0885da327045eed274d7f8913a58e6de0e0f30
Author:     David Mitchell <davem@iabyn.com>
AuthorDate: Tue May 5 10:44:16 2015 +0100
Commit:     David Mitchell <davem@iabyn.com>
CommitDate: Tue May 5 11:23:36 2015 +0100

    null ptr deref in Perl_cv_forget_slab
    
    RT #124385
    
    Parsing following a syntax error could result in a null ptr dereference.
    
    This commit contains a band-aid that returns from Perl_cv_forget_slab() if
    the cv arg is null; but the real issue is much deeper and needs a more
    general fix at some point.
    
    Basically, both the lexer and the parser use the save stack, and after an
    error, they can get out of sync.
    
    In particular:
    
    1) when handling a double-quoted string, the lexer does an ENTER, saves
    most of its current state on the save stack, then uses the literal string
    as the toke source. When it reaches the end of the string, it LEAVEs,
    restores the lexer state and continues with the main source.
    
    2) Whenever the parser starts a new block or sub scope, it remembers the
    current save stack position, and at end of scope, pops the save stack back
    to that position.
    
    In something like
    
        "@{ sub {]}}  }}}"
    
    the lexer sees a double-quoted string, and saves the current lex state.
    The parser sees the start of a sub, and saves PL_compcv etc. Then a parse
    error occurs. The parser goes into error recovery, discarding tokens until
    it can return to a sane state. The lexer runs out of tokens when toking
    the string, does a LEAVE, and switches back to toking the main source.
    This LEAVE restores both the lexer's and the parser's state; in particular
    the parser gets its old PL_compcv restored, even though the parser hasn't
    finished compiling the current sub. Later, series of '}' tokens coming
    through allows the parser to finish the sub. Since PL_error_count > 0, it
    discards the just-compiled sub and sets PL_compcv to null. Normally the
    LEAVE_SCOPE done just after this would restore PL_compcv to its old value
    (e.g. PL_main_cv) but the stack has already been popped, so PL_compcv gets
    left null, and SEGVs occur.
    
    The two main ways I can think of fixing this in the long term are
    1) avoid the lexer using the save stack for long-term state storage;
    in particular, make S_sublex_push() malloc a new parser object rather
    than saving the current lexer state on the save stack.
    2) At the end of a sublex, if PL_error_count > 0, don't try to restore
    state and continue, instead just croak.
    
    N.B. the test that this commit adds to lex.t doesn't actually trigger the
    SEGV, since the bad code is wrapped in an eval which (for reasons I
    haven't researched) avoids the SEGV.


-- 
But Pity stayed his hand. "It's a pity I've run out of bullets",
he thought. -- "Bored of the Rings"

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