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

double free and segfault in Perl v5.23.4-81-g96524c2 #15039

Closed
p5pRT opened this issue Nov 9, 2015 · 7 comments
Closed

double free and segfault in Perl v5.23.4-81-g96524c2 #15039

p5pRT opened this issue Nov 9, 2015 · 7 comments

Comments

@p5pRT
Copy link

p5pRT commented Nov 9, 2015

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

Searchable as RT126602$

@p5pRT
Copy link
Author

p5pRT commented Nov 9, 2015

From @geeknik

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

@p5pRT
Copy link
Author

p5pRT commented Nov 9, 2015

From @dcollinsn

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​:

# 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-archive.perl.org/perl5/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

@p5pRT
Copy link
Author

p5pRT commented Nov 9, 2015

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

@p5pRT
Copy link
Author

p5pRT commented Nov 11, 2015

From @tonycoz

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.

Tony

@p5pRT
Copy link
Author

p5pRT commented Nov 11, 2015

From @tonycoz

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

@p5pRT
Copy link
Author

p5pRT commented Nov 16, 2015

From @tonycoz

On Tue Nov 10 16​:30​:56 2015, tonyc wrote​:

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 cf69025.

Tony

@p5pRT
Copy link
Author

p5pRT commented Nov 16, 2015

@tonycoz - Status changed from 'open' 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