perl5
perl5 copied to clipboard
null ptr deref -> Perl_cv_forget_slab (pad.c:500)
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
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
The RT System itself - Status changed from 'new' to 'open'
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"
@iabyn can we close this or is still pending, it does not segv in 5.37.4