This is an archive of the discontinued LLVM Phabricator instance.

[Decompression] Fail gracefully when out of memory
ClosedPublic

Authored by JDevlieghere on Sep 4 2017, 10:37 AM.

Details

Summary

This patch ensures that we fail gracefully when running out of memory when
allocating a buffer for decompression.

This provides a work-around for: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=3224

I've spend some time looking at a better solution but this is the best I could come up with. I'd be very excited if anyone has a better idea!

Diff Detail

Repository
rL LLVM

Event Timeline

JDevlieghere created this revision.Sep 4 2017, 10:37 AM
davide added a subscriber: davide.Sep 4 2017, 1:56 PM

I don't think we want to do something fancier, at least for now.
If you run out of memory, we just report instead of crashing.
Presumably, if something shows up, we can have an API that propagates back errors to the caller which can take an appropriate action, but I don't see a compelling use case (maybe I miss one?)

lib/Object/Decompressor.cpp
98–100 ↗(On Diff #113777)

fatal?

Use report_fatal_error

grimar added inline comments.Sep 5 2017, 1:15 AM
lib/Object/Decompressor.cpp
98–100 ↗(On Diff #113777)

Thanks for using report_fatal_error here, it is correct I belive because implementation of llvm::report_bad_alloc_error explicitly expects handler does not return.

test/tools/llvm-dwarfdump/dwarf-invalid-compression.test
2 ↗(On Diff #113777)

Would be nice to include some additional information here.
At least decompressor currently can know about section name,
probably something like:
Decompression of '.section_name_here' failed: unable to allocate 2314885530818453536 bytes. ?

JDevlieghere added a subscriber: kcc.

Thanks! I've updated the diff to include the section name.

My test case is the one from oss-fuzz, so unfortunately the section name doesn't say much. I don't know enough about the binary file format to change it.

grimar edited edge metadata.Sep 5 2017, 2:23 AM

I prepared a better binary, you can take it here:
https://drive.google.com/open?id=0B_OWr6ld9gUmZ3lqMkUzcThvd1E
(with that error message will contain proper section name).

It is prepared using following source code and invocation:
test.cpp:
int main() { return 0; }

gcc test.cpp -o out -g -Wl,--compress-debug-sections,zlib

After that result object was modified manually.
Decompressed size of .debug_frame section was changed to 0xffffffffffffffff in
compression header.

Please include this information into testcase. We usually do that for testcases,
which uses precompiled binary
(see llvm\test\DebugInfo\dwarfdump-decompression-error.test for example)

include/llvm/Object/Decompressor.h
46 ↗(On Diff #113809)

You do not need this getter, you can access to SectionName directly from handler as it is a static member function.

test/tools/llvm-dwarfdump/dwarf-invalid-compression.test
2 ↗(On Diff #113809)

Decompression -> decompression
(error messages starts from lowercase)

Thanks George, this has been very helpful!

Diff updated:

  • Better binary for test
  • Move test itself to the appropriate directory
  • Remove section name getter
grimar accepted this revision.Sep 5 2017, 3:03 AM

LGTM, thanks ! (minor nit)

lib/Object/Decompressor.cpp
98 ↗(On Diff #113814)

Did you mean 'const' instead of 'class' ?
Using of 'class' is inconsistend with LLVM code, I think it never uses it in
static_cast expressions, so I would remove it.

This revision is now accepted and ready to land.Sep 5 2017, 3:03 AM
JDevlieghere added inline comments.Sep 5 2017, 3:28 AM
lib/Object/Decompressor.cpp
98 ↗(On Diff #113814)

I had a conflicting variable named Decompressor and the compiler suggested doing this. Because I have never had to use this I wanted to give it try before renaming the variable to D. I renamed the variable but forgot to remove class. Thanks!

Seems like const works here as well, I'll go with that :-)

This revision was automatically updated to reflect the committed changes.