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 in Cu6mPlayer::~Cu6mPlayer() #91
Comments
|
@fcambus Any chance you can submit the reproducers as PRs implemented as extra test files, so running the tests fails because of these bugs? (Some notes are in the 'debugging' section of the |
|
Sure thing! I'll be busy this weekend but will gladly take a look at this sometime next week. I really like the AdPlug project so I would be very happy to help. |
|
This one can be fixed by something like Also, in order to further enforce that no double delete[] occurs even when calling the destructor more than once, which would be a bug in itself, the following change does the job: |
|
This kind of addresses the symptom rather than the problem though. You fix the crash sure, but not the bug that caused the double-free in the first place. That bug is still there, you just don't hear about it any more because two of the detection points are now silenced. |
|
Sure, I could simply have removed the line from Cu6mPlayer::load(), which allocates song_data, and relied on the delete[] song_data; from ~Cu6mPlayer(). However, I decided to use a more robust option. The combination of my two hunks:
It's a fact that my constructs remove two detection points for some bugs... but they do eliminate potential vulnerabilities :) |
|
I see your point, but I'm not sure it's a wise idea to cater for people misusing the library. Are we going to go through every single format player and put checks like this in so that they can have the destructor called multiple times safely? Calling a destructor multiple times is in violation of the C++ standard, so it doesn't seem right to me to include code for handling a situation that can never exist. Consider this situation - the destructor is called the first time, which deallocates Essentially, once the destructor returns, you should consider all variables in the object to be assigned random values. From here you can see that assigning You say your patch also avoids leaks if the caller fails to call the destructor, but I'm not sure it would. If you call To my mind there are two solutions:
Unfortunately I don't know the library well enough to know whether |
|
Right, my hunks avoid a leak if the caller fails to call the destructor after calling In any case, even the simple fix of removing
There are fun, non-destructive ways to pinpoint things which should never have been / no longer be done, such as printing an error message, then sleeping for a large amount of time. That's what Google did for deprecating STLport for Android: https://softwareengineering.stackexchange.com/questions/381763/how-long-to-wait-before-deleting-a-deprecated-method . But it makes little sense to perform the work sprinkling these throughout the code base if there's no consensus that doing so is a good idea :) |
…g to the discussion in issue adplug#91.
|
This issue has been assigned CVE-2019-15151. |
|
@Malvineous: sent a pull request (#103) to add the test case triggering this issue. Let me know if it's what you add in mind. If so, I can prepare another PR for the other issues. |
|
Clearing the pointer after delete is the correct thing to do. Why would you keep the pointer after you call delete one it? The pointer is no longer valid, and there is no reason to keep it, other than causing crashes. The double free crash detected with tools like valgrind proves that clearing the pointer was not present. "what if the destructor is called twice" - what kind of call-path would cause that? That is the same as a double-free, only with an class object. |
While fuzzing AdPlug with American Fuzzy Lop, Frederic Cambus found several memory issues and reported them on github. Hook up the reproducers he provided as test cases in stresstest.cpp. This includes tests for the following github issues: * Issue adplug#85 ("Heap-based buffer overflow in CxadbmfPlayer::__bmf_convert_stream()") * Issue adplug#86 ("Heap-based buffer overflow in CdtmLoader::load()") * Issue adplug#87 ("Heap-based buffer overflow in CmkjPlayer::load()") * Issue adplug#88 ("Multiple heap-based buffer overflows in Ca2mLoader::load()") * Issue adplug#89 ("Multiple heap-based buffer overflows in CradLoader::load()") * Issue adplug#90 ("Multiple heap-based buffer overflows in CmtkLoader::load()") * Issue adplug#91 ("Double free in Cu6mPlayer::~Cu6mPlayer()") Co-authored-by: Frederic Cambus <fred@statdns.com> Bug: adplug#85 Bug: adplug#86 Bug: adplug#87 Bug: adplug#88 Bug: adplug#89 Bug: adplug#90 Bug: adplug#91
Leave deallocation of song_data to destructor when decompression fails, just like on success. This fixes CVE-2019-15151. Even though load() is apparently not supposed to be called twice (and bad things happen in many players if you do), let's also avoid leaking song_data's memory in that case. Fixes: adplug#91
While fuzzing AdPlug with American Fuzzy Lop, Frederic Cambus found several memory issues and reported them on github. Hook up the reproducers he provided as test cases in stresstest.cpp. This includes tests for the following github issues: * Issue #85 ("Heap-based buffer overflow in CxadbmfPlayer::__bmf_convert_stream()") * Issue #86 ("Heap-based buffer overflow in CdtmLoader::load()") * Issue #87 ("Heap-based buffer overflow in CmkjPlayer::load()") * Issue #88 ("Multiple heap-based buffer overflows in Ca2mLoader::load()") * Issue #89 ("Multiple heap-based buffer overflows in CradLoader::load()") * Issue #90 ("Multiple heap-based buffer overflows in CmtkLoader::load()") * Issue #91 ("Double free in Cu6mPlayer::~Cu6mPlayer()") Co-authored-by: Frederic Cambus <fred@statdns.com> Bug: #85 Bug: #86 Bug: #87 Bug: #88 Bug: #89 Bug: #90 Bug: #91
Hi,
While fuzzing AdPlug with American Fuzzy Lop, I found a double free in in Cu6mPlayer::~Cu6mPlayer(), in src/u6m.h L42.
Attaching a reproducer (gzipped so GitHub accepts it): double-free.gz
The text was updated successfully, but these errors were encountered: