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

Attempt to free unreferenced scalar: SV 0x5eb03f8 (memory corruption) #14595

Closed
p5pRT opened this issue Mar 17, 2015 · 18 comments
Closed

Attempt to free unreferenced scalar: SV 0x5eb03f8 (memory corruption) #14595

p5pRT opened this issue Mar 17, 2015 · 18 comments

Comments

@p5pRT
Copy link

p5pRT commented Mar 17, 2015

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

Searchable as RT124097$

@p5pRT
Copy link
Author

p5pRT commented Mar 17, 2015

From @geeknik

There is some memory corruption happening, but not sure if this is a use after free or a double free, I'll await an official explanation of what is happening here.

Built v5.21.10 (v5.21.9-259-g88d9f32) with the following command line​:

./Configure -des -Dusedevel -DDEBUGGING -Dcc=afl-gcc -Doptimize=-O2\ -g && AFL_HARDEN=1 make -j12 test-prep

Bug found with AFL (http​://lcamtuf.coredump.cx/afl)

Valgrind​:
geeknik@​deb7fuzz​:~/findings/perl5/fuzzer02/crashes$ valgrind -q ~/perl/perl test159-min
==18863== Invalid write of size 8
==18863== at 0xAF06A0​: Perl_leave_scope (scope.c​:1231)
==18863== by 0xEA90B0​: Perl_pp_sort (pp_sort.c​:1763)
==18863== by 0x7CA22E​: Perl_runops_debug (dump.c​:2234)
==18863== by 0x53C088​: perl_run (perl.c​:2441)
==18863== by 0x42B167​: main (perlmain.c​:116)
==18863== Address 0x5edbba0 is 0 bytes inside a block of size 80 free'd
==18863== at 0x4C27D4E​: free (vg_replace_malloc.c​:427)
==18863== by 0x5428A7​: Perl_gp_free (gv.c​:2584)
==18863== by 0x95C78B​: Perl_sv_setsv_flags (sv.c​:4532)
==18863== by 0x8B42F7​: Perl_pp_sassign (pp_hot.c​:231)
==18863== by 0x7CA22E​: Perl_runops_debug (dump.c​:2234)
==18863== by 0xE89180​: S_sortcv (pp_sort.c​:1785)
==18863== by 0xE90417​: S_mergesortsv (pp_sort.c​:197)
==18863== by 0xEA6A58​: Perl_pp_sort (pp_sort.c​:1464)
==18863== by 0x7CA22E​: Perl_runops_debug (dump.c​:2234)
==18863== by 0x53C088​: perl_run (perl.c​:2441)
==18863== by 0x42B167​: main (perlmain.c​:116)
==18863==
Can't locate object method "t" via package "r" (perhaps you forgot to load "r"?) at test159-min line 1.
Attempt to free unreferenced scalar​: SV 0x5eb03f8 at test159-min line 1.

GDB​:
gdb-peda$ file ~/perl/perl
gdb-peda$ set args test159-min
gdb-peda$ r
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
*** glibc detected *** /home/geeknik/perl/perl​: malloc()​: memory corruption​: 0x00000000011e1768 ***
======= Backtrace​: =========
/lib/x86_64-linux-gnu/libc.so.6(+0x75be6)[0x7ffff6dd3be6]
/lib/x86_64-linux-gnu/libc.so.6(+0x78c53)[0x7ffff6dd6c53]
/lib/x86_64-linux-gnu/libc.so.6(__libc_calloc+0xc2)[0x7ffff6dd8012]
/home/geeknik/perl/perl(Perl_safesyscalloc+0x3a5)[0x7daca5]
/home/geeknik/perl/perl(PerlIOBuf_get_base+0x1ba)[0xd7b95a]
/home/geeknik/perl/perl(PerlIOBuf_write+0x12ae)[0xd9a34e]
/home/geeknik/perl/perl(Perl_do_print+0x2ab)[0xc40ceb]
/home/geeknik/perl/perl(Perl_write_to_stderr+0x21f)[0x7d7b9f]
/home/geeknik/perl/perl(Perl_die_unwind+0xeb0)[0xb4e3a0]
/home/geeknik/perl/perl(Perl_vcroak+0xed)[0x7d9eed]
/home/geeknik/perl/perl[0x7da4b2]
/home/geeknik/perl/perl(Perl_gv_fetchmethod_pvn_flags+0x24f0)[0x553130]
/home/geeknik/perl/perl(Perl_gv_fetchmethod_sv_flags+0x116)[0x553446]
/home/geeknik/perl/perl(Perl_pp_method_named+0xbf0)[0x9001e0]
/home/geeknik/perl/perl(Perl_runops_debug+0x4cf)[0x7ca22f]
/home/geeknik/perl/perl(perl_run+0x1759)[0x53c089]
/home/geeknik/perl/perl(main+0x408)[0x42b168]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xfd)[0x7ffff6d7cead]
/home/geeknik/perl/perl[0x42b1dd]
======= Memory map​: ========
00400000-00fc7000 r-xp 00000000 fe​:00 1711840 /home/geeknik/perl/perl
011c7000-011ca000 rw-p 00bc7000 fe​:00 1711840 /home/geeknik/perl/perl
011ca000-0120e000 rw-p 00000000 00​:00 0 [heap]
7ffff0000000-7ffff0021000 rw-p 00000000 00​:00 0
7ffff0021000-7ffff4000000 ---p 00000000 00​:00 0
7ffff6b48000-7ffff6b5d000 r-xp 00000000 fe​:00 1048580 /lib/x86_64-linux-gnu/libgcc_s.so.1
7ffff6b5d000-7ffff6d5d000 ---p 00015000 fe​:00 1048580 /lib/x86_64-linux-gnu/libgcc_s.so.1
7ffff6d5d000-7ffff6d5e000 rw-p 00015000 fe​:00 1048580 /lib/x86_64-linux-gnu/libgcc_s.so.1
7ffff6d5e000-7ffff6edf000 r-xp 00000000 fe​:00 1169701 /lib/x86_64-linux-gnu/libc-2.13.so
7ffff6edf000-7ffff70df000 ---p 00181000 fe​:00 1169701 /lib/x86_64-linux-gnu/libc-2.13.so
7ffff70df000-7ffff70e3000 r--p 00181000 fe​:00 1169701 /lib/x86_64-linux-gnu/libc-2.13.so
7ffff70e3000-7ffff70e4000 rw-p 00185000 fe​:00 1169701 /lib/x86_64-linux-gnu/libc-2.13.so
7ffff70e4000-7ffff70e9000 rw-p 00000000 00​:00 0
7ffff70e9000-7ffff70eb000 r-xp 00000000 fe​:00 1169704 /lib/x86_64-linux-gnu/libutil-2.13.so
7ffff70eb000-7ffff72ea000 ---p 00002000 fe​:00 1169704 /lib/x86_64-linux-gnu/libutil-2.13.so
7ffff72ea000-7ffff72eb000 r--p 00001000 fe​:00 1169704 /lib/x86_64-linux-gnu/libutil-2.13.so
7ffff72eb000-7ffff72ec000 rw-p 00002000 fe​:00 1169704 /lib/x86_64-linux-gnu/libutil-2.13.so
7ffff72ec000-7ffff72f4000 r-xp 00000000 fe​:00 1169708 /lib/x86_64-linux-gnu/libcrypt-2.13.so
7ffff72f4000-7ffff74f3000 ---p 00008000 fe​:00 1169708 /lib/x86_64-linux-gnu/libcrypt-2.13.so
7ffff74f3000-7ffff74f4000 r--p 00007000 fe​:00 1169708 /lib/x86_64-linux-gnu/libcrypt-2.13.so
7ffff74f4000-7ffff74f5000 rw-p 00008000 fe​:00 1169708 /lib/x86_64-linux-gnu/libcrypt-2.13.so
7ffff74f5000-7ffff7523000 rw-p 00000000 00​:00 0
7ffff7523000-7ffff75a4000 r-xp 00000000 fe​:00 1169695 /lib/x86_64-linux-gnu/libm-2.13.so
7ffff75a4000-7ffff77a3000 ---p 00081000 fe​:00 1169695 /lib/x86_64-linux-gnu/libm-2.13.so
7ffff77a3000-7ffff77a4000 r--p 00080000 fe​:00 1169695 /lib/x86_64-linux-gnu/libm-2.13.so
7ffff77a4000-7ffff77a5000 rw-p 00081000 fe​:00 1169695 /lib/x86_64-linux-gnu/libm-2.13.so
7ffff77a5000-7ffff77a7000 r-xp 00000000 fe​:00 1169707 /lib/x86_64-linux-gnu/libdl-2.13.so
7ffff77a7000-7ffff79a7000 ---p 00002000 fe​:00 1169707 /lib/x86_64-linux-gnu/libdl-2.13.so
7ffff79a7000-7ffff79a8000 r--p 00002000 fe​:00 1169707 /lib/x86_64-linux-gnu/libdl-2.13.so
7ffff79a8000-7ffff79a9000 rw-p 00003000 fe​:00 1169707 /lib/x86_64-linux-gnu/libdl-2.13.so
7ffff79a9000-7ffff79be000 r-xp 00000000 fe​:00 1169698 /lib/x86_64-linux-gnu/libnsl-2.13.so
7ffff79be000-7ffff7bbd000 ---p 00015000 fe​:00 1169698 /lib/x86_64-linux-gnu/libnsl-2.13.so
7ffff7bbd000-7ffff7bbe000 r--p 00014000 fe​:00 1169698 /lib/x86_64-linux-gnu/libnsl-2.13.so
7ffff7bbe000-7ffff7bbf000 rw-p 00015000 fe​:00 1169698 /lib/x86_64-linux-gnu/libnsl-2.13.so
7ffff7bbf000-7ffff7bc1000 rw-p 00000000 00​:00 0
7ffff7bc1000-7ffff7bd8000 r-xp 00000000 fe​:00 1169716 /lib/x86_64-linux-gnu/libpthread-2.13.so
7ffff7bd8000-7ffff7dd7000 ---p 00017000 fe​:00 1169716 /lib/x86_64-linux-gnu/libpthread-2.13.so
7ffff7dd7000-7ffff7dd8000 r--p 00016000 fe​:00 1169716 /lib/x86_64-linux-gnu/libpthread-2.13.so
7ffff7dd8000-7ffff7dd9000 rw-p 00017000 fe​:00 1169716 /lib/x86_64-linux-gnu/libpthread-2.13.so
7ffff7dd9000-7ffff7ddd000 rw-p 00000000 00​:00 0
7ffff7ddd000-7ffff7dfd000 r-xp 00000000 fe​:00 1169713 /lib/x86_64-linux-gnu/ld-2.13.so
7ffff7e65000-7ffff7fdc000 r--p 00000000 fe​:00 2758480 /usr/lib/locale/locale-archive
7ffff7fdc000-7ffff7fe1000 rw-p 00000000 00​:00 0
7ffff7ff9000-7ffff7ffb000 rw-p 00000000 00​:00 0
7ffff7ffb000-7ffff7ffc000 r-xp 00000000 00​:00 0 [vdso]
7ffff7ffc000-7ffff7ffd000 r--p 0001f000 fe​:00 1169713 /lib/x86_64-linux-gnu/ld-2.13.so
7ffff7ffd000-7ffff7ffe000 rw-p 00020000 fe​:00 1169713 /lib/x86_64-linux-gnu/ld-2.13.so
7ffff7ffe000-7ffff7fff000 rw-p 00000000 00​:00 0
7ffffffde000-7ffffffff000 rw-p 00000000 00​:00 0 [stack]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00​:00 0 [vsyscall]

Program received signal SIGABRT, Aborted.
[----------------------------------registers-----------------------------------]
RAX​: 0x0
RBX​: 0x0
RCX​: 0xffffffffffffffff
RDX​: 0x6
RSI​: 0x3b98
RDI​: 0x3b98
RBP​: 0x7fffffffdc00 --> 0x3
RSP​: 0x7fffffffd1b8 --> 0x7ffff6d933e0 (<*__GI_abort+384>​: mov rdx,QWORD PTR fs​:0x10)
RIP​: 0x7ffff6d90165 (<*__GI_raise+53>​: cmp rax,0xfffffffffffff000)
R8 : 0x7ffff6ea3e40 ("0123456789abcdefghijklmnopqrstuvwxyz")
R9 : 0x4120c8 --> 0x7268747062696c00 ('')
R10​: 0x8
R11​: 0x202
R12​: 0x8
R13​: 0x7fffffffd4e0 ("65000-7ffff7fdc000 r--p 00000000 fe​:00 2758480", ' ' <repeats 20 times>, "/usr/lib/locale/locale-archive\n7ffff7fdc000-7ffff7fe1000 rw-p 00000000 00​:00 0 \n7ffff7ff9000-7ffff7ffb000 rw-p 00000000 00​:00 0 \n7ffff"...)
R14​: 0x64 ('d')
R15​: 0x7
EFLAGS​: 0x202 (carry parity adjust zero sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
  0x7ffff6d9015b <*__GI_raise+43>​: movsxd rdi,eax
  0x7ffff6d9015e <*__GI_raise+46>​: mov eax,0xea
  0x7ffff6d90163 <*__GI_raise+51>​: syscall
=> 0x7ffff6d90165 <*__GI_raise+53>​: cmp rax,0xfffffffffffff000
  0x7ffff6d9016b <*__GI_raise+59>​: ja 0x7ffff6d90182 <*__GI_raise+82>
  0x7ffff6d9016d <*__GI_raise+61>​: repz ret
  0x7ffff6d9016f <*__GI_raise+63>​: nop
  0x7ffff6d90170 <*__GI_raise+64>​: test eax,eax
[------------------------------------stack-------------------------------------]
0000| 0x7fffffffd1b8 --> 0x7ffff6d933e0 (<*__GI_abort+384>​: mov rdx,QWORD PTR fs​:0x10)
0008| 0x7fffffffd1c0 --> 0x7fffffffd2a8 --> 0x0
0016| 0x7fffffffd1c8 --> 0x7fffffffd290 --> 0x0
0024| 0x7fffffffd1d0 --> 0x7fffffffe60e ("/home/geeknik/perl/perl")
0032| 0x7fffffffd1d8 --> 0x17
0040| 0x7fffffffd1e0 --> 0x7ffff6eac11b --> 0x6c000a5d0078305b ('[0x')
0048| 0x7fffffffd1e8 --> 0x3
0056| 0x7fffffffd1f0 --> 0x7fffffffd29a --> 0x0
[------------------------------------------------------------------------------]
Legend​: code, data, rodata, value
Stopped reason​: SIGABRT
0x00007ffff6d90165 in *__GI_raise (sig=<optimized out>) at ../nptl/sysdeps/unix/sysv/linux/raise.c​:64
64 ../nptl/sysdeps/unix/sysv/linux/raise.c​: No such file or directory.
gdb-peda$ bt
#0 0x00007ffff6d90165 in *__GI_raise (sig=<optimized out>) at ../nptl/sysdeps/unix/sysv/linux/raise.c​:64
#1 0x00007ffff6d933e0 in *__GI_abort () at abort.c​:92
#2 0x00007ffff6dca39b in __libc_message (do_abort=<optimized out>, fmt=<optimized out>)
  at ../sysdeps/unix/sysv/linux/libc_fatal.c​:189
#3 0x00007ffff6dd3be6 in malloc_printerr (action=0x3, str=0x7ffff6eaac0a "malloc()​: memory corruption",
  ptr=<optimized out>) at malloc.c​:6312
#4 0x00007ffff6dd6c53 in _int_malloc (av=0x7ffff70e4e40, bytes=<optimized out>) at malloc.c​:4425
#5 0x00007ffff6dd8012 in __libc_calloc (n=<optimized out>, elem_size=<optimized out>) at malloc.c​:4094
#6 0x00000000007daca5 in Perl_safesyscalloc () at util.c​:436
#7 0x0000000000d7b95a in PerlIOBuf_get_base () at perlio.c​:4267
#8 0x0000000000d9a34e in PerlIOBuf_write () at perlio.c​:1781
#9 0x0000000000c40ceb in Perl_do_print ()
#10 0x00000000007d7b9f in Perl_write_to_stderr () at util.c​:1486
#11 0x0000000000b4e3a0 in Perl_die_unwind () at pp_ctl.c​:1686
#12 0x00000000007d9eed in Perl_vcroak () at util.c​:1696
#13 0x00000000007da4b2 in Perl_croak () at util.c​:1741
#14 0x0000000000553130 in Perl_gv_fetchmethod_pvn_flags () at gv.c​:1107
#15 0x0000000000553446 in Perl_gv_fetchmethod_sv_flags () at gv.c​:999
#16 0x00000000009001e0 in Perl_pp_method_named () at pp_hot.c​:3544
#17 0x00000000007ca22f in Perl_runops_debug () at dump.c​:2234
#18 0x000000000053c089 in perl_run ()
#19 0x000000000042b168 in main () at perlmain.c​:116
#20 0x00007ffff6d7cead 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=0x7fffffffe388) at libc-start.c​:244
#21 0x000000000042b1dd in _start ()
gdb-peda$ i r
rax 0x0 0x0
rbx 0x0 0x0
rcx 0xffffffffffffffff 0xffffffffffffffff
rdx 0x6 0x6
rsi 0x3b98 0x3b98
rdi 0x3b98 0x3b98
rbp 0x7fffffffdc00 0x7fffffffdc00
rsp 0x7fffffffd1b8 0x7fffffffd1b8
r8 0x7ffff6ea3e40 0x7ffff6ea3e40
r9 0x4120c8 0x4120c8
r10 0x8 0x8
r11 0x202 0x202
r12 0x8 0x8
r13 0x7fffffffd4e0 0x7fffffffd4e0
r14 0x64 0x64
r15 0x7 0x7
rip 0x7ffff6d90165 0x7ffff6d90165 <*__GI_raise+53>
eflags 0x202 [ IF ]
cs 0x33 0x33
ss 0x2b 0x2b
ds 0x0 0x0
es 0x0 0x0
fs 0x0 0x0
gs 0x0 0x0

Hexdump of the minimized 25-byte test case​:
0000000 2074 2072 6f73 7472 287b 2c30 622a 303d
0000010 3d29 307e 307d 2e2e 0031
0000019

System Info​: Debian 7, Kernel 3.2.65-1+deb7u1 x86_64, GCC 4.9.2, libc 2.13-38+deb7u8

**NOTE** When I was minimizing the test case from 43-bytes to 25-bytes, glibc started popping off a bunch of messages such as these, figured it might relevant​:

*** glibc detected *** /home/geeknik/perl/perl​: invalid fastbin entry (free)​: 0x0000000002790330 ***
*** glibc detected *** /home/geeknik/perl/perl​: invalid fastbin entry (free)​: 0x0000000001433330 ***
*** glibc detected *** /home/geeknik/perl/perl​: corrupted double-linked list​: 0x00000000031a6320 ***
*** glibc detected *** /home/geeknik/perl/perl​: invalid fastbin entry (free)​: 0x0000000001b31330 ***
*** glibc detected *** /home/geeknik/perl/perl​: invalid fastbin entry (free)​: 0x0000000001f02320 ***

The original test case, test159, causes a SIGSEGV while test 159-min causes a SIGABRT. I've attached both test cases, but did not including any gdb or valgrind output from the original test case.

@p5pRT
Copy link
Author

p5pRT commented Mar 17, 2015

From @geeknik

test159

@p5pRT
Copy link
Author

p5pRT commented Mar 17, 2015

From @geeknik

test159-min

@p5pRT
Copy link
Author

p5pRT commented Mar 17, 2015

From @geeknik

Affects (v5.21.7 (v5.21.6-602-ge9d2bd8) as well.

perl -e 't r sort{(0,*b=0)=~0}0..1'
*** glibc detected *** perl​: invalid fastbin entry (free)​: 0x0000000002754530 ***
======= Backtrace​: =========
/lib/x86_64-linux-gnu/libc.so.6(+0x75be6)[0x7fbbcfe30be6]
/lib/x86_64-linux-gnu/libc.so.6(+0x7b733)[0x7fbbcfe36733]
/lib/x86_64-linux-gnu/libc.so.6(realloc+0xf0)[0x7fbbcfe36bd0]
perl(Perl_safesysrealloc+0xdd)[0x6cc36d]
perl(Perl_sv_grow+0x373)[0x7e7623]
perl(Perl_sv_catpvn_flags+0x360)[0x820450]
perl(Perl_sv_vcatpvfn_flags+0x13c8)[0x7c0e68]
perl(Perl_sv_vsetpvfn+0xb3)[0x7fc8d3]
perl(Perl_vmess+0x14f)[0x6ceacf]
perl(Perl_vcroak+0x95)[0x6cd155]
perl[0x6cd416]
perl(Perl_gv_fetchmethod_pvn_flags+0x201b)[0x5112eb]
perl(Perl_gv_fetchmethod_sv_flags+0x12a)[0x51161a]
perl(Perl_pp_method_named+0x9f0)[0x7a7150]
perl(Perl_runops_standard+0x5b)[0x775a6b]
perl(perl_run+0xf7f)[0x4f3dbf]
perl(main+0x40c)[0x42ab1c]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xfd)[0x7fbbcfdd9ead]
perl[0x42ab95]
======= Memory map​: ========
00400000-00c20000 r-xp 00000000 fe​:00 2907415 /usr/local/bin/perl
00e1f000-00e23000 rw-p 0081f000 fe​:00 2907415 /usr/local/bin/perl
00e23000-00e24000 rw-p 00000000 00​:00 0
02734000-02776000 rw-p 00000000 00​:00 0 [heap]
7fbbc8000000-7fbbc8021000 rw-p 00000000 00​:00 0
7fbbc8021000-7fbbcc000000 ---p 00000000 00​:00 0
7fbbcf989000-7fbbcf99e000 r-xp 00000000 fe​:00 1048580 /lib/x86_64-linux-gnu/libgcc_s.so.1
7fbbcf99e000-7fbbcfb9e000 ---p 00015000 fe​:00 1048580 /lib/x86_64-linux-gnu/libgcc_s.so.1
7fbbcfb9e000-7fbbcfb9f000 rw-p 00015000 fe​:00 1048580 /lib/x86_64-linux-gnu/libgcc_s.so.1
7fbbcfb9f000-7fbbcfbb6000 r-xp 00000000 fe​:00 1169716 /lib/x86_64-linux-gnu/libpthread-2.13.so
7fbbcfbb6000-7fbbcfdb5000 ---p 00017000 fe​:00 1169716 /lib/x86_64-linux-gnu/libpthread-2.13.so
7fbbcfdb5000-7fbbcfdb6000 r--p 00016000 fe​:00 1169716 /lib/x86_64-linux-gnu/libpthread-2.13.so
7fbbcfdb6000-7fbbcfdb7000 rw-p 00017000 fe​:00 1169716 /lib/x86_64-linux-gnu/libpthread-2.13.so
7fbbcfdb7000-7fbbcfdbb000 rw-p 00000000 00​:00 0
7fbbcfdbb000-7fbbcff3c000 r-xp 00000000 fe​:00 1169701 /lib/x86_64-linux-gnu/libc-2.13.so
7fbbcff3c000-7fbbd013c000 ---p 00181000 fe​:00 1169701 /lib/x86_64-linux-gnu/libc-2.13.so
7fbbd013c000-7fbbd0140000 r--p 00181000 fe​:00 1169701 /lib/x86_64-linux-gnu/libc-2.13.so
7fbbd0140000-7fbbd0141000 rw-p 00185000 fe​:00 1169701 /lib/x86_64-linux-gnu/libc-2.13.so
7fbbd0141000-7fbbd0146000 rw-p 00000000 00​:00 0
7fbbd0146000-7fbbd0148000 r-xp 00000000 fe​:00 1169704 /lib/x86_64-linux-gnu/libutil-2.13.so
7fbbd0148000-7fbbd0347000 ---p 00002000 fe​:00 1169704 /lib/x86_64-linux-gnu/libutil-2.13.so
7fbbd0347000-7fbbd0348000 r--p 00001000 fe​:00 1169704 /lib/x86_64-linux-gnu/libutil-2.13.so
7fbbd0348000-7fbbd0349000 rw-p 00002000 fe​:00 1169704 /lib/x86_64-linux-gnu/libutil-2.13.so
7fbbd0349000-7fbbd0351000 r-xp 00000000 fe​:00 1169708 /lib/x86_64-linux-gnu/libcrypt-2.13.so
7fbbd0351000-7fbbd0550000 ---p 00008000 fe​:00 1169708 /lib/x86_64-linux-gnu/libcrypt-2.13.so
7fbbd0550000-7fbbd0551000 r--p 00007000 fe​:00 1169708 /lib/x86_64-linux-gnu/libcrypt-2.13.so
7fbbd0551000-7fbbd0552000 rw-p 00008000 fe​:00 1169708 /lib/x86_64-linux-gnu/libcrypt-2.13.so
7fbbd0552000-7fbbd0580000 rw-p 00000000 00​:00 0
7fbbd0580000-7fbbd0601000 r-xp 00000000 fe​:00 1169695 /lib/x86_64-linux-gnu/libm-2.13.so
7fbbd0601000-7fbbd0800000 ---p 00081000 fe​:00 1169695 /lib/x86_64-linux-gnu/libm-2.13.so
7fbbd0800000-7fbbd0801000 r--p 00080000 fe​:00 1169695 /lib/x86_64-linux-gnu/libm-2.13.so
7fbbd0801000-7fbbd0802000 rw-p 00081000 fe​:00 1169695 /lib/x86_64-linux-gnu/libm-2.13.so
7fbbd0802000-7fbbd0804000 r-xp 00000000 fe​:00 1169707 /lib/x86_64-linux-gnu/libdl-2.13.so
7fbbd0804000-7fbbd0a04000 ---p 00002000 fe​:00 1169707 /lib/x86_64-linux-gnu/libdl-2.13.so
7fbbd0a04000-7fbbd0a05000 r--p 00002000 fe​:00 1169707 /lib/x86_64-linux-gnu/libdl-2.13.so
7fbbd0a05000-7fbbd0a06000 rw-p 00003000 fe​:00 1169707 /lib/x86_64-linux-gnu/libdl-2.13.so
7fbbd0a06000-7fbbd0a1b000 r-xp 00000000 fe​:00 1169698 /lib/x86_64-linux-gnu/libnsl-2.13.so
7fbbd0a1b000-7fbbd0c1a000 ---p 00015000 fe​:00 1169698 /lib/x86_64-linux-gnu/libnsl-2.13.so
7fbbd0c1a000-7fbbd0c1b000 r--p 00014000 fe​:00 1169698 /lib/x86_64-linux-gnu/libnsl-2.13.so
7fbbd0c1b000-7fbbd0c1c000 rw-p 00015000 fe​:00 1169698 /lib/x86_64-linux-gnu/libnsl-2.13.so
7fbbd0c1c000-7fbbd0c1e000 rw-p 00000000 00​:00 0
7fbbd0c1e000-7fbbd0c3e000 r-xp 00000000 fe​:00 1169713 /lib/x86_64-linux-gnu/ld-2.13.so
7fbbd0ca7000-7fbbd0e1e000 r--p 00000000 fe​:00 2758480 /usr/lib/locale/locale-archive
7fbbd0e1e000-7fbbd0e23000 rw-p 00000000 00​:00 0
7fbbd0e3b000-7fbbd0e3d000 rw-p 00000000 00​:00 0
7fbbd0e3d000-7fbbd0e3e000 r--p 0001f000 fe​:00 1169713 /lib/x86_64-linux-gnu/ld-2.13.so
7fbbd0e3e000-7fbbd0e3f000 rw-p 00020000 fe​:00 1169713 /lib/x86_64-linux-gnu/ld-2.13.so
7fbbd0e3f000-7fbbd0e40000 rw-p 00000000 00​:00 0
7ffd1bd8c000-7ffd1bdad000 rw-p 00000000 00​:00 0 [stack]
7ffd1bdeb000-7ffd1bdec000 r-xp 00000000 00​:00 0 [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00​:00 0 [vsyscall]
Aborted (core dumped)

gdb-peda$ file perl
gdb-peda$ set args test159-min
gdb-peda$ r
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
*** glibc detected *** /usr/local/bin/perl​: malloc()​: memory corruption​: 0x0000000000e3a750 ***
======= Backtrace​: =========
/lib/x86_64-linux-gnu/libc.so.6(+0x75be6)[0x7ffff6fefbe6]
/lib/x86_64-linux-gnu/libc.so.6(+0x78c53)[0x7ffff6ff2c53]
/lib/x86_64-linux-gnu/libc.so.6(__libc_calloc+0xc2)[0x7ffff6ff4012]
/usr/local/bin/perl(Perl_safesyscalloc+0x165)[0x6cd585]
/usr/local/bin/perl(PerlIOBuf_get_base+0x1ca)[0xa9201a]
/usr/local/bin/perl(PerlIOBuf_write+0x1196)[0xaa5346]
/usr/local/bin/perl(Perl_do_print+0x2bb)[0x9afefb]
/usr/local/bin/perl(Perl_write_to_stderr+0x23b)[0x6c92ab]
/usr/local/bin/perl(Perl_die_unwind+0x1220)[0x903340]
/usr/local/bin/perl(Perl_vcroak+0xea)[0x6cd1aa]
/usr/local/bin/perl[0x6cd416]
/usr/local/bin/perl(Perl_gv_fetchmethod_pvn_flags+0x201b)[0x5112eb]
/usr/local/bin/perl(Perl_gv_fetchmethod_sv_flags+0x12a)[0x51161a]
/usr/local/bin/perl(Perl_pp_method_named+0x9f0)[0x7a7150]
/usr/local/bin/perl(Perl_runops_standard+0x5b)[0x775a6b]
/usr/local/bin/perl(perl_run+0xf7f)[0x4f3dbf]
/usr/local/bin/perl(main+0x40c)[0x42ab1c]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xfd)[0x7ffff6f98ead]
/usr/local/bin/perl[0x42ab95]
======= Memory map​: ========
00400000-00c20000 r-xp 00000000 fe​:00 2907415 /usr/local/bin/perl
00e1f000-00e23000 rw-p 0081f000 fe​:00 2907415 /usr/local/bin/perl
00e23000-00e67000 rw-p 00000000 00​:00 0 [heap]
7ffff0000000-7ffff0021000 rw-p 00000000 00​:00 0
7ffff0021000-7ffff4000000 ---p 00000000 00​:00 0
7ffff6b48000-7ffff6b5d000 r-xp 00000000 fe​:00 1048580 /lib/x86_64-linux-gnu/libgcc_s.so.1
7ffff6b5d000-7ffff6d5d000 ---p 00015000 fe​:00 1048580 /lib/x86_64-linux-gnu/libgcc_s.so.1
7ffff6d5d000-7ffff6d5e000 rw-p 00015000 fe​:00 1048580 /lib/x86_64-linux-gnu/libgcc_s.so.1
7ffff6d5e000-7ffff6d75000 r-xp 00000000 fe​:00 1169716 /lib/x86_64-linux-gnu/libpthread-2.13.so
7ffff6d75000-7ffff6f74000 ---p 00017000 fe​:00 1169716 /lib/x86_64-linux-gnu/libpthread-2.13.so
7ffff6f74000-7ffff6f75000 r--p 00016000 fe​:00 1169716 /lib/x86_64-linux-gnu/libpthread-2.13.so
7ffff6f75000-7ffff6f76000 rw-p 00017000 fe​:00 1169716 /lib/x86_64-linux-gnu/libpthread-2.13.so
7ffff6f76000-7ffff6f7a000 rw-p 00000000 00​:00 0
7ffff6f7a000-7ffff70fb000 r-xp 00000000 fe​:00 1169701 /lib/x86_64-linux-gnu/libc-2.13.so
7ffff70fb000-7ffff72fb000 ---p 00181000 fe​:00 1169701 /lib/x86_64-linux-gnu/libc-2.13.so
7ffff72fb000-7ffff72ff000 r--p 00181000 fe​:00 1169701 /lib/x86_64-linux-gnu/libc-2.13.so
7ffff72ff000-7ffff7300000 rw-p 00185000 fe​:00 1169701 /lib/x86_64-linux-gnu/libc-2.13.so
7ffff7300000-7ffff7305000 rw-p 00000000 00​:00 0
7ffff7305000-7ffff7307000 r-xp 00000000 fe​:00 1169704 /lib/x86_64-linux-gnu/libutil-2.13.so
7ffff7307000-7ffff7506000 ---p 00002000 fe​:00 1169704 /lib/x86_64-linux-gnu/libutil-2.13.so
7ffff7506000-7ffff7507000 r--p 00001000 fe​:00 1169704 /lib/x86_64-linux-gnu/libutil-2.13.so
7ffff7507000-7ffff7508000 rw-p 00002000 fe​:00 1169704 /lib/x86_64-linux-gnu/libutil-2.13.so
7ffff7508000-7ffff7510000 r-xp 00000000 fe​:00 1169708 /lib/x86_64-linux-gnu/libcrypt-2.13.so
7ffff7510000-7ffff770f000 ---p 00008000 fe​:00 1169708 /lib/x86_64-linux-gnu/libcrypt-2.13.so
7ffff770f000-7ffff7710000 r--p 00007000 fe​:00 1169708 /lib/x86_64-linux-gnu/libcrypt-2.13.so
7ffff7710000-7ffff7711000 rw-p 00008000 fe​:00 1169708 /lib/x86_64-linux-gnu/libcrypt-2.13.so
7ffff7711000-7ffff773f000 rw-p 00000000 00​:00 0
7ffff773f000-7ffff77c0000 r-xp 00000000 fe​:00 1169695 /lib/x86_64-linux-gnu/libm-2.13.so
7ffff77c0000-7ffff79bf000 ---p 00081000 fe​:00 1169695 /lib/x86_64-linux-gnu/libm-2.13.so
7ffff79bf000-7ffff79c0000 r--p 00080000 fe​:00 1169695 /lib/x86_64-linux-gnu/libm-2.13.so
7ffff79c0000-7ffff79c1000 rw-p 00081000 fe​:00 1169695 /lib/x86_64-linux-gnu/libm-2.13.so
7ffff79c1000-7ffff79c3000 r-xp 00000000 fe​:00 1169707 /lib/x86_64-linux-gnu/libdl-2.13.so
7ffff79c3000-7ffff7bc3000 ---p 00002000 fe​:00 1169707 /lib/x86_64-linux-gnu/libdl-2.13.so
7ffff7bc3000-7ffff7bc4000 r--p 00002000 fe​:00 1169707 /lib/x86_64-linux-gnu/libdl-2.13.so
7ffff7bc4000-7ffff7bc5000 rw-p 00003000 fe​:00 1169707 /lib/x86_64-linux-gnu/libdl-2.13.so
7ffff7bc5000-7ffff7bda000 r-xp 00000000 fe​:00 1169698 /lib/x86_64-linux-gnu/libnsl-2.13.so
7ffff7bda000-7ffff7dd9000 ---p 00015000 fe​:00 1169698 /lib/x86_64-linux-gnu/libnsl-2.13.so
7ffff7dd9000-7ffff7dda000 r--p 00014000 fe​:00 1169698 /lib/x86_64-linux-gnu/libnsl-2.13.so
7ffff7dda000-7ffff7ddb000 rw-p 00015000 fe​:00 1169698 /lib/x86_64-linux-gnu/libnsl-2.13.so
7ffff7ddb000-7ffff7ddd000 rw-p 00000000 00​:00 0
7ffff7ddd000-7ffff7dfd000 r-xp 00000000 fe​:00 1169713 /lib/x86_64-linux-gnu/ld-2.13.so
7ffff7e65000-7ffff7fdc000 r--p 00000000 fe​:00 2758480 /usr/lib/locale/locale-archive
7ffff7fdc000-7ffff7fe1000 rw-p 00000000 00​:00 0
7ffff7ff9000-7ffff7ffb000 rw-p 00000000 00​:00 0
7ffff7ffb000-7ffff7ffc000 r-xp 00000000 00​:00 0 [vdso]
7ffff7ffc000-7ffff7ffd000 r--p 0001f000 fe​:00 1169713 /lib/x86_64-linux-gnu/ld-2.13.so
7ffff7ffd000-7ffff7ffe000 rw-p 00020000 fe​:00 1169713 /lib/x86_64-linux-gnu/ld-2.13.so
7ffff7ffe000-7ffff7fff000 rw-p 00000000 00​:00 0
7ffffffde000-7ffffffff000 rw-p 00000000 00​:00 0 [stack]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00​:00 0 [vsyscall]

Program received signal SIGABRT, Aborted.
[----------------------------------registers-----------------------------------]
RAX​: 0x0
RBX​: 0x0
RCX​: 0xffffffffffffffff
RDX​: 0x6
RSI​: 0x546f ('oT')
RDI​: 0x546f ('oT')
RBP​: 0x7fffffffdc30 --> 0x3
RSP​: 0x7fffffffd1e8 --> 0x7ffff6faf3e0 (<*__GI_abort+384>​: mov rdx,QWORD PTR fs​:0x10)
RIP​: 0x7ffff6fac165 (<*__GI_raise+53>​: cmp rax,0xfffffffffffff000)
R8 : 0x7ffff70bfe40 ("0123456789abcdefghijklmnopqrstuvwxyz")
R9 : 0x408f18 --> 0x0
R10​: 0x8
R11​: 0x206
R12​: 0x8
R13​: 0x7fffffffd510 ("fff7fdc000 r--p 00000000 fe​:00 2758480", ' ' <repeats 20 times>, "/usr/lib/locale/locale-archive\n7ffff7fdc000-7ffff7fe1000 rw-p 00000000 00​:00 0 \n7ffff7ff9000-7ffff7ffb000 rw-p 00000000 00​:00 0 \n7ffff7ffb000-"...)
R14​: 0x60 ('`')
R15​: 0x7
EFLAGS​: 0x206 (carry PARITY adjust zero sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
  0x7ffff6fac15b <*__GI_raise+43>​: movsxd rdi,eax
  0x7ffff6fac15e <*__GI_raise+46>​: mov eax,0xea
  0x7ffff6fac163 <*__GI_raise+51>​: syscall
=> 0x7ffff6fac165 <*__GI_raise+53>​: cmp rax,0xfffffffffffff000
  0x7ffff6fac16b <*__GI_raise+59>​: ja 0x7ffff6fac182 <*__GI_raise+82>
  0x7ffff6fac16d <*__GI_raise+61>​: repz ret
  0x7ffff6fac16f <*__GI_raise+63>​: nop
  0x7ffff6fac170 <*__GI_raise+64>​: test eax,eax
[------------------------------------stack-------------------------------------]
0000| 0x7fffffffd1e8 --> 0x7ffff6faf3e0 (<*__GI_abort+384>​: mov rdx,QWORD PTR fs​:0x10)
0008| 0x7fffffffd1f0 --> 0x7fffffffd2d8 --> 0x0
0016| 0x7fffffffd1f8 --> 0x7fffffffd2c0 --> 0x0
0024| 0x7fffffffd200 --> 0x7fffffffe616 ("/usr/local/bin/perl")
0032| 0x7fffffffd208 --> 0x13
0040| 0x7fffffffd210 --> 0x7ffff70c811b --> 0x6c000a5d0078305b ('[0x')
0048| 0x7fffffffd218 --> 0x3
0056| 0x7fffffffd220 --> 0x7fffffffd2ca --> 0x0
[------------------------------------------------------------------------------]
Legend​: code, data, rodata, value
Stopped reason​: SIGABRT
0x00007ffff6fac165 in *__GI_raise (sig=<optimized out>) at ../nptl/sysdeps/unix/sysv/linux/raise.c​:64
64 ../nptl/sysdeps/unix/sysv/linux/raise.c​: No such file or directory.

@p5pRT
Copy link
Author

p5pRT commented Mar 17, 2015

From @iabyn

On Tue, Mar 17, 2015 at 03​:24​:58AM -0700, Brian Carpenter wrote​:

==18863== Invalid write of size 8
==18863== at 0xAF06A0​: Perl_leave_scope (scope.c​:1231)
==18863== by 0xEA90B0​: Perl_pp_sort (pp_sort.c​:1763)
==18863== by 0x7CA22E​: Perl_runops_debug (dump.c​:2234)
==18863== by 0x53C088​: perl_run (perl.c​:2441)
==18863== by 0x42B167​: main (perlmain.c​:116)

on code basically like​:

  @​a = sort{ *a=0; 1} 0..1;

basically its deleting the *a glob then trying to restore the old value of
$a on scope exit. I suspect sort needs to hold a ref count on *a and *b or
something like that.

--
You never really learn to swear until you learn to drive.

@p5pRT
Copy link
Author

p5pRT commented Mar 17, 2015

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

@p5pRT
Copy link
Author

p5pRT commented Nov 26, 2015

From @tonycoz

On Tue Mar 17 09​:50​:02 2015, davem wrote​:

On Tue, Mar 17, 2015 at 03​:24​:58AM -0700, Brian Carpenter wrote​:

==18863== Invalid write of size 8
==18863== at 0xAF06A0​: Perl_leave_scope (scope.c​:1231)
==18863== by 0xEA90B0​: Perl_pp_sort (pp_sort.c​:1763)
==18863== by 0x7CA22E​: Perl_runops_debug (dump.c​:2234)
==18863== by 0x53C088​: perl_run (perl.c​:2441)
==18863== by 0x42B167​: main (perlmain.c​:116)

on code basically like​:

@&#8203;a = sort\{ \*a=0; 1\} 0\.\.1;

basically its deleting the *a glob then trying to restore the old value of
$a on scope exit. I suspect sort needs to hold a ref count on *a and *b or
something like that.

Like the attached?

Tony

@p5pRT
Copy link
Author

p5pRT commented Nov 26, 2015

From @tonycoz

0001-perl-124097-don-t-let-the-GPs-be-removed-out-from-un.patch
From 472e56692ec732c054a96072a540725842ba6051 Mon Sep 17 00:00:00 2001
From: Tony Cook <tony@develop-help.com>
Date: Thu, 26 Nov 2015 15:23:23 +1100
Subject: [perl #124097] don't let the GPs be removed out from under pp_sort

---
 pp_sort.c   | 6 ++++++
 t/op/sort.t | 5 ++++-
 2 files changed, 10 insertions(+), 1 deletion(-)

diff --git a/pp_sort.c b/pp_sort.c
index 64a67d8..f1be44f 100644
--- a/pp_sort.c
+++ b/pp_sort.c
@@ -1649,6 +1649,7 @@ PP(pp_sort)
 	    CATCH_SET(TRUE);
 	    PUSHSTACKi(PERLSI_SORT);
 	    if (!hasargs && !is_xsub) {
+                GV *first_copy, *second_copy;
 		SAVEGENERICSV(PL_firstgv);
 		SAVEGENERICSV(PL_secondgv);
 		PL_firstgv = MUTABLE_GV(SvREFCNT_inc(
@@ -1657,6 +1658,11 @@ PP(pp_sort)
 		PL_secondgv = MUTABLE_GV(SvREFCNT_inc(
 		    gv_fetchpvs("b", GV_ADD|GV_NOTQUAL, SVt_PV)
 		));
+                /* make sure the GP isn't removed out from under us */
+                first_copy = (GV*)newSVsv(MUTABLE_SV(PL_firstgv));
+                second_copy = (GV*)newSVsv(MUTABLE_SV(PL_secondgv));
+                SAVEFREESV(first_copy);
+                SAVEFREESV(second_copy);
 		SAVESPTR(GvSV(PL_firstgv));
 		SAVESPTR(GvSV(PL_secondgv));
 	    }
diff --git a/t/op/sort.t b/t/op/sort.t
index 3c76365..14a5aed 100644
--- a/t/op/sort.t
+++ b/t/op/sort.t
@@ -7,7 +7,7 @@ BEGIN {
     set_up_inc('../lib');
 }
 use warnings;
-plan(tests => 193);
+plan(tests => 194);
 
 # these shouldn't hang
 {
@@ -1127,3 +1127,6 @@ pass "no crash when sort block deletes *a and *b";
     ::is (join('-', sort f2 3,1,2,4), '1-2-3-4', "Ret: f2");
     ::is (join('-', sort f3 3,1,2,4), '1-2-3-4', "Ret: f3");
 }
+
+@a = sort{ *a=0; 1} 0..1;
+pass "No crash when GP deleted out from under us [perl 124097]";
-- 
2.1.4

@p5pRT
Copy link
Author

p5pRT commented Nov 27, 2015

From @iabyn

On Wed, Nov 25, 2015 at 08​:24​:22PM -0800, Tony Cook via RT wrote​:

On Tue Mar 17 09​:50​:02 2015, davem wrote​:

On Tue, Mar 17, 2015 at 03​:24​:58AM -0700, Brian Carpenter wrote​:

==18863== Invalid write of size 8
==18863== at 0xAF06A0​: Perl_leave_scope (scope.c​:1231)
==18863== by 0xEA90B0​: Perl_pp_sort (pp_sort.c​:1763)
==18863== by 0x7CA22E​: Perl_runops_debug (dump.c​:2234)
==18863== by 0x53C088​: perl_run (perl.c​:2441)
==18863== by 0x42B167​: main (perlmain.c​:116)

on code basically like​:

@&#8203;a = sort\{ \*a=0; 1\} 0\.\.1;

basically its deleting the *a glob then trying to restore the old value of
$a on scope exit. I suspect sort needs to hold a ref count on *a and *b or
something like that.

Like the attached?

+ /* make sure the GP isn't removed out from under us */
+ first_copy = (GV*)newSVsv(MUTABLE_SV(PL_firstgv));
+ second_copy = (GV*)newSVsv(MUTABLE_SV(PL_secondgv));
+ SAVEFREESV(first_copy);
+ SAVEFREESV(second_copy);

Wouldn't save_gp(PL_firstgv, 0) be more efficient?

--
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 Nov 29, 2015

From @tonycoz

On Fri, Nov 27, 2015 at 01​:42​:30PM +0000, Dave Mitchell wrote​:

On Wed, Nov 25, 2015 at 08​:24​:22PM -0800, Tony Cook via RT wrote​:

Like the attached?

+ /* make sure the GP isn't removed out from under us */
+ first_copy = (GV*)newSVsv(MUTABLE_SV(PL_firstgv));
+ second_copy = (GV*)newSVsv(MUTABLE_SV(PL_secondgv));
+ SAVEFREESV(first_copy);
+ SAVEFREESV(second_copy);

Wouldn't save_gp(PL_firstgv, 0) be more efficient?

It would, but it also restores the GP to the GV, and the user has
chosen to replace it - should we be restoring it?

With save_gp​:

$ ./perl -e 'sub a { print "hello\n" } a(); @​x = sort { *a = sub { print "goodbye\n" }; 1 } 0 .. 1; a();'
hello
hello

With the patch I supplied​:

$ ./perl -e 'sub a { print "hello\n" } a(); @​x = sort { *a = sub { print "goodbye\n" }; 1 } 0 .. 1; a();'
hello
goodbye

Tony

@p5pRT
Copy link
Author

p5pRT commented Nov 30, 2015

From @iabyn

On Mon, Nov 30, 2015 at 10​:14​:31AM +1100, Tony Cook wrote​:

On Fri, Nov 27, 2015 at 01​:42​:30PM +0000, Dave Mitchell wrote​:

On Wed, Nov 25, 2015 at 08​:24​:22PM -0800, Tony Cook via RT wrote​:

Like the attached?

+ /* make sure the GP isn't removed out from under us */
+ first_copy = (GV*)newSVsv(MUTABLE_SV(PL_firstgv));
+ second_copy = (GV*)newSVsv(MUTABLE_SV(PL_secondgv));
+ SAVEFREESV(first_copy);
+ SAVEFREESV(second_copy);

Wouldn't save_gp(PL_firstgv, 0) be more efficient?

It would, but it also restores the GP to the GV, and the user has
chosen to replace it - should we be restoring it?

With save_gp​:

$ ./perl -e 'sub a { print "hello\n" } a(); @​x = sort { *a = sub { print "goodbye\n" }; 1 } 0 .. 1; a();'
hello
hello

With the patch I supplied​:

$ ./perl -e 'sub a { print "hello\n" } a(); @​x = sort { *a = sub { print "goodbye\n" }; 1 } 0 .. 1; a();'
hello
goodbye

I'd expect sort {block} 1, 2 to have the same semantics as​:

  {
  local *a = \1;
  local *b = \2;
  { block }
  }

'local *a = ...' does a combination of

  save_gp(gv,0) via rv2gv

and

  SAVEGENERICSV(SvGV(gv)) via pp_sassign and gv_setref,

so I'd expect some combination of those to Do The Right Thing.

And local does seem to Do The Right Thing​:

  sub a { print "hello\n" }
  a();
  {
  local *a = \1;
  {
  *a = sub { print "goodbye\n" };
  1;
  }
  }
  a()

prints​:

  hello
  goodbye

So maybe there's a way to achieve this with save_gp?

--
In England there is a special word which means the last sunshine
of the summer. That word is "spring".

@p5pRT
Copy link
Author

p5pRT commented Dec 2, 2015

From @tonycoz

On Mon Nov 30 03​:42​:06 2015, davem wrote​:

So maybe there's a way to achieve this with save_gp?

Do you mean like the attached?

I was thinking about how to document GVf_INTRO, something like​:

"Localize the next GP slot set."

and save_gp (part of the API) something like​:

Saves the current GP of gv on the save stack to be restored on scope exit.

If empty is true, replace the GP with a new GP.

If empty is false, mark gv with GVf_INTRO so the next reference assigned is localized, which is how C< local *foo = $someref; > works.

Tony

@p5pRT
Copy link
Author

p5pRT commented Dec 2, 2015

From @tonycoz

0001-perl-124097-don-t-let-the-GPs-be-removed-out-from-un.patch
From 9f5f69448338d796de8e443d5ed74c2614700fa5 Mon Sep 17 00:00:00 2001
From: Tony Cook <tony@develop-help.com>
Date: Wed, 2 Dec 2015 14:26:52 +1100
Subject: [perl #124097] don't let the GPs be removed out from under pp_sort

Needs tests for preserving modifications to slots in *a and *b
---
 pp_sort.c   | 7 +++++++
 t/op/sort.t | 5 ++++-
 2 files changed, 11 insertions(+), 1 deletion(-)

diff --git a/pp_sort.c b/pp_sort.c
index 64a67d8..51742f6 100644
--- a/pp_sort.c
+++ b/pp_sort.c
@@ -1657,6 +1657,13 @@ PP(pp_sort)
 		PL_secondgv = MUTABLE_GV(SvREFCNT_inc(
 		    gv_fetchpvs("b", GV_ADD|GV_NOTQUAL, SVt_PV)
 		));
+                /* make sure the GP isn't removed out from under us for
+                 * the SAVESPTR() */
+                save_gp(PL_firstgv, 0);
+                save_gp(PL_secondgv, 0);
+                /* we don't want modifications localized */
+                GvINTRO_off(PL_firstgv);
+                GvINTRO_off(PL_secondgv);
 		SAVESPTR(GvSV(PL_firstgv));
 		SAVESPTR(GvSV(PL_secondgv));
 	    }
diff --git a/t/op/sort.t b/t/op/sort.t
index 3c76365..14a5aed 100644
--- a/t/op/sort.t
+++ b/t/op/sort.t
@@ -7,7 +7,7 @@ BEGIN {
     set_up_inc('../lib');
 }
 use warnings;
-plan(tests => 193);
+plan(tests => 194);
 
 # these shouldn't hang
 {
@@ -1127,3 +1127,6 @@ pass "no crash when sort block deletes *a and *b";
     ::is (join('-', sort f2 3,1,2,4), '1-2-3-4', "Ret: f2");
     ::is (join('-', sort f3 3,1,2,4), '1-2-3-4', "Ret: f3");
 }
+
+@a = sort{ *a=0; 1} 0..1;
+pass "No crash when GP deleted out from under us [perl 124097]";
-- 
2.1.4

@p5pRT
Copy link
Author

p5pRT commented Dec 2, 2015

From @iabyn

On Tue, Dec 01, 2015 at 08​:05​:03PM -0800, Tony Cook via RT wrote​:

On Mon Nov 30 03​:42​:06 2015, davem wrote​:

So maybe there's a way to achieve this with save_gp?

Do you mean like the attached?

Looks good to me (as far as I understand these things, which isn't far).
I notice that it looks very similar in approach to SAVE_DEFSV(), which
is encouraging.

I was thinking about how to document GVf_INTRO, something like​:

"Localize the next GP slot set."

How about​:

A one-shot flag which indicates that the next assignment of a reference
to the glob is to be localised; it distinguishes 'local *g = $ref' from
'*g = $ref'.

and save_gp (part of the API) something like​:

Saves the current GP of gv on the save stack to be restored on scope exit.

If empty is true, replace the GP with a new GP.

If empty is false, mark gv with GVf_INTRO so the next reference assigned is localized, which is how C< local *foo = $someref; > works.

looks ok.

--
You never really learn to swear until you learn to drive.

@p5pRT
Copy link
Author

p5pRT commented Dec 17, 2015

From @tonycoz

On Tue Dec 01 20​:05​:03 2015, tonyc wrote​:

On Mon Nov 30 03​:42​:06 2015, davem wrote​:

So maybe there's a way to achieve this with save_gp?

Do you mean like the attached?

Applied as dc9ef99 with an extra test.

Added GVf_INTRO and save_gp() documentation in 364bbfa.

Tony

@p5pRT
Copy link
Author

p5pRT commented Dec 17, 2015

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

@p5pRT
Copy link
Author

p5pRT commented May 13, 2016

From @khwilliamson

Thank you for submitting this report. You have helped make Perl better.
 
With the release of Perl 5.24.0 on May 9, 2016, this and 149 other issues have been resolved.

Perl 5.24.0 may be downloaded via https://metacpan.org/release/RJBS/perl-5.24.0

@p5pRT
Copy link
Author

p5pRT commented May 13, 2016

@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