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

fuzzing testcase triggers LeakSanitizer over 101 byte memory leak #15752

Open
p5pRT opened this issue Dec 5, 2016 · 5 comments
Open

fuzzing testcase triggers LeakSanitizer over 101 byte memory leak #15752

p5pRT opened this issue Dec 5, 2016 · 5 comments

Comments

@p5pRT
Copy link

p5pRT commented Dec 5, 2016

Migrated from rt.perl.org#130270 (status was 'open')

Searchable as RT130270$

@p5pRT
Copy link
Author

p5pRT commented Dec 5, 2016

From @geeknik

Triggered with Perl v5.25.7-26-g7332835. I've never seen this before with
Perl, not sure if it is even a bug or just an unlucky test case generated
by AFL.

./perl test269

=================================================================
==24156==ERROR​: LeakSanitizer​: detected memory leaks

Direct leak of 48 byte(s) in 1 object(s) allocated from​:
  #0 0x4c0e10 in calloc (/root/perl/perl+0x4c0e10)
  #1 0x7fb251 in Perl_safesyscalloc /root/perl/util.c​:442​:18

Direct leak of 38 byte(s) in 1 object(s) allocated from​:
  #0 0x4c0cbb in malloc (/root/perl/perl+0x4c0cbb)
  #1 0x7fa227 in Perl_safesysmalloc /root/perl/util.c​:153​:21

Indirect leak of 15 byte(s) in 1 object(s) allocated from​:
  #0 0x4c0cbb in malloc (/root/perl/perl+0x4c0cbb)
  #1 0x7fa227 in Perl_safesysmalloc /root/perl/util.c​:153​:21

SUMMARY​: AddressSanitizer​: 101 byte(s) leaked in 3 allocation(s).

@p5pRT
Copy link
Author

p5pRT commented Dec 5, 2016

From @geeknik

test269.gz

@p5pRT
Copy link
Author

p5pRT commented Dec 6, 2016

From @tonycoz

On Mon, 05 Dec 2016 10​:52​:13 -0800, brian.carpenter@​gmail.com wrote​:

Triggered with Perl v5.25.7-26-g7332835. I've never seen this before with
Perl, not sure if it is even a bug or just an unlucky test case generated
by AFL.

./perl test269

This looks like more than one bug, with some interactions between them.

If I build blead with -DDEBUGGING -Doptimize=-O0\ -g and run your
code as "130270.pl" I see the leak you describe under valgrind - sometimes​:

tony@​mars​:.../git/perl$ PERL_DESTRUCT_LEVEL=2 valgrind --leak-check=full ./perl ../130270.pl
==7919== Memcheck, a memory error detector
==7919== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==7919== Using Valgrind-3.10.0 and LibVEX; rerun with -h for copyright info
==7919== Command​: ./perl ../130270.pl
==7919==
Can't use an undefined value as a symbol reference at ../130270.pl line 1.
Attempt to free unreferenced scalar​: SV 0x5f71000.
Attempt to free unreferenced scalar​: SV 0x5f71000.
panic​: magic_killbackrefs (freed backref AV/SV) during global destruction.
==7919==
==7919== HEAP SUMMARY​:
==7919== in use at exit​: 100,067 bytes in 173 blocks
==7919== total heap usage​: 820 allocs, 647 frees, 162,754 bytes allocated
==7919==
==7919== 80 bytes in 1 blocks are definitely lost in loss record 94 of 145
==7919== at 0x4C2AD10​: calloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==7919== by 0x558D5A​: Perl_safesyscalloc (util.c​:440)
==7919== by 0x46E273​: Perl_newGP (gv.c​:174)
==7919== by 0x46FBD2​: Perl_gv_init_pvn (gv.c​:413)
==7919== by 0x47F2A9​: Perl_gv_fetchpvn_flags (gv.c​:2401)
==7919== by 0x4954E5​: S_force_ident (toke.c​:2093)
==7919== by 0x4A7FEA​: Perl_yylex (toke.c​:5491)
==7919== by 0x4D1A24​: Perl_yyparse (perly.c​:347)
==7919== by 0x460116​: S_parse_body (perl.c​:2374)
==7919== by 0x45E5E6​: perl_parse (perl.c​:1689)
==7919== by 0x41EFC5​: main (perlmain.c​:121)
==7919==
==7919== LEAK SUMMARY​:
==7919== definitely lost​: 80 bytes in 1 blocks
==7919== indirectly lost​: 0 bytes in 0 blocks
==7919== possibly lost​: 0 bytes in 0 blocks
==7919== still reachable​: 99,987 bytes in 172 blocks
==7919== suppressed​: 0 bytes in 0 blocks
==7919== Reachable blocks (those to which a pointer was found) are not shown.
==7919== To see them, rerun with​: --leak-check=full --show-leak-kinds=all
==7919==
==7919== For counts of detected and suppressed errors, rerun with​: -v
==7919== ERROR SUMMARY​: 1 errors from 1 contexts (suppressed​: 0 from 0)

Note the panic, which probably causes the still reachable leaks.

Sometimes the same invocation displays no "definitely lost"​:

tony@​mars​:.../git/perl$ PERL_DESTRUCT_LEVEL=2 valgrind --leak-check=full ./perl ../130270.pl
==7916== Memcheck, a memory error detector
==7916== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==7916== Using Valgrind-3.10.0 and LibVEX; rerun with -h for copyright info
==7916== Command​: ./perl ../130270.pl
==7916==
Can't use an undefined value as a symbol reference at ../130270.pl line 1.
Attempt to free unreferenced scalar​: SV 0x5f71000.
Attempt to free unreferenced scalar​: SV 0x5f71000.
panic​: magic_killbackrefs (freed backref AV/SV) during global destruction.
==7916==
==7916== HEAP SUMMARY​:
==7916== in use at exit​: 119,933 bytes in 579 blocks
==7916== total heap usage​: 820 allocs, 241 frees, 162,754 bytes allocated
==7916==
==7916== LEAK SUMMARY​:
==7916== definitely lost​: 0 bytes in 0 blocks
==7916== indirectly lost​: 0 bytes in 0 blocks
==7916== possibly lost​: 0 bytes in 0 blocks
==7916== still reachable​: 119,933 bytes in 579 blocks
==7916== suppressed​: 0 bytes in 0 blocks
==7916== Reachable blocks (those to which a pointer was found) are not shown.
==7916== To see them, rerun with​: --leak-check=full --show-leak-kinds=all
==7916==
==7916== For counts of detected and suppressed errors, rerun with​: -v
==7916== ERROR SUMMARY​: 0 errors from 0 contexts (suppressed​: 0 from 0)

but we still have a panic.

If I change the name of the test script (which I'd done to work on
reducing the test case)​:

tony@​mars​:.../git/perl$ PERL_DESTRUCT_LEVEL=2 valgrind --leak-check=full ./perl ../130270b.pl
==7999== Memcheck, a memory error detector
==7999== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==7999== Using Valgrind-3.10.0 and LibVEX; rerun with -h for copyright info
==7999== Command​: ./perl ../130270b.pl
==7999==
==7999== Invalid read of size 8
==7999== at 0x600122​: Perl_newSV_type (sv.c​:9654)
==7999== by 0x4794EC​: S_parse_gv_stash_name (gv.c​:1639)
==7999== by 0x47EDF7​: Perl_gv_fetchpvn_flags (gv.c​:2324)
==7999== by 0x478A17​: Perl_gv_fetchsv (gv.c​:1561)
==7999== by 0x5DF5FE​: Perl_sv_setsv_flags (sv.c​:4548)
==7999== by 0x5A109B​: Perl_pp_sassign (pp_hot.c​:226)
==7999== by 0x5571AD​: Perl_runops_debug (dump.c​:2260)
==7999== by 0x460EB1​: S_run_body (perl.c​:2526)
==7999== by 0x460494​: perl_run (perl.c​:2449)
==7999== by 0x41EFDD​: main (perlmain.c​:123)
==7999== Address 0x2200000c00000001 is not stack'd, malloc'd or (recently) free'd
==7999==
==7999==
==7999== Process terminating with default action of signal 11 (SIGSEGV)
==7999== General Protection Fault
==7999== at 0x600122​: Perl_newSV_type (sv.c​:9654)
==7999== by 0x4794EC​: S_parse_gv_stash_name (gv.c​:1639)
==7999== by 0x47EDF7​: Perl_gv_fetchpvn_flags (gv.c​:2324)
==7999== by 0x478A17​: Perl_gv_fetchsv (gv.c​:1561)
==7999== by 0x5DF5FE​: Perl_sv_setsv_flags (sv.c​:4548)
==7999== by 0x5A109B​: Perl_pp_sassign (pp_hot.c​:226)
==7999== by 0x5571AD​: Perl_runops_debug (dump.c​:2260)
==7999== by 0x460EB1​: S_run_body (perl.c​:2526)
==7999== by 0x460494​: perl_run (perl.c​:2449)
==7999== by 0x41EFDD​: main (perlmain.c​:123)
==7999==

I tried the following local change to track down the location more accurately​:

Inline Patch
diff --git a/sv.c b/sv.c
index dc392f0..95b0dad 100644
--- a/sv.c
+++ b/sv.c
@@ -348,6 +348,7 @@ S_new_SV(pTHX_ const char *file, int line, const char *func)
 #  define new_SV(p) (p)=S_new_SV(aTHX_ __FILE__, __LINE__, FUNCTION__)
 
 #else
+#if 0
 #  define new_SV(p) \
     STMT_START {                                       \
        if (PL_sv_root)                                 \
@@ -360,6 +361,22 @@ S_new_SV(pTHX_ const char *file, int line, const char *func)
        MEM_LOG_NEW_SV(p, __FILE__, __LINE__, FUNCTION__);  \
     } STMT_END
 #endif
+#  define new_SV(p) \
+    ((p) = S_new_SV(aTHX))
+
+static __inline__
+SV * S_new_SV(aTHX) {
+    SV *p;
+    if (PL_sv_root)
+        uproot_SV(p);
+    else
+        (p) = S_more_sv(aTHX);
+    SvANY(p) = 0;
+    SvREFCNT(p) = 1;
+    SvFLAGS(p) = 0;
+    return p;
+}
+#endif
 
 
 /* del_SV(): return an empty SV head to the free list */

tony@mars:.../git/perl$ PERL_DESTRUCT_LEVEL=2 valgrind --leak-check=full ./perl ../130270b.pl ==10650== Memcheck\, a memory error detector ==10650== Copyright \(C\) 2002\-2013\, and GNU GPL'd\, by Julian Seward et al\. ==10650== Using Valgrind\-3\.10\.0 and LibVEX; rerun with \-h for copyright info ==10650== Command​: \./perl \.\./130270b\.pl ==10650== ==10650== Invalid read of size 8 ==10650== at 0x5BEB21​: S\_new\_SV \(sv\.c​:371\) ==10650== by 0x5FFC70​: Perl\_newSV\_type \(sv\.c​:9671\) ==10650== by 0x4794EC​: S\_parse\_gv\_stash\_name \(gv\.c​:1639\) ==10650== by 0x47EDF7​: Perl\_gv\_fetchpvn\_flags \(gv\.c​:2324\) ==10650== by 0x478A17​: Perl\_gv\_fetchsv \(gv\.c​:1561\) ==10650== by 0x5DF677​: Perl\_sv\_setsv\_flags \(sv\.c​:4565\) ==10650== by 0x5A109B​: Perl\_pp\_sassign \(pp\_hot\.c​:226\) ==10650== by 0x5571AD​: Perl\_runops\_debug \(dump\.c​:2260\) ==10650== by 0x460EB1​: S\_run\_body \(perl\.c​:2526\) ==10650== by 0x460494​: perl\_run \(perl\.c​:2449\) ==10650== by 0x41EFDD​: main \(perlmain\.c​:123\) ==10650== Address 0x2200000c00000001 is not stack'd\, malloc'd or \(recently\) free'd ==10650== ==10650== ==10650== Process terminating with default action of signal 11 \(SIGSEGV\) ==10650== General Protection Fault

which is the call to uproot_SV().

Without valgrind this doesn't always segfault​:

tony@​mars​:.../git/perl$ PERL_DESTRUCT_LEVEL=2 ./perl ../130270b.pl
Attempt to free unreferenced glob pointers during global destruction.
panic​: del_backref, svp=0 during global destruction.

but usually does​:

tony@​mars​:.../git/perl$ PERL_DESTRUCT_LEVEL=2 ./perl ../130270b.pl
Attempt to free unreferenced scalar​: SV 0x1d6a9c8 during global destruction.
Segmentation fault

Tony

@p5pRT
Copy link
Author

p5pRT commented Dec 6, 2016

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

@p5pRT
Copy link
Author

p5pRT commented Jan 21, 2019

From @tonycoz

On Mon, 05 Dec 2016 16​:27​:55 -0800, tonyc wrote​:

On Mon, 05 Dec 2016 10​:52​:13 -0800, brian.carpenter@​gmail.com wrote​:

Triggered with Perl v5.25.7-26-g7332835. I've never seen this before
with
Perl, not sure if it is even a bug or just an unlucky test case
generated
by AFL.

./perl test269

This looks like more than one bug, with some interactions between
them.

If I build blead with -DDEBUGGING -Doptimize=-O0\ -g and run your
code as "130270.pl" I see the leak you describe under valgrind -
sometimes​:

Looking at this now​:

$ ./perl -Ilib -MO=Deparse ../130270.pl
$$0 ^= ($0 |= (*0 = *aHH​::HHMHHHHHHHOH)), *& = ($$0 ^= ($0 |= (*0 = *aHH​::HHMHHHHHHHOH = *& = *a6))) foreach (('b') x 56);
'???';

it looks like another stack-not-refcounted bug.

Tony

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

2 participants