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

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

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



Subject: SIGSEGV in hek_eq_pvn_flags
Download (untitled) / with headers
text/plain 9.7k
Greetings Porters, I have compiled bleadperl with the afl-gcc compiler using: ./Configure -Dusedevel -Dprefix='/usr/local/perl-afl' -Dcc='ccache afl-gcc' -Uuselongdouble -Duse64bitall -Doptimize=-g -Uversiononly -Uman1dir -Uman3dir -Dusequadmath -des AFL_HARDEN=1 make && make test And then fuzzed the resulting binary using: AFL_NO_VAR_CHECK=1 afl-fuzz -i in -o out bin/perl @@ After reducing testcases using `afl-tmin` and performing additional minimization by hand, I have located the following testcase that triggers a segmentation fault in the perl interpreter. The testcase is the 25-character file: /${*::::::=0}$0{*::::=0}/ On normal and debug builds, this crashes with a segmentation fault. dcollins@nightshade64:~/perl$ ~/perl/perl -e '/${*::::::=0}$0{*::::=0}/' Segmentation fault dcollins@nightshade64:~/perl$ ~/perldebug/perl -e '/${*::::::=0}$0{*::::=0}/' Segmentation fault Debugging tool output is below. I don't think this has been reported yet, strategic searches for "S_mro_gather_and_rename" don't seem to yield any past reports. It's dereferencing something that isn't a pointer. **GDB** dcollins@nightshade64:~/perl$ gdb --args ~/perl/perl -e '/${*::::::=0}$0{*::::=0}/' GNU gdb (GDB) 7.10 Copyright (C) 2015 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "x86_64-unknown-linux-gnu". Type "show configuration" for configuration details. For bug reporting instructions, please see: <http://www.gnu.org/software/gdb/bugs/>. Find the GDB manual and other documentation resources online at: <http://www.gnu.org/software/gdb/documentation/>. For help, type "help". Type "apropos word" to search for commands related to "word"... Reading symbols from /home/dcollins/perl/perl...done. (gdb) run Starting program: /home/dcollins/perl/perl -e /\$\{\*::::::=0\}\$0\{\*::::=0\}/ [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. 0x0000000000773478 in hek_eq_pvn_flags (flags=<optimized out>, pvlen=<optimized out>, pv=<optimized out>, hek=<optimized out>) at hv.c:2349 2349 return (bytes_cmp_utf8( (gdb) bt #0 0x0000000000773478 in hek_eq_pvn_flags (flags=<optimized out>, pvlen=<optimized out>, pv=<optimized out>, hek=<optimized out>) at hv.c:2349 #1 Perl_hv_ename_delete (hv=0xe99d58, name=name@entry=0xe92860 "::", len=2, flags=flags@entry=0) at hv.c:2488 #2 0x000000000073020c in S_mro_gather_and_rename (stashes=stashes@entry=0xe99470, seen_stashes=seen_stashes@entry=0xe99500, stash=stash@entry=0x0, oldstash=oldstash@entry=0xe99d58, namesv=namesv@entry=0xe994e8) at mro_core.c:962 #3 0x000000000072d09a in S_mro_gather_and_rename (stashes=stashes@entry=0xe99470, seen_stashes=0xe99500, stash=stash@entry=0xe99d58, oldstash=oldstash@entry=0xe99cf8, namesv=namesv@entry=0xe99458) at mro_core.c:1186 #4 0x0000000000738e6b in Perl_mro_package_moved (stash=0xe99d58, oldstash=oldstash@entry=0xe99cf8, gv=gv@entry=0xe99ce0, flags=flags@entry=0) at mro_core.c:851 #5 0x00000000007fd515 in Perl_sv_setsv_flags (dstr=dstr@entry=0xe99ce0, sstr=sstr@entry=0xe99d40, flags=flags@entry=1538) at sv.c:4561 #6 0x00000000007949d0 in Perl_pp_sassign () at pp_hot.c:226 #7 0x000000000079148b in Perl_runops_standard () at run.c:41 #8 0x00000000004ebf9f in S_run_body (oldscope=1) at perl.c:2483 #9 perl_run (my_perl=<optimized out>) at perl.c:2406 #10 0x00000000004276a8 in main (argc=3, argv=0x7fffffffe338, env=0x7fffffffe358) at perlmain.c:116 (gdb) info locals No locals. (gdb) l 2344 if (flags & SVf_UTF8) 2345 return (bytes_cmp_utf8( 2346 (const U8*)HEK_KEY(hek), HEK_LEN(hek), 2347 (const U8*)pv, pvlen) == 0); 2348 else 2349 return (bytes_cmp_utf8( 2350 (const U8*)pv, pvlen, 2351 (const U8*)HEK_KEY(hek), HEK_LEN(hek)) == 0); 2352 } 2353 else (gdb) **VALGRIND** dcollins@nightshade64:~/perl$ valgrind ~/perl/perl -e '/${*::::::=0}$0{*::::=0}/' ==9173== Memcheck, a memory error detector ==9173== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al. ==9173== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info ==9173== Command: /home/dcollins/perl/perl -e /${*::::::=0}$0{*::::=0}/ ==9173== ==9173== Invalid read of size 4 ==9173== at 0x773478: hek_eq_pvn_flags (hv.c:2349) ==9173== by 0x773478: Perl_hv_ename_delete (hv.c:2488) ==9173== by 0x73020B: S_mro_gather_and_rename (mro_core.c:962) ==9173== by 0x72D099: S_mro_gather_and_rename (mro_core.c:1186) ==9173== by 0x738E6A: Perl_mro_package_moved (mro_core.c:851) ==9173== by 0x7FD514: Perl_sv_setsv_flags (sv.c:4561) ==9173== by 0x7949CF: Perl_pp_sassign (pp_hot.c:226) ==9173== by 0x79148A: Perl_runops_standard (run.c:41) ==9173== by 0x4EBF9E: S_run_body (perl.c:2483) ==9173== by 0x4EBF9E: perl_run (perl.c:2406) ==9173== by 0x4276A7: main (perlmain.c:116) ==9173== Address 0x4 is not stack'd, malloc'd or (recently) free'd ==9173== ==9173== ==9173== Process terminating with default action of signal 11 (SIGSEGV) ==9173== Access not within mapped region at address 0x4 ==9173== at 0x773478: hek_eq_pvn_flags (hv.c:2349) ==9173== by 0x773478: Perl_hv_ename_delete (hv.c:2488) ==9173== by 0x73020B: S_mro_gather_and_rename (mro_core.c:962) ==9173== by 0x72D099: S_mro_gather_and_rename (mro_core.c:1186) ==9173== by 0x738E6A: Perl_mro_package_moved (mro_core.c:851) ==9173== by 0x7FD514: Perl_sv_setsv_flags (sv.c:4561) ==9173== by 0x7949CF: Perl_pp_sassign (pp_hot.c:226) ==9173== by 0x79148A: Perl_runops_standard (run.c:41) ==9173== by 0x4EBF9E: S_run_body (perl.c:2483) ==9173== by 0x4EBF9E: perl_run (perl.c:2406) ==9173== by 0x4276A7: main (perlmain.c:116) ==9173== If you believe this happened as a result of a stack ==9173== overflow in your program's main thread (unlikely but ==9173== possible), you can try to increase the size of the ==9173== main thread stack using the --main-stacksize= flag. ==9173== The main thread stack size used in this run was 8388608. ==9173== ==9173== HEAP SUMMARY: ==9173== in use at exit: 121,264 bytes in 656 blocks ==9173== total heap usage: 770 allocs, 114 frees, 138,239 bytes allocated ==9173== ==9173== LEAK SUMMARY: ==9173== definitely lost: 328 bytes in 1 blocks ==9173== indirectly lost: 2,631 bytes in 39 blocks ==9173== possibly lost: 0 bytes in 0 blocks ==9173== still reachable: 118,305 bytes in 616 blocks ==9173== suppressed: 0 bytes in 0 blocks ==9173== Rerun with --leak-check=full to see details of leaked memory ==9173== ==9173== For counts of detected and suppressed errors, rerun with: -v ==9173== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0) Segmentation fault **PERL -V** dcollins@nightshade64:~/perl$ ./perl -Ilib -V Summary of my perl5 (revision 5 version 24 subversion 0) configuration: Commit id: 10d36cf9c1885126580478a10462ed672361059e Platform: osname=linux, osvers=3.16.0-4-amd64, archname=x86_64-linux-ld uname='linux nightshade64 3.16.0-4-amd64 #1 smp debian 3.16.7-ckt20-1+deb8u3 (2016-01-17) x86_64 gnulinux ' config_args='-Dusedevel -Dprefix=/usr/local/perl-afl -Dcc=ccache afl-gcc -Duselongdouble -Duse64bitall -Doptimize=-g -Uversiononly -Uman1dir -Uman3dir -des' hint=recommended, useposix=true, d_sigaction=define useithreads=undef, usemultiplicity=undef use64bitint=define, use64bitall=define, uselongdouble=define usemymalloc=n, bincompat5005=undef Compiler: cc='ccache afl-gcc', ccflags ='-fwrapv -fno-strict-aliasing -pipe -fstack-protector-strong -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64', optimize='-g', cppflags='-fwrapv -fno-strict-aliasing -pipe -fstack-protector-strong -I/usr/local/include' ccversion='', gccversion='5.2.0', gccosandvers='' intsize=4, longsize=8, ptrsize=8, doublesize=8, byteorder=12345678, doublekind=3 d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=16, longdblkind=3 ivtype='long', ivsize=8, nvtype='long double', nvsize=16, Off_t='off_t', lseeksize=8 alignbytes=16, prototype=define Linker and Libraries: ld='ccache afl-gcc', ldflags =' -fstack-protector-strong -L/usr/local/lib' libpth=/usr/local/lib /usr/local/lib/gcc/x86_64-unknown-linux-gnu/5.2.0/include-fixed /usr/include/x86_64-linux-gnu /usr/lib /lib/x86_64-linux-gnu /lib/../lib /usr/lib/x86_64-linux-gnu /usr/lib/../lib /lib libs=-lpthread -lnsl -ldl -lm -lcrypt -lutil -lc perllibs=-lpthread -lnsl -ldl -lm -lcrypt -lutil -lc libc=libc-2.19.so, so=so, useshrplib=false, libperl=libperl.a gnulibc_version='2.19' Dynamic Linking: dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E' cccdlflags='-fPIC', lddlflags='-shared -g -L/usr/local/lib -fstack-protector-strong' Characteristics of this binary (from libperl): Compile-time options: HAS_TIMES PERLIO_LAYERS PERL_COPY_ON_WRITE PERL_DONT_CREATE_GVSV PERL_HASH_FUNC_ONE_AT_A_TIME_HARD PERL_MALLOC_WRAP PERL_PRESERVE_IVUV PERL_USE_DEVEL USE_64_BIT_ALL USE_64_BIT_INT USE_LARGE_FILES USE_LOCALE USE_LOCALE_COLLATE USE_LOCALE_CTYPE USE_LOCALE_NUMERIC USE_LOCALE_TIME USE_LONG_DOUBLE USE_PERLIO USE_PERL_ATOF Locally applied patches: RC3 Built under linux Compiled at Apr 30 2016 15:50:19 @INC: lib /usr/local/perl-afl/lib/site_perl/5.24.0/x86_64-linux-ld /usr/local/perl-afl/lib/site_perl/5.24.0 /usr/local/perl-afl/lib/5.24.0/x86_64-linux-ld /usr/local/perl-afl/lib/5.24.0 .
RT-Send-CC: perl5-porters [...] perl.org
Download (untitled) / with headers
text/plain 806b
This appears to be a precedence error, fixable with an extra pair of parens as below. I don't understand this area well though, and I'd like to add a test that's less obscure than the reported test case. Any suggestions? Hugo diff --git a/hv.c b/hv.c index 7b5ad95..5523475 100644 --- a/hv.c +++ b/hv.c @@ -2476,9 +2476,10 @@ Perl_hv_ename_delete(pTHX_ HV *hv, const char *name, U32 return; } if ( - count > 0 && (HEK_UTF8(*namep) || (flags & SVf_UTF8)) + count > 0 && ((HEK_UTF8(*namep) || (flags & SVf_UTF8)) ? hek_eq_pvn_flags(aTHX_ *namep, name, (I32)len, flags) : (HEK_LEN(*namep) == (I32)len && memEQ(HEK_KEY(*namep), name, l + ) ) { aux->xhv_name_count = -count; }
RT-Send-CC: perl5-porters [...] perl.org
Download (untitled) / with headers
text/plain 791b
On Tue May 10 01:00:01 2016, hv wrote: Show quoted text
> This appears to be a precedence error, fixable with an extra pair of > parens as below. I don't understand this area well though, and I'd > like to add a test that's less obscure than the reported test case. > > Any suggestions?
I think there may be more to this bug than meets the eye. If I add the debugging code in the attached patch, I get this: SV = PVHV(0x7fda9280aec0) at 0x7fda9282a938 REFCNT = 1 FLAGS = (OOK,SHAREKEYS,OVERLOAD) AUX_FLAGS = 0 ARRAY = 0x7fda924098e0 KEYS = 0 FILL = 0 (cached = 0) MAX = 7 RITER = -1 EITER = 0x0 RAND = 0x2da71023 NAMECOUNT = -3 ENAME = "::::", (null) etc. ENAME should never have null in it. That’s a bug, possibly elsewhere. I need to dig deeper. -- Father Chrysostomos
Subject: debug-diff.txt
Download debug-diff.txt
text/plain 562b
diff --git a/hv.c b/hv.c index 7b5ad95..697a0aa 100644 --- a/hv.c +++ b/hv.c @@ -2478,7 +2478,7 @@ Perl_hv_ename_delete(pTHX_ HV *hv, const char *name, U32 len, U32 flags) if ( count > 0 && (HEK_UTF8(*namep) || (flags & SVf_UTF8)) ? hek_eq_pvn_flags(aTHX_ *namep, name, (I32)len, flags) - : (HEK_LEN(*namep) == (I32)len && memEQ(HEK_KEY(*namep), name, len)) + : (*namep || (Perl_sv_dump(aTHX_ (SV*)hv),0), (HEK_LEN(*namep) == (I32)len && memEQ(HEK_KEY(*namep), name, len))) ) { aux->xhv_name_count = -count; }
RT-Send-CC: perl5-porters [...] perl.org
Download (untitled) / with headers
text/plain 2.3k
On Tue May 10 21:13:32 2016, sprout wrote: Show quoted text
> On Tue May 10 01:00:01 2016, hv wrote:
> > This appears to be a precedence error, fixable with an extra pair of > > parens as below. I don't understand this area well though, and I'd > > like to add a test that's less obscure than the reported test case. > > > > Any suggestions?
This is the simplest test case I can come up with: %h; *::::::=*h; delete $::{"::"} It has to do with two code paths dividing up and reconstructing names like :::::: differently. Perl keeps track of all the effective names of a stash, if it gets aliased or reassigned. That is what HvENAME is for, whereas HvNAME is the original, canonical name of the stash. In the short case above, %h must be vivified first, before the assignment (any compile-time mention will work). Then, when the assignment happens, it gets the *effective* name :::: assigned to it. Internally, a stash may have a list of names. If the canonical name (the first name in the list) is not one of the effective names, then the name count is negative, to indicate that. After the assignment above, we have: NULL, "::::" (with a name count of -2) such that HvNAME is NULL, but HvENAME is a hek containing "::::". The count>0 check in hv_ename_delete protects against reading that null, but this is where the precedence problem prevents it and causes a crash. I think you can go ahead and apply your fix, for this reason. Show quoted text
> > I think there may be more to this bug than meets the eye. > > If I add the debugging code in the attached patch, I get this: > > SV = PVHV(0x7fda9280aec0) at 0x7fda9282a938 > REFCNT = 1 > FLAGS = (OOK,SHAREKEYS,OVERLOAD) > AUX_FLAGS = 0 > ARRAY = 0x7fda924098e0 > KEYS = 0 > FILL = 0 (cached = 0) > MAX = 7 > RITER = -1 > EITER = 0x0 > RAND = 0x2da71023 > NAMECOUNT = -3 > ENAME = "::::", (null) > > etc. > > ENAME should never have null in it. That’s a bug, possibly elsewhere. > I need to dig deeper.
Actually two bugs. First, *::::=anything is assigning the empty string as a name to whatever hash is put there. Secondly, dump.c is dumping the empty string as (null), which should only be used for a null pointer. (The null-handling code was added when ename supported was not partially written and nulls were appearing in the array due to bugs elsewhere that were fixed before the code was merged.) -- Father Chrysostomos
RT-Send-CC: perl5-porters [...] perl.org
Download (untitled) / with headers
text/plain 1.6k
On Sat May 14 10:24:41 2016, sprout wrote: Show quoted text
> On Tue May 10 21:13:32 2016, sprout wrote:
> > On Tue May 10 01:00:01 2016, hv wrote:
> > > This appears to be a precedence error, fixable with an extra pair > > > of > > > parens as below. I don't understand this area well though, and I'd > > > like to add a test that's less obscure than the reported test case. > > > > > > Any suggestions?
> > This is the simplest test case I can come up with: > > %h; *::::::=*h; delete $::{"::"}
... Show quoted text
> I think you can go ahead and apply your fix, for this reason.
I have applied your patch in 60a26c797bb. Thank you. I have applied the test in 7f1bd063e. Show quoted text
> > > > I think there may be more to this bug than meets the eye. > > > > If I add the debugging code in the attached patch, I get this: > > > > SV = PVHV(0x7fda9280aec0) at 0x7fda9282a938 > > REFCNT = 1 > > FLAGS = (OOK,SHAREKEYS,OVERLOAD) > > AUX_FLAGS = 0 > > ARRAY = 0x7fda924098e0 > > KEYS = 0 > > FILL = 0 (cached = 0) > > MAX = 7 > > RITER = -1 > > EITER = 0x0 > > RAND = 0x2da71023 > > NAMECOUNT = -3 > > ENAME = "::::", (null) > > > > etc. > > > > ENAME should never have null in it. That’s a bug, possibly > > elsewhere. > > I need to dig deeper.
> > Actually two bugs. First, *::::=anything is assigning the empty > string as a name to whatever hash is put there. Secondly, dump.c is > dumping the empty string as (null), which should only be used for a > null pointer.
I have fixed dump.c in 8e5993c4dcf. As for the discrepancy in how :::: names are parsed, I think we can leave things as they are unless some other real bug shows up as a result. I am marking this ticket as resolved. -- Father Chrysostomos


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