Bug 21880 - Memory leak in demangle
Summary: Memory leak in demangle
Status: RESOLVED INVALID
Alias: None
Product: binutils
Classification: Unclassified
Component: binutils (show other bugs)
Version: 2.28
: P2 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2017-08-01 20:05 UTC by Google-Autofuzz
Modified: 2018-05-09 08:16 UTC (History)
4 users (show)

See Also:
Host:
Target:
Build:
Last reconfirmed: 2017-09-26 00:00:00


Attachments
binutils docker file (1.26 KB, text/plain)
2017-08-01 20:05 UTC, Google-Autofuzz
Details
Demangle PoC (15 bytes, text/plain)
2017-08-01 20:06 UTC, Google-Autofuzz
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Google-Autofuzz 2017-08-01 20:05:43 UTC
Created attachment 10305 [details]
binutils docker file

Hello binutils team,
 
As part of our fuzzing efforts at Google, we have identified an issue affecting binutils (tested with revision 2.28.51 (git: branch master, commit 1b19ec971047a074486e6b775dc1969aa13f30fb)).  To reproduce we are attaching a dockerfile to help compiling the project with the LLVM taking advantage of the sanitizers that it offers.
 
Attached is a dockerfile that can be used for reproduction.  More information about how to use the dockerfile can be found here:  https://docs.docker.com/engine/reference/builder/
TL;DR instructions:
mkdir binutils
cp Dockerfile /path/to/binutils
docker build --no-cache /path/to/binutils
docker run -it <image id>
(from another terminal, outside the container):
docker cp /path/to/attached/reproducer <container id>:/fuzzing/
https://docs.docker.com/engine/reference/commandline/cp/
(back inside the container) /fuzzing/repro.sh /fuzzing/reproducer
 
Alternatively, and depending on the bug, you could use gcc, valgrind or other instrumentation tools to aid in the investigation.
 
The sanitizer error that we encountered is here:
 
 ==42==ERROR: LeakSanitizer: detected memory leaks
 
Direct leak of 8 byte(s) in 1 object(s) allocated from:
    #0 0x4cd488 in __interceptor_malloc (/fuzzing/binutils-gdb/build/demangle_fuzzer+0x4cd488)
    #1 0x52f179 in xmalloc /fuzzing/binutils-gdb/libiberty/xmalloc.c:147:12
    #2 0x50fb7e in demangle_template /fuzzing/binutils-gdb/libiberty/cplus-dem.c:2228:27
    #3 0x50e30d in demangle_signature /fuzzing/binutils-gdb/libiberty/cplus-dem.c:1691:18
    #4 0x50bc20 in internal_cplus_demangle /fuzzing/binutils-gdb/libiberty/cplus-dem.c:1257:14
    #5 0x50a99c in cplus_demangle /fuzzing/binutils-gdb/libiberty/cplus-dem.c:918:9
    #6 0x50847d in LLVMFuzzerTestOneInput /fuzzing/binutils-gdb/build/../libiberty/demangle_fuzzer.cc:11:20
    #7 0x535eec in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) (/fuzzing/binutils-gdb/build/demangle_fuzzer+0x535eec)
    #8 0x52f3bc in main (/fuzzing/binutils-gdb/build/demangle_fuzzer+0x52f3bc)
 
Indirect leak of 1 byte(s) in 1 object(s) allocated from:
    #0 0x4cd488 in __interceptor_malloc (/fuzzing/binutils-gdb/build/demangle_fuzzer+0x4cd488)
    #1 0x52f179 in xmalloc /fuzzing/binutils-gdb/libiberty/xmalloc.c:147:12
    #2 0x5100db in demangle_template /fuzzing/binutils-gdb/libiberty/cplus-dem.c:2327:31
    #3 0x50e30d in demangle_signature /fuzzing/binutils-gdb/libiberty/cplus-dem.c:1691:18
    #4 0x50bc20 in internal_cplus_demangle /fuzzing/binutils-gdb/libiberty/cplus-dem.c:1257:14
    #5 0x50a99c in cplus_demangle /fuzzing/binutils-gdb/libiberty/cplus-dem.c:918:9
    #6 0x50847d in LLVMFuzzerTestOneInput /fuzzing/binutils-gdb/build/../libiberty/demangle_fuzzer.cc:11:20
    #7 0x535eec in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) (/fuzzing/binutils-gdb/build/demangle_fuzzer+0x535eec)
    #8 0x52f3bc in main (/fuzzing/binutils-gdb/build/demangle_fuzzer+0x52f3bc)
 
SUMMARY: AddressSanitizer: 9 byte(s) leaked in 2 allocation(s).
 
We will gladly work with you so you can successfully confirm and reproduce this issue. Do let us know if you have any feedback surrounding the documentation.
 
Once you have reproduced the issue, we’d appreciate to learn your expected timeline for an update to be released. With any fix, please attribute the report to “Google Autofuzz project”.
 
We are also pleased to inform you that your project is eligible for inclusion to the OSS-Fuzz project, which can provide additional continuous fuzzing, and encourage you to investigate integration options (https://github.com/google/oss-fuzz/blob/master/docs/new_project_guide.md).
 
Don’t hesitate to let us know if you have any questions!
 
Google AutoFuzz Team
Comment 1 Google-Autofuzz 2017-08-01 20:06:02 UTC
Created attachment 10306 [details]
Demangle PoC
Comment 2 Google-Autofuzz 2017-08-02 00:38:37 UTC
Resolving in favor of reporting directly to GCC.
Comment 3 Google-Autofuzz 2017-08-03 23:17:33 UTC
GCC indicated that this was the proper component for our report since this only reproduces with binutils, apologies for the noise.
Comment 4 Dongliang Mu 2017-09-20 15:04:17 UTC
Hello Google AutoFuzz Team:

I tried to reproduce this bug in the docker, but when I compiled demangle_fuzzer.cc. It encounters one error:

$ $CXX $CXXFLAGS $LDFLAGS -I../include ../libiberty/demangle_fuzzer.cc libiberty.a -lFuzzer -o demangle_fuzzer
In file included from ../libiberty/demangle_fuzzer.cc:5:
In file included from ../include/demangle.h:32:
../include/libiberty.h:112:14: error: 'basename' is missing exception specification 'throw()'
extern char *basename (const char *) ATTRIBUTE_RETURNS_NONNULL ATTRIBUTE_NONNULL(1);
             ^
                                     throw()
/usr/include/string.h:601:26: note: previous declaration is here
extern "C++" const char *basename (const char *__filename)
                         ^
1 error generated.


How do I fix this problem and then trigger the bug?

Note, in the confguration of binutils, "--host" option is essential.

The new Dockerfile for my case is https://gist.github.com/mudongliang/3c14d1c4937a9aa6035957f34adfe68f
Comment 5 Dongliang Mu 2017-09-20 16:57:51 UTC
(In reply to Dongliang Mu from comment #4)
> Hello Google AutoFuzz Team:
> 
> I tried to reproduce this bug in the docker, but when I compiled
> demangle_fuzzer.cc. It encounters one error:
> 
> $ $CXX $CXXFLAGS $LDFLAGS -I../include ../libiberty/demangle_fuzzer.cc
> libiberty.a -lFuzzer -o demangle_fuzzer
> In file included from ../libiberty/demangle_fuzzer.cc:5:
> In file included from ../include/demangle.h:32:
> ../include/libiberty.h:112:14: error: 'basename' is missing exception
> specification 'throw()'
> extern char *basename (const char *) ATTRIBUTE_RETURNS_NONNULL
> ATTRIBUTE_NONNULL(1);
>              ^
>                                      throw()
> /usr/include/string.h:601:26: note: previous declaration is here
> extern "C++" const char *basename (const char *__filename)
>                          ^
> 1 error generated.
> 
> 
> How do I fix this problem and then trigger the bug?
>

-DHAVE_DECL_BASENAME is missing.

Sorry for the noise. 
> Note, in the confguration of binutils, "--host" option is essential.
> 
> The new Dockerfile for my case is
> https://gist.github.com/mudongliang/3c14d1c4937a9aa6035957f34adfe68f
Comment 6 Nick Clifton 2017-09-26 14:04:32 UTC
(In reply to Google-Autofuzz from comment #0)

Hi Google-Autofuzz,

> The sanitizer error that we encountered is here:

>     #1 0x52f179 in xmalloc /fuzzing/binutils-gdb/libiberty/xmalloc.c:147:12
>     #2 0x50fb7e in demangle_template
> /fuzzing/binutils-gdb/libiberty/cplus-dem.c:2228:27

This problem is in the libiberty library, which is maintained by the gcc project, not the binutils project.  Please could you refile this bug report with the gcc bug tracking system here:

  https://gcc.gnu.org/bugzilla/enter_bug.cgi

Thanks very much.

Cheers
  Nick
Comment 7 Markus Trippelsdorf 2017-09-26 14:33:21 UTC
(In reply to Nick Clifton from comment #6)
> (In reply to Google-Autofuzz from comment #0)
> 
> Hi Google-Autofuzz,
> 
> > The sanitizer error that we encountered is here:
> 
> >     #1 0x52f179 in xmalloc /fuzzing/binutils-gdb/libiberty/xmalloc.c:147:12
> >     #2 0x50fb7e in demangle_template
> > /fuzzing/binutils-gdb/libiberty/cplus-dem.c:2228:27
> 
> This problem is in the libiberty library, which is maintained by the gcc
> project, not the binutils project.  Please could you refile this bug report
> with the gcc bug tracking system here:

No, the problem only exists in binutils c++filt. libiberty is fine.
Comment 8 Markus Trippelsdorf 2017-09-26 14:48:22 UTC
gcc's PR81680-81684 are all binutils c++filt only bugs.

(direct libiberty test:)
markus@x4 libiberty % valgrind ./a.out __H1r_H1
==9297== Memcheck, a memory error detector
==9297== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==9297== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==9297== Command: ./a.out __H1r_H1
==9297== 
failed demangling
Failed: __H1r_H1
==9297== 
==9297== HEAP SUMMARY:
==9297==     in use at exit: 0 bytes in 0 blocks
==9297==   total heap usage: 1 allocs, 1 frees, 1,024 bytes allocated
==9297== 
==9297== All heap blocks were freed -- no leaks are possible

(binutils c++filt:)
markus@x4 libiberty % valgrind --leak-check=full c++filt __H1r_H1 
==9426== Memcheck, a memory error detector
==9426== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==9426== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==9426== Command: c++filt __H1r_H1
==9426== 
__H1r_H1
==9426== 
==9426== HEAP SUMMARY:
==9426==     in use at exit: 9 bytes in 2 blocks
==9426==   total heap usage: 6 allocs, 4 frees, 1,105 bytes allocated
==9426== 
==9426== 9 (8 direct, 1 indirect) bytes in 1 blocks are definitely lost in loss record 2 of 2
==9426==    at 0x4834C0F: malloc (vg_replace_malloc.c:299)
==9426==    by 0x493D437: xmalloc (in /usr/lib64/binutils/x86_64-pc-linux-gnu/git/libbfd-2.29.51.20170917.so)
==9426==    by 0x492B62C: demangle_template (in /usr/lib64/binutils/x86_64-pc-linux-gnu/git/libbfd-2.29.51.20170917.so)
==9426==    by 0x492CD1B: demangle_signature (in /usr/lib64/binutils/x86_64-pc-linux-gnu/git/libbfd-2.29.51.20170917.so)
==9426==    by 0x492DDCA: internal_cplus_demangle (in /usr/lib64/binutils/x86_64-pc-linux-gnu/git/libbfd-2.29.51.20170917.so)
==9426==    by 0x4928A5A: cplus_demangle (in /usr/lib64/binutils/x86_64-pc-linux-gnu/git/libbfd-2.29.51.20170917.so)
==9426==    by 0x401F5D: demangle_it (in /usr/x86_64-pc-linux-gnu/binutils-bin/git/c++filt)
==9426==    by 0x401BA5: main (in /usr/x86_64-pc-linux-gnu/binutils-bin/git/c++filt)
==9426== 
==9426== LEAK SUMMARY:
==9426==    definitely lost: 8 bytes in 1 blocks
==9426==    indirectly lost: 1 bytes in 1 blocks
==9426==      possibly lost: 0 bytes in 0 blocks
==9426==    still reachable: 0 bytes in 0 blocks
==9426==         suppressed: 0 bytes in 0 blocks
Comment 9 Alan Modra 2018-05-09 08:16:10 UTC
Not a binutils bug.  Comment #6 is correct, #7 is incorrect, and #8 is leaping to the wrong conclusion.  In fact, comment #8 shows the leak is in demangle_template (in libibery/cplus-dem.c).  binutils/cxxfilt.c properly frees the string returned from cplus_demangle.