Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

null ptr deref -> Perl_ck_shift (op.c:10857) #14739

Closed
p5pRT opened this issue Jun 7, 2015 · 31 comments
Closed

null ptr deref -> Perl_ck_shift (op.c:10857) #14739

p5pRT opened this issue Jun 7, 2015 · 31 comments

Comments

@p5pRT
Copy link

p5pRT commented Jun 7, 2015

Migrated from rt.perl.org#125351 (status was 'resolved')

Searchable as RT125351$

@p5pRT
Copy link
Author

p5pRT commented Jun 7, 2015

From @geeknik

The attached "script" causes a null ptr deref and seg fault in Perl v5.23.0 (v5.22.0-63-g216b41c)​:

Program received signal SIGSEGV, Segmentation fault.
0x000000000049a777 in Perl_ck_shift () at op.c​:10857
10857 if (!CvUNIQUE(PL_compcv)) {
(gdb) bt
#0 0x000000000049a777 in Perl_ck_shift () at op.c​:10857
#1 0x000000000065f233 in Perl_yyparse ()
#2 0x0000000000534d79 in perl_parse ()
#3 0x000000000042ac38 in main () at perlmain.c​:114
(gdb) i r
rax 0x0 0
rbx 0x11e1fb0 18751408
rcx 0x0 0
rdx 0x0 0
rsi 0xa5 165
rdi 0x11e1fb0 18751408
rbp 0xa5 0xa5
rsp 0x7fffffffdf20 0x7fffffffdf20
r8 0xac1580 11277696
r9 0x0 0
r10 0x0 0
r11 0x27 39
r12 0xc6 198
r13 0x11f04f0 18810096
r14 0x27 39
r15 0xef5a0f 15686159
rip 0x49a777 0x49a777 <Perl_ck_shift+167>
eflags 0x10246 [ PF ZF IF RF ]
cs 0x33 51
ss 0x2b 43
ds 0x0 0
es 0x0 0
fs 0x0 0
gs 0x0 0

==51781== Invalid read of size 8
==51781== at 0x49A777​: Perl_ck_shift (op.c​:10857)
==51781== by 0x65F232​: Perl_yyparse (perly.y​:996)
==51781== by 0x534D78​: perl_parse (perl.c​:2296)
==51781== by 0x42AC37​: main (perlmain.c​:114)
==51781== Address 0x0 is not stack'd, malloc'd or (recently) free'd
==51781==
==51781==
==51781== Process terminating with default action of signal 11 (SIGSEGV)
==51781== Access not within mapped region at address 0x0
==51781== at 0x49A777​: Perl_ck_shift (op.c​:10857)
==51781== by 0x65F232​: Perl_yyparse (perly.y​:996)
==51781== by 0x534D78​: perl_parse (perl.c​:2296)
==51781== by 0x42AC37​: main (perlmain.c​:114)
==51781== If you believe this happened as a result of a stack
==51781== overflow in your program's main thread (unlikely but
==51781== possible), you can try to increase the size of the
==51781== main thread stack using the --main-stacksize= flag.
==51781== The main thread stack size used in this run was 8388608.
Segmentation fault

It also causes a null ptr deref and seg fault in Perl v5.21.7 (v5.21.6-602-ge9d2bd8), albeit in a different location and file​:

Program received signal SIGSEGV, Segmentation fault.
S_pad_findlex (namepv=namepv@​entry=0x7fffffffdb30 "&shift", namelen=namelen@​entry=6, flags=flags@​entry=0, cv=0x0, seq=4, Perl_warn=Perl_warn@​entry=1,
  out_capture=out_capture@​entry=0x0, out_name=out_name@​entry=0x7fffffffd8f0, out_flags=out_flags@​entry=0x7fffffffd8e0) at pad.c​:1141
1141 pad.c​: No such file or directory.
(gdb) bt
#0 S_pad_findlex (namepv=namepv@​entry=0x7fffffffdb30 "&shift", namelen=namelen@​entry=6, flags=flags@​entry=0, cv=0x0, seq=4,
  Perl_warn=Perl_warn@​entry=1, out_capture=out_capture@​entry=0x0, out_name=out_name@​entry=0x7fffffffd8f0, out_flags=out_flags@​entry=0x7fffffffd8e0)
  at pad.c​:1141
#1 0x00000000005e217d in Perl_pad_findmy_pvn (namepv=0x7fffffffdb30 "&shift", namelen=6, flags=<optimized out>) at pad.c​:962
#2 0x0000000000579950 in Perl_yylex () at toke.c​:6430
#3 0x00000000005c60b5 in Perl_yyparse (gramtype=<optimized out>) at perly.c​:322
#4 0x00000000004f0875 in S_parse_body (xsinit=0x42ac70 <xs_init>, env=0x0) at perl.c​:2271
#5 perl_parse (my_perl=<optimized out>, xsinit=0x42ac70 <xs_init>, argc=<optimized out>, argv=<optimized out>, env=0x0) at perl.c​:1605
#6 0x000000000042a87c in main (argc=2, argv=0x7fffffffe3a8, env=0x7fffffffe3c0) at perlmain.c​:114
#7 0x00007ffff6f98ead in __libc_start_main (main=<optimized out>, argc=<optimized out>, ubp_av=<optimized out>, init=<optimized out>,
  fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fffffffe398) at libc-start.c​:244
#8 0x000000000042ab95 in _start ()
(gdb) i r
rax 0x7fffffffd8e0 140737488345312
rbx 0x0 0
rcx 0x0 0
rdx 0x0 0
rsi 0x0 0
rdi 0x7fffffffdb30 140737488345904
rbp 0x6 0x6
rsp 0x7fffffffd7f0 0x7fffffffd7f0
r8 0x4 4
r9 0x1 1
r10 0x5 5
r11 0x7ffff70cf4f0 140737338209520
r12 0x7fffffffdb31 140737488345905
r13 0x0 0
r14 0x6 6
r15 0xe42065 14950501
rip 0x5dea2f 0x5dea2f <S_pad_findlex+55>
eflags 0x10246 [ PF ZF IF RF ]
cs 0x33 51
ss 0x2b 43
ds 0x0 0
es 0x0 0
fs 0x0 0
gs 0x0 0

==12210== Invalid read of size 8
==12210== at 0x5DEA2F​: S_pad_findlex (pad.c​:1141)
==12210== by 0x5E217C​: Perl_pad_findmy_pvn (pad.c​:962)
==12210== by 0x57994F​: Perl_yylex (toke.c​:6430)
==12210== by 0x5C60B4​: Perl_yyparse (perly.c​:322)
==12210== by 0x4F0874​: perl_parse (perl.c​:2271)
==12210== by 0x42A87B​: main (perlmain.c​:114)
==12210== Address 0x0 is not stack'd, malloc'd or (recently) free'd
==12210==
==12210==
==12210== Process terminating with default action of signal 11 (SIGSEGV)
==12210== Access not within mapped region at address 0x0
==12210== at 0x5DEA2F​: S_pad_findlex (pad.c​:1141)
==12210== by 0x5E217C​: Perl_pad_findmy_pvn (pad.c​:962)
==12210== by 0x57994F​: Perl_yylex (toke.c​:6430)
==12210== by 0x5C60B4​: Perl_yyparse (perly.c​:322)
==12210== by 0x4F0874​: perl_parse (perl.c​:2271)
==12210== by 0x42A87B​: main (perlmain.c​:114)
==12210== If you believe this happened as a result of a stack
==12210== overflow in your program's main thread (unlikely but
==12210== possible), you can try to increase the size of the
==12210== main thread stack using the --main-stacksize= flag.
==12210== The main thread stack size used in this run was 8388608.
Segmentation fault

This bug was found with AFL (http​://lcamtuf.coredump.cx/afl/).

@p5pRT
Copy link
Author

p5pRT commented Jun 7, 2015

From @geeknik

test555-min

@p5pRT
Copy link
Author

p5pRT commented Jun 10, 2015

From @tonycoz

On Sun Jun 07 12​:36​:52 2015, brian.carpenter@​gmail.com wrote​:

The attached "script" causes a null ptr deref and seg fault in Perl
v5.23.0 (v5.22.0-63-g216b41c)​:

Program received signal SIGSEGV, Segmentation fault.
0x000000000049a777 in Perl_ck_shift () at op.c​:10857
10857 if (!CvUNIQUE(PL_compcv)) {
(gdb) bt
#0 0x000000000049a777 in Perl_ck_shift () at op.c​:10857
#1 0x000000000065f233 in Perl_yyparse ()
#2 0x0000000000534d79 in perl_parse ()
#3 0x000000000042ac38 in main () at perlmain.c​:114

This looks like it has the same base cause as 124187.

Tony

@p5pRT
Copy link
Author

p5pRT commented Jun 10, 2015

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

@p5pRT
Copy link
Author

p5pRT commented Aug 31, 2015

From @geeknik

FYI, this issue is still present in v5.23.1-213-g4b06b8d.

On Tue Jun 09 22​:52​:01 2015, tonyc wrote​:

This looks like it has the same base cause as 124187.

Tony

@p5pRT
Copy link
Author

p5pRT commented Sep 26, 2015

From @geeknik

perl -e 'qq{@​{sub{]]}}}}-shift'

triggers a null ptr deref and segfault in perl v5.21.7 (v5.21.6-602-ge9d2bd8).

S_pad_findlex (namepv=namepv@​entry=0x7fffffffdb30 "&shift", namelen=namelen@​entry=6,
  flags=flags@​entry=0, cv=0x0, seq=4, Perl_warn=Perl_warn@​entry=1,
  out_capture=out_capture@​entry=0x0, out_name=out_name@​entry=0x7fffffffd8f0,
  out_flags=out_flags@​entry=0x7fffffffd8e0) at pad.c​:1141
1141 pad.c​: No such file or directory.
(gdb) bt
#0 S_pad_findlex (namepv=namepv@​entry=0x7fffffffdb30 "&shift", namelen=namelen@​entry=6,
  flags=flags@​entry=0, cv=0x0, seq=4, Perl_warn=Perl_warn@​entry=1,
  out_capture=out_capture@​entry=0x0, out_name=out_name@​entry=0x7fffffffd8f0,
  out_flags=out_flags@​entry=0x7fffffffd8e0) at pad.c​:1141
#1 0x00000000005e217d in Perl_pad_findmy_pvn (namepv=0x7fffffffdb30 "&shift", namelen=6,
  flags=<optimized out>) at pad.c​:962
#2 0x0000000000579950 in Perl_yylex () at toke.c​:6430
#3 0x00000000005c60b5 in Perl_yyparse (gramtype=<optimized out>) at perly.c​:322
#4 0x00000000004f0875 in S_parse_body (xsinit=0x42ac70 <xs_init>, env=0x0) at perl.c​:2271
#5 perl_parse (my_perl=<optimized out>, xsinit=0x42ac70 <xs_init>, argc=<optimized out>,
  argv=<optimized out>, env=0x0) at perl.c​:1605
#6 0x000000000042a87c in main (argc=2, argv=0x7fffffffe3a8, env=0x7fffffffe3c0)
  at perlmain.c​:114
#7 0x00007ffff6f98ead in __libc_start_main (main=<optimized out>, argc=<optimized out>,
  ubp_av=<optimized out>, init=<optimized out>, fini=<optimized out>,
  rtld_fini=<optimized out>, stack_end=0x7fffffffe398) at libc-start.c​:244
#8 0x000000000042ab95 in _start ()

==46065== Invalid read of size 8
==46065== at 0x5DEA2F​: S_pad_findlex (pad.c​:1141)
==46065== by 0x5E217C​: Perl_pad_findmy_pvn (pad.c​:962)
==46065== by 0x57994F​: Perl_yylex (toke.c​:6430)
==46065== by 0x5C60B4​: Perl_yyparse (perly.c​:322)
==46065== by 0x4F0874​: S_parse_body (perl.c​:2271)
==46065== by 0x4F0874​: perl_parse (perl.c​:1605)
==46065== by 0x42A87B​: main (perlmain.c​:114)
==46065== Address 0x0 is not stack'd, malloc'd or (recently) free'd
==46065== Process terminating with default action of signal 11 (SIGSEGV)
==46065== Access not within mapped region at address 0x0
==46065== at 0x5DEA2F​: S_pad_findlex (pad.c​:1141)
==46065== by 0x5E217C​: Perl_pad_findmy_pvn (pad.c​:962)
==46065== by 0x57994F​: Perl_yylex (toke.c​:6430)
==46065== by 0x5C60B4​: Perl_yyparse (perly.c​:322)
==46065== by 0x4F0874​: S_parse_body (perl.c​:2271)
==46065== by 0x4F0874​: perl_parse (perl.c​:1605)
==46065== by 0x42A87B​: main (perlmain.c​:114)

This same script also triggers a completely different null ptr deref and segfault in perl v5.23.4 (v5.23.3-7-ge120c24)​:

0x00000000004a07c7 in Perl_ck_shift () at op.c​:10710
10710 if (!CvUNIQUE(PL_compcv)) {
(gdb) bt
#0 0x00000000004a07c7 in Perl_ck_shift () at op.c​:10710
#1 0x000000000066df23 in Perl_yyparse ()
#2 0x000000000053c005 in S_parse_body () at perl.c​:2304
#3 0x0000000000543d83 in perl_parse () at perl.c​:1634
#4 0x000000000042c6f8 in main () at perlmain.c​:114

==24849== Invalid read of size 8
==24849== at 0x4A07C7​: Perl_ck_shift (op.c​:10710)
==24849== by 0x66DF22​: Perl_yyparse (perly.y​:996)
==24849== by 0x53C004​: S_parse_body (perl.c​:2304)
==24849== by 0x543D82​: perl_parse (perl.c​:1634)
==24849== by 0x42C6F7​: main (perlmain.c​:114)
==24849== Address 0x0 is not stack'd, malloc'd or (recently) free'd
==24849== Process terminating with default action of signal 11 (SIGSEGV)
==24849== Access not within mapped region at address 0x0
==24849== at 0x4A07C7​: Perl_ck_shift (op.c​:10710)
==24849== by 0x66DF22​: Perl_yyparse (perly.y​:996)
==24849== by 0x53C004​: S_parse_body (perl.c​:2304)
==24849== by 0x543D82​: perl_parse (perl.c​:1634)
==24849== by 0x42C6F7​: main (perlmain.c​:114)

@p5pRT
Copy link
Author

p5pRT commented Jan 17, 2016

From @geeknik

This issue is still present in v5.23.7 (v5.23.6-109-g388b516).

@p5pRT
Copy link
Author

p5pRT commented Jan 17, 2016

From [Unknown Contact. See original ticket]

This issue is still present in v5.23.7 (v5.23.6-109-g388b516).

@p5pRT
Copy link
Author

p5pRT commented Aug 19, 2016

From @geeknik

From v5.25.4 (v5.25.3-305-g8c6b0c7)​:

./perl -e 'qq{@​{sub{q}}]]}};s0{shift'

ASAN​:SIGSEGV

==31752==ERROR​: AddressSanitizer​: SEGV on unknown address 0x000000000000 (pc 0x00000055ff13 bp 0x7ffda0f99310 sp 0x7ffda0f99110 T0)
  #0 0x55ff12 in Perl_ck_shift /root/perl/op.c​:10881​:7
  #1 0x6b5f8c in Perl_yyparse /root/perl/perly.y​:1166​:23
  #2 0x59c4a1 in S_parse_body /root/perl/perl.c​:2372​:9
  #3 0x59283c in perl_parse /root/perl/perl.c​:1688​:2
  #4 0x4de835 in main /root/perl/perlmain.c​:121​:18
  #5 0x7f34f1834b44 in __libc_start_main /build/glibc-uPj9cH/glibc-2.19/csu/libc-start.c​:287
  #6 0x4de4cc in _start (/root/perl/perl+0x4de4cc)

AddressSanitizer can not provide additional info.
SUMMARY​: AddressSanitizer​: SEGV /root/perl/op.c​:10881 Perl_ck_shift
==31752==ABORTING

@p5pRT
Copy link
Author

p5pRT commented Aug 19, 2016

From [Unknown Contact. See original ticket]

From v5.25.4 (v5.25.3-305-g8c6b0c7)​:

./perl -e 'qq{@​{sub{q}}]]}};s0{shift'

ASAN​:SIGSEGV

==31752==ERROR​: AddressSanitizer​: SEGV on unknown address 0x000000000000 (pc 0x00000055ff13 bp 0x7ffda0f99310 sp 0x7ffda0f99110 T0)
  #0 0x55ff12 in Perl_ck_shift /root/perl/op.c​:10881​:7
  #1 0x6b5f8c in Perl_yyparse /root/perl/perly.y​:1166​:23
  #2 0x59c4a1 in S_parse_body /root/perl/perl.c​:2372​:9
  #3 0x59283c in perl_parse /root/perl/perl.c​:1688​:2
  #4 0x4de835 in main /root/perl/perlmain.c​:121​:18
  #5 0x7f34f1834b44 in __libc_start_main /build/glibc-uPj9cH/glibc-2.19/csu/libc-start.c​:287
  #6 0x4de4cc in _start (/root/perl/perl+0x4de4cc)

AddressSanitizer can not provide additional info.
SUMMARY​: AddressSanitizer​: SEGV /root/perl/op.c​:10881 Perl_ck_shift
==31752==ABORTING

@p5pRT
Copy link
Author

p5pRT commented Sep 15, 2016

From @geeknik

On Fri Sep 25 19​:47​:03 2015, brian.carpenter@​gmail.com wrote​:

perl -e 'qq{@​{sub{]]}}}}-shift'

v5.25.5 (v5.25.4-110-g95c0a76)

==9144==ERROR​: AddressSanitizer​: SEGV on unknown address 0x000000000000 (pc 0x00000055fdf3 bp 0x7ffcd79efc10 sp 0x7ffcd79efa30 T0)
  #0 0x55fdf2 in Perl_ck_shift /root/perl/op.c​:10914​:7
  #1 0x6b6d05 in Perl_yyparse /root/perl/perly.y​:1162​:23
  #2 0x59c451 in S_parse_body /root/perl/perl.c​:2373​:9
  #3 0x5927fc in perl_parse /root/perl/perl.c​:1689​:2
  #4 0x4de5d5 in main /root/perl/perlmain.c​:121​:18
  #5 0x7f43e8cb8b44 in __libc_start_main /build/glibc-uPj9cH/glibc-2.19/csu/libc-start.c​:287
  #6 0x4de26c in _start (/root/perl/perl+0x4de26c)

AddressSanitizer can not provide additional info.
SUMMARY​: AddressSanitizer​: SEGV /root/perl/op.c​:10914 Perl_ck_shift
==9144==ABORTING

@p5pRT
Copy link
Author

p5pRT commented Sep 15, 2016

From [Unknown Contact. See original ticket]

On Fri Sep 25 19​:47​:03 2015, brian.carpenter@​gmail.com wrote​:

perl -e 'qq{@​{sub{]]}}}}-shift'

v5.25.5 (v5.25.4-110-g95c0a76)

==9144==ERROR​: AddressSanitizer​: SEGV on unknown address 0x000000000000 (pc 0x00000055fdf3 bp 0x7ffcd79efc10 sp 0x7ffcd79efa30 T0)
  #0 0x55fdf2 in Perl_ck_shift /root/perl/op.c​:10914​:7
  #1 0x6b6d05 in Perl_yyparse /root/perl/perly.y​:1162​:23
  #2 0x59c451 in S_parse_body /root/perl/perl.c​:2373​:9
  #3 0x5927fc in perl_parse /root/perl/perl.c​:1689​:2
  #4 0x4de5d5 in main /root/perl/perlmain.c​:121​:18
  #5 0x7f43e8cb8b44 in __libc_start_main /build/glibc-uPj9cH/glibc-2.19/csu/libc-start.c​:287
  #6 0x4de26c in _start (/root/perl/perl+0x4de26c)

AddressSanitizer can not provide additional info.
SUMMARY​: AddressSanitizer​: SEGV /root/perl/op.c​:10914 Perl_ck_shift
==9144==ABORTING

@p5pRT
Copy link
Author

p5pRT commented Oct 14, 2016

From @geeknik

perl -e 'qq{@​{sub{]]}}}}*shift' triggers this crash in v5.25.6 (v5.25.5-104-gaff2be5).

@p5pRT
Copy link
Author

p5pRT commented Feb 7, 2017

From @hvds

The original case is still crashing as before​:
% ./miniperl -e 'qq{@​{sub{]]}}}};shift'
Segmentation fault (core dumped)
%
.. due to a NULL PL_compcv set by Perl_newATTRSUB_x() (since Father C's 9ffcdca) and hit in Perl_ck_shift().

It seems clear that as mooted this is essentially the same underlying issue as [perl #124187], but that one has been resolved so they should not be merged.

I'll copy Dave's commit message from there, since it will be more useful here for the future (particularly the bit about PL_compcv)​:

commit de0885d
Author​: David Mitchell <davem@​iabyn.com>
Date​: Tue May 5 10​:44​:16 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.

@p5pRT
Copy link
Author

p5pRT commented Feb 7, 2017

From @hvds

This looks to be the same as [perl #125351], I'll merge them.

Hugo

@p5pRT
Copy link
Author

p5pRT commented Feb 7, 2017

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

@p5pRT
Copy link
Author

p5pRT commented Mar 31, 2017

From zefram@fysh.org

Looks to be the same mechanism as [perl #126191].

-zefram

@p5pRT
Copy link
Author

p5pRT commented Dec 21, 2017

From sraums2498@gmail.com

=================================================================
==114384==ERROR​: AddressSanitizer​: heap-buffer-overflow on address 0x60300000e8e0 at pc 0x000000f14a34 bp 0x7fff4e9807b0 sp 0x7fff4e9807a0
READ of size 8 at 0x60300000e8e0 thread T0
  #0 0xf14a33 in Perl_cv_undef_flags /home/asan_perl/Documents/perl-5.26.1/pad.c​:397
  #1 0x1cc91a1 in Perl_sv_clear /home/asan_perl/Documents/perl-5.26.1/sv.c​:6623
  #2 0x1ca0107 in Perl_sv_free2 /home/asan_perl/Documents/perl-5.26.1/sv.c​:7073
  #3 0x8de987 in S_SvREFCNT_dec /home/asan_perl/Documents/perl-5.26.1/inline.h​:189
  #4 0x8de987 in perl_destruct /home/asan_perl/Documents/perl-5.26.1/perl.c​:840
  #5 0x46b5fb in main /home/asan_perl/Documents/perl-5.26.1/perlmain.c​:134
  #6 0x7fd03655782f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)
  #7 0x46c888 in _start (/home/asan_perl/Documents/perl-5.26.1/perl+0x46c888)

0x60300000e8e0 is located 0 bytes to the right of 32-byte region [0x60300000e8c0,0x60300000e8e0)
allocated by thread T0 here​:
  #0 0x7fd0372fb602 in malloc (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x98602)
  #1 0x167dd81 in Perl_safesysmalloc /home/asan_perl/Documents/perl-5.26.1/util.c​:153
  #2 0x1adf2d0 in Perl_av_extend_guts /home/asan_perl/Documents/perl-5.26.1/av.c​:186
  #3 0x1aed221 in Perl_av_extend /home/asan_perl/Documents/perl-5.26.1/av.c​:80
  #4 0x1aed221 in Perl_av_store /home/asan_perl/Documents/perl-5.26.1/av.c​:355
  #5 0xf248f4 in Perl_pad_new /home/asan_perl/Documents/perl-5.26.1/pad.c​:231
  #6 0x905842 in S_parse_body /home/asan_perl/Documents/perl-5.26.1/perl.c​:2272
  #7 0x905842 in perl_parse /home/asan_perl/Documents/perl-5.26.1/perl.c​:1692
  #8 0x46b239 in main /home/asan_perl/Documents/perl-5.26.1/perlmain.c​:121
  #9 0x7fd03655782f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)

SUMMARY​: AddressSanitizer​: heap-buffer-overflow /home/asan_perl/Documents/perl-5.26.1/pad.c​:397 Perl_cv_undef_flags
Shadow bytes around the buggy address​:
  0x0c067fff9cc0​: 02 fa fa fa 00 00 00 00 fa fa 00 00 00 00 fa fa
  0x0c067fff9cd0​: 00 00 00 00 fa fa fd fd fd fd fa fa 00 00 00 00
  0x0c067fff9ce0​: fa fa fd fd fd fd fa fa 00 00 00 00 fa fa fd fd
  0x0c067fff9cf0​: fd fd fa fa 00 00 00 00 fa fa 00 00 00 00 fa fa
  0x0c067fff9d00​: fd fd fd fd fa fa fd fd fd fd fa fa 00 00 00 00
=>0x0c067fff9d10​: fa fa 00 00 00 00 fa fa 00 00 00 00[fa]fa 00 00
  0x0c067fff9d20​: 00 fa fa fa 00 00 00 00 fa fa 00 00 00 00 fa fa
  0x0c067fff9d30​: 00 00 00 05 fa fa 00 00 00 00 fa fa fd fd fd fd
  0x0c067fff9d40​: fa fa 00 00 07 fa fa fa 00 00 03 fa fa fa 00 00
  0x0c067fff9d50​: 00 02 fa fa 00 00 00 07 fa fa 00 00 03 fa fa fa
  0x0c067fff9d60​: 00 00 00 00 fa fa 00 00 02 fa fa fa 00 00 00 02
Shadow byte legend (one shadow byte represents 8 application bytes)​:
  Addressable​: 00
  Partially addressable​: 01 02 03 04 05 06 07
  Heap left redzone​: fa
  Heap right redzone​: fb
  Freed heap region​: fd
  Stack left redzone​: f1
  Stack mid redzone​: f2
  Stack right redzone​: f3
  Stack partial redzone​: f4
  Stack after return​: f5
  Stack use after scope​: f8
  Global redzone​: f9
  Global init order​: f6
  Poisoned by user​: f7
  Container overflow​: fc
  Array cookie​: ac
  Intra object redzone​: bb
  ASan internal​: fe
==114384==ABORTING

--
Regards,
SRAUMS

@p5pRT
Copy link
Author

p5pRT commented Dec 21, 2017

From sraums2498@gmail.com

89

@p5pRT
Copy link
Author

p5pRT commented Jan 9, 2018

From @hvds

This appears similar to rt131836, but is not fixed by its fix. It reduces at least to​:
  ./miniperl -e 's//${sub{b{]]]{}#$/ sub{}'
with the same stack trace.

I'll come back to this after completing triage on the current batch of new tickets if nobody else gets to it, but I anticipate it'll need more knowledge of the lex/parse phase than I can bring to bear.

Hugo

@p5pRT
Copy link
Author

p5pRT commented Jan 9, 2018

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

@p5pRT
Copy link
Author

p5pRT commented Jan 18, 2018

From @tonycoz

On Mon, 08 Jan 2018 16​:41​:35 -0800, hv wrote​:

This appears similar to rt131836, but is not fixed by its fix. It
reduces at least to​:
./miniperl -e 's//${sub{b{]]]{}#$/ sub{}'
with the same stack trace.

I'll come back to this after completing triage on the current batch of
new tickets if nobody else gets to it, but I anticipate it'll need
more knowledge of the lex/parse phase than I can bring to bear.

This looks like another case of #125351 and other similar sublex recovery issues.

Tony

@p5pRT
Copy link
Author

p5pRT commented Jan 30, 2018

From @tonycoz

On Wed, 17 Jan 2018 16​:24​:03 -0800, tonyc wrote​:

On Mon, 08 Jan 2018 16​:41​:35 -0800, hv wrote​:

This appears similar to rt131836, but is not fixed by its fix. It
reduces at least to​:
./miniperl -e 's//${sub{b{]]]{}#$/ sub{}'
with the same stack trace.

I'll come back to this after completing triage on the current batch
of
new tickets if nobody else gets to it, but I anticipate it'll need
more knowledge of the lex/parse phase than I can bring to bear.

This looks like another case of #125351 and other similar sublex
recovery issues.

And so it is.

Since it requires feedng code to the interpreter it isn't a security issue, so it's now public.

Since it duplicates #125351 I'm merging it into that ticket.

Tony

@p5pRT
Copy link
Author

p5pRT commented Jan 30, 2018

From @tonycoz

On Mon, 29 Jan 2018 21​:29​:37 -0800, tonyc wrote​:

On Wed, 17 Jan 2018 16​:24​:03 -0800, tonyc wrote​:

On Mon, 08 Jan 2018 16​:41​:35 -0800, hv wrote​:

This appears similar to rt131836, but is not fixed by its fix. It
reduces at least to​:
./miniperl -e 's//${sub{b{]]]{}#$/ sub{}'
with the same stack trace.

I'll come back to this after completing triage on the current batch
of
new tickets if nobody else gets to it, but I anticipate it'll need
more knowledge of the lex/parse phase than I can bring to bear.

This looks like another case of #125351 and other similar sublex
recovery issues.

And so it is.

Since it requires feedng code to the interpreter it isn't a security
issue, so it's now public.

Since it duplicates #125351 I'm merging it into that ticket.

And here is hopefully a patch for this long-standing issue.

Tony

@p5pRT
Copy link
Author

p5pRT commented Jan 30, 2018

From @tonycoz

0001-perl-125351-abort-parsing-if-parse-errors-happen-in-.patch
From abf27f937c988e96bf65c6be92ac4edc188e31c3 Mon Sep 17 00:00:00 2001
From: Tony Cook <tony@develop-help.com>
Date: Tue, 30 Jan 2018 16:40:53 +1100
Subject: (perl #125351) abort parsing if parse errors happen in a sub lex

We've had a few reports of segmentation faults and other misbehaviour
when sub-parsing, such as within interpolated expressions, fails.

This change aborts compilation if anything complex enough to not be
parsed by the lexer is compiled in a sub-parse *and* an error
occurs within the sub-parse.

An earlier version of this patch failed on simpler expressions,
which caused many test failures, which this version doesn't (which may
just mean we need more tests...)
---
 parser.h     |  2 ++
 t/base/lex.t | 11 ++++++++++-
 toke.c       | 18 ++++++++++++++++++
 3 files changed, 30 insertions(+), 1 deletion(-)

diff --git a/parser.h b/parser.h
index 4187e0a93d..216e9deca8 100644
--- a/parser.h
+++ b/parser.h
@@ -58,6 +58,7 @@ typedef struct yy_parser {
 				   1 = @{...}  2 = ->@ */
     U8		expect;		/* how to interpret ambiguous tokens */
     bool	preambled;
+    bool        sub_no_recover; /* can't recover from a sublex error */
     I32		lex_formbrack;	/* bracket count at outer format level */
     OP		*lex_inpat;	/* in pattern $) and $| are special */
     OP		*lex_op;	/* extra info to pass back on op */
@@ -95,6 +96,7 @@ typedef struct yy_parser {
     U16		in_my;		/* we're compiling a "my"/"our" declaration */
     U8		lex_state;	/* next token is determined */
     U8		error_count;	/* how many compile errors so far, max 10 */
+    U8		sub_error_count; /* the number of errors before sublexing */
     HV		*in_my_stash;	/* declared class of this "my" declaration */
     PerlIO	*rsfp;		/* current source file pointer */
     AV		*rsfp_filters;	/* holds chain of active source filters */
diff --git a/t/base/lex.t b/t/base/lex.t
index de33e7a688..414aa1fceb 100644
--- a/t/base/lex.t
+++ b/t/base/lex.t
@@ -1,6 +1,6 @@
 #!./perl
 
-print "1..117\n";
+print "1..120\n";
 
 $x = 'x';
 
@@ -557,6 +557,15 @@ eval q|s##[}#e|;
  eval ('/@0{0*->@*/*]');
  print "ok $test - 128171\n"; $test++;
 }
+{
+  # various sub-parse recovery issues that crashed perl
+  eval 's//${sub{b{]]]{}#$/ sub{}';
+  print "ok $test - 132640\n"; $test++;
+  eval 'qq{@{sub{]]}}}};shift';
+  print "ok $test - 125351\n"; $test++;
+  eval 'qq{@{sub{]]}}}}-shift';
+  print "ok $test - 126192\n"; $test++;
+}
 
 $foo = "WRONG"; $foo:: = "bar"; $bar = "baz";
 print "not " unless "$foo::$bar" eq "barbaz";
diff --git a/toke.c b/toke.c
index 5959bc3e9e..3dcc7e9f86 100644
--- a/toke.c
+++ b/toke.c
@@ -2390,6 +2390,8 @@ S_sublex_start(pTHX)
     PL_parser->lex_super_state = PL_lex_state;
     PL_parser->lex_sub_inwhat = (U16)op_type;
     PL_parser->lex_sub_op = PL_lex_op;
+    PL_parser->sub_no_recover = FALSE;
+    PL_parser->sub_error_count = PL_error_count;
     PL_lex_state = LEX_INTERPPUSH;
 
     PL_expect = XTERM;
@@ -2569,6 +2571,20 @@ S_sublex_done(pTHX)
     else {
 	const line_t l = CopLINE(PL_curcop);
 	LEAVE;
+        if (PL_parser->sub_error_count != PL_error_count) {
+            const char * const name = OutCopFILE(PL_curcop);
+            if (PL_parser->sub_no_recover) {
+                const char * msg = "";
+                if (PL_in_eval) {
+                    SV *errsv = ERRSV;
+                    if (SvCUR(ERRSV)) {
+                        msg = Perl_form(aTHX_ "%" SVf, SVfARG(errsv));
+                    }
+                }
+                abort_execution(msg, name);
+                NOT_REACHED;
+            }
+        }
 	if (PL_multi_close == '<')
 	    PL_parser->herelines += l - PL_multi_end;
 	PL_bufend = SvPVX(PL_linestr);
@@ -4157,6 +4173,7 @@ S_intuit_more(pTHX_ char *s, char *e)
 	return TRUE;
     if (*s != '{' && *s != '[')
 	return FALSE;
+    PL_parser->sub_no_recover = TRUE;
     if (!PL_lex_inpat)
 	return TRUE;
 
@@ -9580,6 +9597,7 @@ S_scan_ident(pTHX_ char *s, char *dest, STRLEN destlen, I32 ck_uni)
             CopLINE_set(PL_curcop, orig_copline);
             PL_parser->herelines = herelines;
 	    *dest = '\0';
+            PL_parser->sub_no_recover = TRUE;
 	}
     }
     else if (   PL_lex_state == LEX_INTERPNORMAL
-- 
2.11.0

@p5pRT
Copy link
Author

p5pRT commented Feb 27, 2018

From @tonycoz

On Mon, 29 Jan 2018 21​:42​:34 -0800, tonyc wrote​:

And here is hopefully a patch for this long-standing issue.

Which I apparently applied as bb4e4c3.

Tony

@p5pRT
Copy link
Author

p5pRT commented Feb 27, 2018

@tonycoz - Status changed from 'open' to 'pending release'

@p5pRT
Copy link
Author

p5pRT commented Mar 27, 2018

From sraums2498@gmail.com

Hi,
Actually I have been targeting perl interpreter to find vulnerabilities
which I thought will be covered under "security" issues here.
Can I seek help to understand following statement? This will positively
help me restructuring my approach.

Since it requires feedng code to the interpreter it isn't a security
issue, so it's now public.

On Tue, Feb 27, 2018 at 6​:09 AM, Tony Cook via RT <perlbug-followup@​perl.org

wrote​:

On Mon, 29 Jan 2018 21​:42​:34 -0800, tonyc wrote​:

And here is hopefully a patch for this long-standing issue.

Which I apparently applied as bb4e4c3.

Tony

--
Regards,
SRAUMS

@p5pRT
Copy link
Author

p5pRT commented Mar 28, 2018

From @iabyn

On Tue, Mar 27, 2018 at 12​:38​:50PM +0530, SRAUMS JN wrote​:

Hi,
Actually I have been targeting perl interpreter to find vulnerabilities
which I thought will be covered under "security" issues here.
Can I seek help to understand following statement? This will positively
help me restructuring my approach.

Since it requires feedng code to the interpreter it isn't a security
issue, so it's now public.

The perl interpreter has two main sources of input​: code and data.

The data is highly likely to be under the control of an attacker.
If there is a bug in the interpreter which can be triggered by supplying
carefully crafted data (think of a bug in an XML parser which is parsing
XML supplied by untrusted websites), then that's a security issue with
perl.

If a bug in perl requires the attacker to supply specially-crafted source
code to the interpreter (e.g. a specific syntax error) then that's not an
issue, because if the attacker can control or influence what source code
is fed to the perl interpreter, they could just as easily feed

  system "rm -rf /"

or similar to the interpreter.

--
Wesley Crusher gets beaten up by his classmates for being a smarmy git,
and consequently has a go at making some friends of his own age for a
change.
  -- Things That Never Happen in "Star Trek" #18

@p5pRT
Copy link
Author

p5pRT commented Jun 23, 2018

From @khwilliamson

Thank you for filing this report. You have helped make Perl better.

With the release yesterday of Perl 5.28.0, this and 185 other issues have been
resolved.

Perl 5.28.0 may be downloaded via​:
https://metacpan.org/release/XSAWYERX/perl-5.28.0

If you find that the problem persists, feel free to reopen this ticket.

@p5pRT
Copy link
Author

p5pRT commented Jun 23, 2018

@khwilliamson - Status changed from 'pending release' to 'resolved'

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant