Skip Menu |
Report information
Id: 126602
Status: resolved
Priority: 0/
Queue: perl5

Owner: Nobody
Requestors: brian.carpenter [at] gmail.com
Cc:
AdminCc:

Operating System: (no value)
PatchStatus: (no value)
Severity: low
Type: unknown
Perl Version: (no value)
Fixed In: (no value)

Attachments
0001-perl-126602-make-sure-targ-isn-t-freed-from-under-us.patch



Subject: double free and segfault in Perl v5.23.4-81-g96524c2
Download (untitled) / with headers
text/plain 4.7k
The following triggers a double free (I think) and a segfault in Perl v5.23.4-81-g96524c2: perl -e 's//*_=0;s|0||;00.y0/e' Segmentation fault ==6727== Invalid read of size 1 ==6727== at 0x99A0B1: S_sv_uncow (sv.c:5107) ==6727== by 0x9877B8: Perl_sv_force_normal_flags (sv.c:5169) ==6727== by 0x6ED035: Perl_pregfree2 (regcomp.c:17511) ==6727== by 0x93A207: Perl_sv_clear (sv.c:6458) ==6727== by 0x93EFFB: Perl_sv_free2 (sv.c:6885) ==6727== by 0x43E3C4: S_SvREFCNT_dec (inline.h:166) ==6727== by 0x43E3C4: Perl_op_clear (op.c:973) ==6727== by 0x43E79B: Perl_op_free (op.c:779) ==6727== by 0x43EE67: Perl_op_free (op.c:762) ==6727== by 0x5294F0: perl_destruct (perl.c:777) ==6727== by 0x42C56F: main (perlmain.c:127) ==6727== Address 0x5f818a9 is 9 bytes inside a block of size 10 free'd ==6727== at 0x4C28D29: free (vg_replace_malloc.c:530) ==6727== by 0xB54521: Perl_pp_substcont (pp_ctl.c:249) ==6727== by 0x7E0D0E: Perl_runops_debug (dump.c:2224) ==6727== by 0x544AF5: S_run_body (perl.c:2464) ==6727== by 0x544AF5: perl_run (perl.c:2387) ==6727== by 0x42C617: main (perlmain.c:116) ==6727== Block was alloc'd at ==6727== at 0x4C27C0F: malloc (vg_replace_malloc.c:299) ==6727== by 0x7F0BAC: Perl_safesysmalloc (util.c:153) ==6727== by 0x98EF0F: Perl_sv_grow (sv.c:1628) ==6727== by 0x9F0867: Perl_sv_pvn_force_flags (sv.c:9875) ==6727== by 0x901FD6: Perl_pp_subst (pp_hot.c:2997) ==6727== by 0x7E0D0E: Perl_runops_debug (dump.c:2224) ==6727== by 0x544AF5: S_run_body (perl.c:2464) ==6727== by 0x544AF5: perl_run (perl.c:2387) ==6727== by 0x42C617: main (perlmain.c:116) ==6727== ==6727== Invalid free() / delete / delete[] / realloc() ==6727== at 0x4C28D29: free (vg_replace_malloc.c:530) ==6727== by 0x93D344: Perl_sv_clear (sv.c:6610) ==6727== by 0x93EFFB: Perl_sv_free2 (sv.c:6885) ==6727== by 0x6ED544: S_SvREFCNT_dec (inline.h:166) ==6727== by 0x6ED544: Perl_pregfree2 (regcomp.c:17513) ==6727== by 0x93A207: Perl_sv_clear (sv.c:6458) ==6727== by 0x93EFFB: Perl_sv_free2 (sv.c:6885) ==6727== by 0x43E3C4: S_SvREFCNT_dec (inline.h:166) ==6727== by 0x43E3C4: Perl_op_clear (op.c:973) ==6727== by 0x43E79B: Perl_op_free (op.c:779) ==6727== by 0x43EE67: Perl_op_free (op.c:762) ==6727== by 0x5294F0: perl_destruct (perl.c:777) ==6727== by 0x42C56F: main (perlmain.c:127) ==6727== Address 0x5f818a0 is 0 bytes inside a block of size 10 free'd ==6727== at 0x4C28D29: free (vg_replace_malloc.c:530) ==6727== by 0xB54521: Perl_pp_substcont (pp_ctl.c:249) ==6727== by 0x7E0D0E: Perl_runops_debug (dump.c:2224) ==6727== by 0x544AF5: S_run_body (perl.c:2464) ==6727== by 0x544AF5: perl_run (perl.c:2387) ==6727== by 0x42C617: main (perlmain.c:116) ==6727== Block was alloc'd at ==6727== at 0x4C27C0F: malloc (vg_replace_malloc.c:299) ==6727== by 0x7F0BAC: Perl_safesysmalloc (util.c:153) ==6727== by 0x98EF0F: Perl_sv_grow (sv.c:1628) ==6727== by 0x9F0867: Perl_sv_pvn_force_flags (sv.c:9875) ==6727== by 0x901FD6: Perl_pp_subst (pp_hot.c:2997) ==6727== by 0x7E0D0E: Perl_runops_debug (dump.c:2224) ==6727== by 0x544AF5: S_run_body (perl.c:2464) ==6727== by 0x544AF5: perl_run (perl.c:2387) ==6727== by 0x42C617: main (perlmain.c:116) ==6727== Program received signal SIGSEGV, Segmentation fault. malloc_consolidate (av=av@entry=0x7ffff7062620 <main_arena>) at malloc.c:4151 4151 malloc.c: No such file or directory. (gdb) bt #0 malloc_consolidate (av=av@entry=0x7ffff7062620 <main_arena>) at malloc.c:4151 #1 0x00007ffff6d38691 in _int_free (av=0x7ffff7062620 <main_arena>, p=<optimized out>, have_lock=0) at malloc.c:4057 #2 0x000000000043a8cc in Perl_opslab_free (slab=0x1218020) at op.c:418 #3 0x000000000043e7a7 in Perl_op_free (o=<optimized out>) at op.c:780 #4 0x00000000005294f1 in perl_destruct (my_perl=<optimized out>) at perl.c:777 #5 0x000000000042c570 in main (argc=3, argv=0x7fffffffe358, env=0x7fffffffe378) at perlmain.c:127 (gdb) i r rax 0x1213360 18953056 rbx 0x7ffff7062678 140737337763448 rcx 0x7ffff7062678 140737337763448 rdx 0x361 865 rsi 0x1214340 18957120 rdi 0x7ffff7062620 140737337763360 rbp 0x1213360 0x1213360 rsp 0x7fffffffdfa0 0x7fffffffdfa0 r8 0x7ffff7062628 140737337763368 r9 0x7ffff7062670 140737337763440 r10 0x0 0 r11 0x1216050 18964560 r12 0x7ffff82759d8 140737356716504 r13 0x20 32 r14 0x1213030 18952240 r15 0x7ffff7062620 140737337763360 rip 0x7ffff6d37b95 0x7ffff6d37b95 <malloc_consolidate+245> eflags 0x10206 [ PF IF RF ] cs 0x33 51 ss 0x2b 43 ds 0x0 0 es 0x0 0 fs 0x0 0 gs 0x0 0
Subject: Re: [perl #126602] double free and segfault in Perl v5.23.4-81-g96524c2
Date: Mon, 9 Nov 2015 15:19:17 -0500
From: Dan Collins <dcollinsn [...] gmail.com>
To: Perl5 Porters <perl5-porters [...] perl.org>
Download (untitled) / with headers
text/plain 5.6k
This is probably a stack-is-not-refcounted issue. The outer s/// places $_ on the stack, and in the execution of the regex, *_ is then assigned to and $_ is implicitly accessed again. It might be possible to fix this double free, but this seems very similar to other issues that have been impossible to fix in the general case.

On Mon, Nov 9, 2015 at 3:13 PM, Brian Carpenter <perlbug-followup@perl.org> wrote:
Show quoted text
# New Ticket Created by  Brian Carpenter
# Please include the string:  [perl #126602]
# in the subject line of all future correspondence about this issue.
# <URL: https://rt.perl.org/Ticket/Display.html?id=126602 >


The following triggers a double free (I think) and a segfault in Perl v5.23.4-81-g96524c2:

perl -e 's//*_=0;s|0||;00.y0/e'
Segmentation fault

==6727== Invalid read of size 1
==6727==    at 0x99A0B1: S_sv_uncow (sv.c:5107)
==6727==    by 0x9877B8: Perl_sv_force_normal_flags (sv.c:5169)
==6727==    by 0x6ED035: Perl_pregfree2 (regcomp.c:17511)
==6727==    by 0x93A207: Perl_sv_clear (sv.c:6458)
==6727==    by 0x93EFFB: Perl_sv_free2 (sv.c:6885)
==6727==    by 0x43E3C4: S_SvREFCNT_dec (inline.h:166)
==6727==    by 0x43E3C4: Perl_op_clear (op.c:973)
==6727==    by 0x43E79B: Perl_op_free (op.c:779)
==6727==    by 0x43EE67: Perl_op_free (op.c:762)
==6727==    by 0x5294F0: perl_destruct (perl.c:777)
==6727==    by 0x42C56F: main (perlmain.c:127)
==6727==  Address 0x5f818a9 is 9 bytes inside a block of size 10 free'd
==6727==    at 0x4C28D29: free (vg_replace_malloc.c:530)
==6727==    by 0xB54521: Perl_pp_substcont (pp_ctl.c:249)
==6727==    by 0x7E0D0E: Perl_runops_debug (dump.c:2224)
==6727==    by 0x544AF5: S_run_body (perl.c:2464)
==6727==    by 0x544AF5: perl_run (perl.c:2387)
==6727==    by 0x42C617: main (perlmain.c:116)
==6727==  Block was alloc'd at
==6727==    at 0x4C27C0F: malloc (vg_replace_malloc.c:299)
==6727==    by 0x7F0BAC: Perl_safesysmalloc (util.c:153)
==6727==    by 0x98EF0F: Perl_sv_grow (sv.c:1628)
==6727==    by 0x9F0867: Perl_sv_pvn_force_flags (sv.c:9875)
==6727==    by 0x901FD6: Perl_pp_subst (pp_hot.c:2997)
==6727==    by 0x7E0D0E: Perl_runops_debug (dump.c:2224)
==6727==    by 0x544AF5: S_run_body (perl.c:2464)
==6727==    by 0x544AF5: perl_run (perl.c:2387)
==6727==    by 0x42C617: main (perlmain.c:116)
==6727==
==6727== Invalid free() / delete / delete[] / realloc()
==6727==    at 0x4C28D29: free (vg_replace_malloc.c:530)
==6727==    by 0x93D344: Perl_sv_clear (sv.c:6610)
==6727==    by 0x93EFFB: Perl_sv_free2 (sv.c:6885)
==6727==    by 0x6ED544: S_SvREFCNT_dec (inline.h:166)
==6727==    by 0x6ED544: Perl_pregfree2 (regcomp.c:17513)
==6727==    by 0x93A207: Perl_sv_clear (sv.c:6458)
==6727==    by 0x93EFFB: Perl_sv_free2 (sv.c:6885)
==6727==    by 0x43E3C4: S_SvREFCNT_dec (inline.h:166)
==6727==    by 0x43E3C4: Perl_op_clear (op.c:973)
==6727==    by 0x43E79B: Perl_op_free (op.c:779)
==6727==    by 0x43EE67: Perl_op_free (op.c:762)
==6727==    by 0x5294F0: perl_destruct (perl.c:777)
==6727==    by 0x42C56F: main (perlmain.c:127)
==6727==  Address 0x5f818a0 is 0 bytes inside a block of size 10 free'd
==6727==    at 0x4C28D29: free (vg_replace_malloc.c:530)
==6727==    by 0xB54521: Perl_pp_substcont (pp_ctl.c:249)
==6727==    by 0x7E0D0E: Perl_runops_debug (dump.c:2224)
==6727==    by 0x544AF5: S_run_body (perl.c:2464)
==6727==    by 0x544AF5: perl_run (perl.c:2387)
==6727==    by 0x42C617: main (perlmain.c:116)
==6727==  Block was alloc'd at
==6727==    at 0x4C27C0F: malloc (vg_replace_malloc.c:299)
==6727==    by 0x7F0BAC: Perl_safesysmalloc (util.c:153)
==6727==    by 0x98EF0F: Perl_sv_grow (sv.c:1628)
==6727==    by 0x9F0867: Perl_sv_pvn_force_flags (sv.c:9875)
==6727==    by 0x901FD6: Perl_pp_subst (pp_hot.c:2997)
==6727==    by 0x7E0D0E: Perl_runops_debug (dump.c:2224)
==6727==    by 0x544AF5: S_run_body (perl.c:2464)
==6727==    by 0x544AF5: perl_run (perl.c:2387)
==6727==    by 0x42C617: main (perlmain.c:116)
==6727==

Program received signal SIGSEGV, Segmentation fault.
malloc_consolidate (av=av@entry=0x7ffff7062620 <main_arena>) at malloc.c:4151
4151    malloc.c: No such file or directory.
(gdb) bt
#0  malloc_consolidate (av=av@entry=0x7ffff7062620 <main_arena>) at malloc.c:4151
#1  0x00007ffff6d38691 in _int_free (av=0x7ffff7062620 <main_arena>, p=<optimized out>,
    have_lock=0) at malloc.c:4057
#2  0x000000000043a8cc in Perl_opslab_free (slab=0x1218020) at op.c:418
#3  0x000000000043e7a7 in Perl_op_free (o=<optimized out>) at op.c:780
#4  0x00000000005294f1 in perl_destruct (my_perl=<optimized out>) at perl.c:777
#5  0x000000000042c570 in main (argc=3, argv=0x7fffffffe358, env=0x7fffffffe378)
    at perlmain.c:127
(gdb) i r
rax            0x1213360        18953056
rbx            0x7ffff7062678   140737337763448
rcx            0x7ffff7062678   140737337763448
rdx            0x361    865
rsi            0x1214340        18957120
rdi            0x7ffff7062620   140737337763360
rbp            0x1213360        0x1213360
rsp            0x7fffffffdfa0   0x7fffffffdfa0
r8             0x7ffff7062628   140737337763368
r9             0x7ffff7062670   140737337763440
r10            0x0      0
r11            0x1216050        18964560
r12            0x7ffff82759d8   140737356716504
r13            0x20     32
r14            0x1213030        18952240
r15            0x7ffff7062620   140737337763360
rip            0x7ffff6d37b95   0x7ffff6d37b95 <malloc_consolidate+245>
eflags         0x10206  [ PF IF RF ]
cs             0x33     51
ss             0x2b     43
ds             0x0      0
es             0x0      0
fs             0x0      0
gs             0x0      0


RT-Send-CC: perl5-porters [...] perl.org
Download (untitled) / with headers
text/plain 585b
On Mon Nov 09 12:20:11 2015, dcollinsn@gmail.com wrote: Show quoted text
> This is probably a stack-is-not-refcounted issue. The outer s/// places $_ > on the stack, and in the execution of the regex, *_ is then assigned to and > $_ is implicitly accessed again. It might be possible to fix this double > free, but this seems very similar to other issues that have been impossible > to fix in the general case.
In this case the SV that's being freed isn't being stored on the argument stack, but on the context stack, and we can keep a reference count there. Patch with fix attached for review. Tony
Subject: 0001-perl-126602-make-sure-targ-isn-t-freed-from-under-us.patch
From 7a2d29de9695586d39befe1c5e32ac94642db5cf Mon Sep 17 00:00:00 2001 From: Tony Cook <tony@develop-help.com> Date: Wed, 11 Nov 2015 11:29:03 +1100 Subject: [perl #126602] make sure targ isn't freed from under us --- cop.h | 6 ++++-- t/re/subst.t | 7 ++++++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/cop.h b/cop.h index d36d189..b15ddf4 100644 --- a/cop.h +++ b/cop.h @@ -939,11 +939,13 @@ struct subst { cx->sb_rx = rx, \ cx->cx_type = CXt_SUBST | (once ? CXp_ONCE : 0); \ rxres_save(&cx->sb_rxres, rx); \ - (void)ReREFCNT_inc(rx) + (void)ReREFCNT_inc(rx); \ + SvREFCNT_inc_void_NN(targ) # define POPSUBST(cx) cx = &cxstack[cxstack_ix--]; \ rxres_free(&cx->sb_rxres); \ - ReREFCNT_dec(cx->sb_rx) + ReREFCNT_dec(cx->sb_rx); \ + SvREFCNT_dec_NN(cx->sb_targ) #endif #define CxONCE(cx) ((cx)->cx_type & CXp_ONCE) diff --git a/t/re/subst.t b/t/re/subst.t index 2fed182..7939fe5 100644 --- a/t/re/subst.t +++ b/t/re/subst.t @@ -9,7 +9,7 @@ BEGIN { require './loc_tools.pl'; } -plan( tests => 267 ); +plan( tests => 268 ); $_ = 'david'; $a = s/david/rules/r; @@ -1078,3 +1078,8 @@ SKIP: { $s1 =~ s/.?/$s1++/ge; is($s1, "01","RT #123954 s1"); } +{ + # RT #126602 double free if the value being modified is freed in the replacement + fresh_perl_is('s//*_=0;s|0||;00.y0/e; print qq(ok\n)', "ok\n", { stderr => 1 }, + "[perl #126602] s//*_=0;s|0||/e crashes"); +} -- 2.1.4
RT-Send-CC: perl5-porters [...] perl.org
Download (untitled) / with headers
text/plain 721b
On Tue Nov 10 16:30:56 2015, tonyc wrote: Show quoted text
> On Mon Nov 09 12:20:11 2015, dcollinsn@gmail.com wrote:
> > This is probably a stack-is-not-refcounted issue. The outer s/// > > places $_ > > on the stack, and in the execution of the regex, *_ is then assigned > > to and > > $_ is implicitly accessed again. It might be possible to fix this > > double > > free, but this seems very similar to other issues that have been > > impossible > > to fix in the general case.
> > In this case the SV that's being freed isn't being stored on the > argument stack, but on the context stack, and we can keep a reference > count there. > > Patch with fix attached for review.
Applied in cf69025fa87b76cf2f1859253fb3313ffd5b7e48. Tony


This service is sponsored and maintained by Best Practical Solutions and runs on Perl.org infrastructure.

For issues related to this RT instance (aka "perlbug"), please contact perlbug-admin at perl.org