perl5 icon indicating copy to clipboard operation
perl5 copied to clipboard

null ptr deref -> Perl_cv_forget_slab (pad.c:500)

Open p5pRT opened this issue 9 years ago • 6 comments

Migrated from rt.perl.org#124385 (status was 'open')

Searchable as RT124385$

p5pRT avatar Apr 25 '15 01:04 p5pRT

From @geeknik

Built v5.21.12 (v5.21.11-10-ga8f582b) using the following command line​:

./Configure -des -Dusedevel -DDEBUGGING -Dcc=afl-gcc -Doptimize=-O2\ -g && AFL_HARDEN=1 make -j6 test-prep

Bug found with AFL (http​://lcamtuf.coredump.cx/afl)

Valgrind​: ==7327== Invalid read of size 8 ==7327== at 0x66546C​: Perl_cv_forget_slab (pad.c​:500) ==7327== by 0x48EFC3​: Perl_newPROG (op.c​:4093) ==7327== by 0x6612F1​: Perl_yyparse (perly.y​:120) ==7327== by 0x534740​: perl_parse (perl.c​:2296) ==7327== by 0x42AC97​: main (perlmain.c​:114) ==7327== Address 0x0 is not stack'd, malloc'd or (recently) free'd ==7327== ==7327== ==7327== Process terminating with default action of signal 11 (SIGSEGV) ==7327== Access not within mapped region at address 0x0 ==7327== at 0x66546C​: Perl_cv_forget_slab (pad.c​:500) ==7327== by 0x48EFC3​: Perl_newPROG (op.c​:4093) ==7327== by 0x6612F1​: Perl_yyparse (perly.y​:120) ==7327== by 0x534740​: perl_parse (perl.c​:2296) ==7327== by 0x42AC97​: main (perlmain.c​:114) ==7327== If you believe this happened as a result of a stack ==7327== overflow in your program's main thread (unlikely but ==7327== possible), you can try to increase the size of the ==7327== main thread stack using the --main-stacksize= flag. ==7327== The main thread stack size used in this run was 8388608. Segmentation fault

GDB​: Program received signal SIGSEGV, Segmentation fault. [----------------------------------registers-----------------------------------] RAX​: 0x0 RBX​: 0x11f2d50 --> 0x0 RCX​: 0xc4 RDX​: 0x0 RSI​: 0x11f2f00 (" at end of line\n") RDI​: 0x0 RBP​: 0x11f2d50 --> 0x0 RSP​: 0x7fffffffdee0 --> 0x11ef390 --> 0x11f2d50 --> 0x0 RIP​: 0x66546c (<Perl_cv_forget_slab+60>​: mov rdx,QWORD PTR [rdi]) R8 : 0x0 R9 : 0x11f2f40 --> 0x11f2d98 --> 0x11f2df8 --> 0x11f2d50 --> 0x0 R10​: 0x0 R11​: 0x2d ('-') R12​: 0xffffffff00000000 R13​: 0x11ef390 --> 0x11f2d50 --> 0x0 R14​: 0x67 ('g') R15​: 0x14 EFLAGS​: 0x10202 (carry parity adjust zero sign trap INTERRUPT direction overflow) [-------------------------------------code-------------------------------------]   0x66545c <Perl_cv_forget_slab+44>​: mov rdx,QWORD PTR [rsp]   0x665460 <Perl_cv_forget_slab+48>​: lea rsp,[rsp+0x98]   0x665468 <Perl_cv_forget_slab+56>​: sub rsp,0x18 => 0x66546c <Perl_cv_forget_slab+60>​: mov rdx,QWORD PTR [rdi]   0x66546f <Perl_cv_forget_slab+63>​: mov rax,QWORD PTR fs​:0x28   0x665478 <Perl_cv_forget_slab+72>​: mov QWORD PTR [rsp+0x8],rax   0x66547d <Perl_cv_forget_slab+77>​: xor eax,eax   0x66547f <Perl_cv_forget_slab+79>​: mov eax,DWORD PTR [rdx+0x5c] [------------------------------------stack-------------------------------------] 0000| 0x7fffffffdee0 --> 0x11ef390 --> 0x11f2d50 --> 0x0 0008| 0x7fffffffdee8 --> 0x67 ('g') 0016| 0x7fffffffdef0 --> 0x14 0024| 0x7fffffffdef8 --> 0x48efc4 (<Perl_newPROG+1604>​: test BYTE PTR [rip+0xd401dd],0x8 # 0x11cf1a8 <PL_perldb>) 0032| 0x7fffffffdf00 --> 0x304 0040| 0x7fffffffdf08 --> 0x1b60f849122f2000 0048| 0x7fffffffdf10 --> 0x0 0056| 0x7fffffffdf18 --> 0x11ef0a0 --> 0x0 [------------------------------------------------------------------------------] Legend​: code, data, rodata, value Stopped reason​: SIGSEGV Perl_cv_forget_slab () at pad.c​:500 500 const bool slabbed = !!CvSLABBED(cv); gdb-peda$ list 495 */ 496
497 void 498 Perl_cv_forget_slab(pTHX_ CV *cv) 499 { 500 const bool slabbed = !!CvSLABBED(cv); 501 OPSLAB *slab = NULL; 502
503 PERL_ARGS_ASSERT_CV_FORGET_SLAB; 504

System Info​: Debian 7, Kernel 3.2.65-1+deb7u2 x86_64, GCC 4.9.2, libc 2.13-38+deb7u8

p5pRT avatar Apr 25 '15 01:04 p5pRT

From @geeknik

test55-min

p5pRT avatar Apr 25 '15 01:04 p5pRT

From @hvds

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.

Hugo

p5pRT avatar Apr 26 '15 22:04 p5pRT

The RT System itself - Status changed from 'new' to 'open'

p5pRT avatar Apr 26 '15 22:04 p5pRT

From @iabyn

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"

p5pRT avatar May 05 '15 10:05 p5pRT

@iabyn can we close this or is still pending, it does not segv in 5.37.4

demerphq avatar Sep 08 '22 12:09 demerphq