Perl / perl5

🐪 The Perl programming language
https://dev.perl.org/perl5/
Other
1.85k stars 527 forks source link

Null pointer dereference in S_SvREFCNT_dec #16627

Open p5pRT opened 5 years ago

p5pRT commented 5 years ago

Migrated from rt.perl.org#133369 (status was 'new')

Searchable as RT133369$

p5pRT commented 5 years ago

From @geeknik

./perl -e 'for$0(qw(0 0)){push@​r\,qr/@​r(?{})/}' triggers a null pointer dereference and segfault in v5.29.0-87-ga13f1de.

==10676==ERROR​: AddressSanitizer​: SEGV on unknown address 0x000000000000 (pc 0x0000007060c8 bp 0x7fffb4efe100 sp 0x7fffb4efe0e0 T0) ==10676==The signal is caused by a READ memory access. ==10676==Hint​: address points to the zero page.   #0 0x7060c7 in S_SvREFCNT_dec /root/perl/./inline.h​:212​:11   #1 0x7305f0 in S_free_codeblocks /root/perl/regcomp.c​:6268​:9   #2 0x9b59ca in Perl_leave_scope /root/perl/scope.c   #3 0x9df198 in Perl_dounwind /root/perl/pp_ctl.c​:1549​:9   #4 0x5b5846 in S_my_exit_jump /root/perl/perl.c​:5240​:9   #5 0x5c092e in Perl_my_failure_exit /root/perl/perl.c​:5227​:5   #6 0x9e1d2f in Perl_die_unwind /root/perl/pp_ctl.c​:1796​:5   #7 0x7ce081 in Perl_vcroak /root/perl/util.c​:1715​:5   #8 0x7c6b5b in Perl_croak /root/perl/util.c​:1760​:5   #9 0x70362b in S_reg /root/perl/regcomp.c   #10 0x77618a in S_regatom /root/perl/regcomp.c​:12960​:15   #11 0x77232c in S_regpiece /root/perl/regcomp.c​:12004​:11   #12 0x762ea2 in S_regbranch /root/perl/regcomp.c​:11932​:18   #13 0x6f451c in S_reg /root/perl/regcomp.c​:11663​:10   #14 0x77618a in S_regatom /root/perl/regcomp.c​:12960​:15   #15 0x77232c in S_regpiece /root/perl/regcomp.c​:12004​:11   #16 0x762ea2 in S_regbranch /root/perl/regcomp.c​:11932​:18   #17 0x6f451c in S_reg /root/perl/regcomp.c​:11663​:10   #18 0x6dc4ba in Perl_re_op_compile /root/perl/regcomp.c​:7224​:9   #19 0x9c4274 in Perl_pp_regcomp /root/perl/pp_ctl.c​:108​:14   #20 0x7c17d8 in Perl_runops_debug /root/perl/dump.c​:2536​:23   #21 0x5b0831 in S_run_body /root/perl/perl.c   #22 0x5afe7b in perl_run /root/perl/perl.c​:2617​:2   #23 0x50da47 in main /root/perl/perlmain.c​:122​:9   #24 0x7f39127c182f in __libc_start_main /build/glibc-Cl5G7W/glibc-2.23/csu/../csu/libc-start.c​:291   #25 0x436d28 in _start (/root/perl/perl+0x436d28)

AddressSanitizer can not provide additional info. SUMMARY​: AddressSanitizer​: SEGV /root/perl/./inline.h​:212​:11 in S_SvREFCNT_dec ==10676==ABORTING

khwilliamson commented 3 weeks ago

This is still present in v39.10

==62279==ERROR: AddressSanitizer: SEGV on unknown address (pc 0x55e6f775dee0 bp 0x7fffab24da10 sp 0x7fffab24d9d0 T0) ==62279==The signal is caused by a READ memory access. ==62279==Hint: this fault was caused by a dereference of a high value address (see register values below). Disassemble the provided pc to learn which register was used.

0 0x55e6f775dee0 in Perl_SvREFCNT_dec_NN /home/khw/perl/locales/straight/./sv_inline.h:710:14

1 0x55e6f7777ae2 in S_free_codeblocks /home/khw/perl/locales/straight/regcomp.c:498:13

2 0x55e6f7a3c0cc in Perl_leave_scope /home/khw/perl/locales/straight/scope.c:1537:13

3 0x55e6f74bcbb5 in Perl_dounwind /home/khw/perl/locales/straight/pp_ctl.c:1775:9

4 0x55e6f707e980 in S_my_exit_jump /home/khw/perl/locales/straight/perl.c:5519:9

5 0x55e6f7093ca7 in Perl_my_failure_exit /home/khw/perl/locales/straight/perl.c:5506:5

6 0x55e6f74c3996 in Perl_die_unwind /home/khw/perl/locales/straight/pp_ctl.c:2092:5

7 0x55e6f7d7f9e6 in Perl_vcroak /home/khw/perl/locales/straight/util.c:1897:5

8 0x55e6f7d8077d in Perl_croak /home/khw/perl/locales/straight/util.c:1948:5

9 0x55e6f77446a4 in S_reg /home/khw/perl/locales/straight/regcomp.c:3797:21

10 0x55e6f77c2880 in S_regatom /home/khw/perl/locales/straight/regcomp.c:5609:15

11 0x55e6f77b55ae in S_regpiece /home/khw/perl/locales/straight/regcomp.c:4745:11

12 0x55e6f778d187 in S_regbranch /home/khw/perl/locales/straight/regcomp.c:4510:18

13 0x55e6f7755896 in S_reg /home/khw/perl/locales/straight/regcomp.c:4182:10

14 0x55e6f77c2880 in S_regatom /home/khw/perl/locales/straight/regcomp.c:5609:15

15 0x55e6f77b55ae in S_regpiece /home/khw/perl/locales/straight/regcomp.c:4745:11

16 0x55e6f778d187 in S_regbranch /home/khw/perl/locales/straight/regcomp.c:4510:18

17 0x55e6f7755896 in S_reg /home/khw/perl/locales/straight/regcomp.c:4182:10

18 0x55e6f76fb3be in Perl_re_op_compile /home/khw/perl/locales/straight/regcomp.c:1714:9

19 0x55e6f7494e3f in Perl_pp_regcomp /home/khw/perl/locales/straight/pp_ctl.c:119:14

20 0x55e6f7155438 in Perl_runops_debug /home/khw/perl/locales/straight/dump.c:2866:23

21 0x55e6f7074fa2 in S_run_body /home/khw/perl/locales/straight/perl.c:2889:9

22 0x55e6f707219d in perl_run /home/khw/perl/locales/straight/perl.c:2804:9

23 0x55e6f6f58cf4 in main /home/khw/perl/locales/straight/perlmain.c:127:9

24 0x7fad5cf0dd8f in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16

25 0x7fad5cf0de3f in __libc_start_main csu/../csu/libc-start.c:392:3

26 0x55e6f6e9ad24 in _start (/home/khw/perl/locales/straight/perl+0x28fd24) (BuildId: 0cb917dd7204b49daa8373c79aba4404dbac8aea)

mauke commented 3 weeks ago

I don't get a null pointer dereference, but I'm not using ASan either.

$ ./perl -Ilib -Mre=eval -e 'for$0(qw(0 0)){push@r,qr/@r(?{})/}' 
Segmentation fault
$ gdb --args ./perl -Ilib -Mre=eval -e 'for$0(qw(0 0)){push@r,qr/@r(?{})/}'
...
(gdb) r
Starting program: /home/mauke/Projects/perl5/perl -Ilib -Mre=eval -e for\$0\(qw\(0\ 0\)\)\{push@r,qr/@r\(\?\{\}\)/\}
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".

Program received signal SIGSEGV, Segmentation fault.
S_compile_runtime_code (plen=<optimized out>, pat=0x555555a520f0 "(?^:(?{}))(?{})", pRExC_state=0x7fffffffd280) at regcomp.c:1053
1053                assert(pat[src->start] == '(');
(gdb) bt
#0  S_compile_runtime_code (plen=<optimized out>, pat=0x555555a520f0 "(?^:(?{}))(?{})", pRExC_state=0x7fffffffd280) at regcomp.c:1053
#1  Perl_re_op_compile (patternp=<optimized out>, pat_count=<optimized out>, expr=<optimized out>, eng=0x555555a235c0 <PL_core_reg_engine>, old_re=0x555555a2f678, is_bare_re=<optimized out>, orig_rx_flags=0, pm_flags=2013265920)
    at regcomp.c:1602
#2  0x000055555568c1e0 in Perl_pp_regcomp () at pp_ctl.c:121
#3  0x00005555555f0252 in Perl_runops_debug () at dump.c:2866
#4  0x00005555555d5ed0 in S_run_body (oldscope=1) at perl.c:2865
#5  perl_run (my_perl=<optimized out>) at perl.c:2780
#6  0x000055555559e19c in main (argc=<optimized out>, argv=<optimized out>, env=<optimized out>) at perlmain.c:127
(gdb) p src
$1 = (struct reg_code_block *) 0x555555a63350
(gdb) p src->start
$2 = 2314885530818453536
(gdb) 
mauke commented 3 weeks ago

Slightly reduced:

perl -e 'use re "eval"; my @x = qr/(?{})/; push @x, qr/(?{})@x/'

This segfaults about 50% of the time for me.

jkeenan commented 3 weeks ago

Slightly reduced:

perl -e 'use re "eval"; my @x = qr/(?{})/; push @x, qr/(?{})@x/'

This segfaults about 50% of the time for me.

... which is what I also get on Ubuntu Linux 22.04 LTS. But on FreeBSD-13, I don't get any message or segfault.

$ perl -e 'use re "eval"; my @x = qr/(?{})/; push @x, qr/(?{})@x/'
$ perl -e 'use re "eval"; my @x = qr/(?{})/; push @x, qr/(?{})@x/'
$ perl -e 'use re "eval"; my @x = qr/(?{})/; push @x, qr/(?{})@x/'
$ perl -e 'use re "eval"; my @x = qr/(?{})/; push @x, qr/(?{})@x/'
$ perl -e 'use re "eval"; my @x = qr/(?{})/; push @x, qr/(?{})@x/'
$ perl -e 'use re "eval"; my @x = qr/(?{})/; push @x, qr/(?{})@x/'
$ perl -e 'use re "eval"; my @x = qr/(?{})/; push @x, qr/(?{})@x/'
$ perl -e 'use re "eval"; my @x = qr/(?{})/; push @x, qr/(?{})@x/'
$ perl -e 'use re "eval"; my @x = qr/(?{})/; push @x, qr/(?{})@x/'
$ perl -e 'use re "eval"; my @x = qr/(?{})/; push @x, qr/(?{})@x/'
mauke commented 3 weeks ago

I have a patch that seems to fix this issue: https://github.com/mauke/perl5/commit/039cadf286fae4962564c355239af1f20fc4d8a3

However, this patch was written based on vibes, not any deep understanding of the code. I'd appreciate any review of what's going on here. @iabyn ?

iabyn commented 3 weeks ago

I have a very similar patch in development (passing address of n as a pointer), but there are some subtleties you've missed (notably at line 734, *pn shouldn't be reset to zero). I wasn't entirely happy with my branch, so I was going to leave it until tomorrow to see if there was a more elegant fix. Probably best to leave this one to me - it was my mistake in the first place.

iabyn commented 1 week ago

I've now created PR #22201, which has a more general fix to this issue.