lvandeve / lodepng

PNG encoder and decoder in C and C++.
zlib License
2.11k stars 426 forks source link

vulnerability Discover #165

Closed Cvjark closed 2 years ago

Cvjark commented 2 years ago

==93357==ERROR: AddressSanitizer: requested allocation size 0x2040616141210 (0x2040616142210 after adjustments for alignment, red zones etc.) exceeds maximum supported size of 0x10000000000 (thread T0)

0 0x55d0e8 in realloc /home/bupt/桌面/tools/llvm-12.0.1/llvm/projects/compiler-rt/lib/asan/asan_malloc_linux.cpp:164

#1 0x5af9f4 in lodepng_realloc(void*, unsigned long) /home/bupt/lodepng/lodepng.cpp:86:10
#2 0x5f3b58 in ucvector_reserve(ucvector*, unsigned long) /home/bupt/lodepng/lodepng.cpp:273:18
#3 0x5f3a0d in ucvector_resize(ucvector*, unsigned long) /home/bupt/lodepng/lodepng.cpp:286:10
#4 0x5ed6c1 in zlib_decompress(unsigned char**, unsigned long*, unsigned long, unsigned char const*, unsigned long, LodePNGDecompressSettings const*) /home/bupt/lodepng/lodepng.cpp:2232:7
#5 0x5d8cfe in decodeGeneric(unsigned char**, unsigned int*, unsigned int*, LodePNGState*, unsigned char const*, unsigned long) /home/bupt/lodepng/lodepng.cpp:4958:20
#6 0x5d4e13 in lodepng_decode(unsigned char**, unsigned int*, unsigned int*, LodePNGState*, unsigned char const*, unsigned long) /home/bupt/lodepng/lodepng.cpp:4979:3
#7 0x5ef615 in lodepng::decode(std::vector<unsigned char, std::allocator<unsigned char> >&, unsigned int&, unsigned int&, lodepng::State&, unsigned char const*, unsigned long) /home/bupt/lodepng/lodepng.cpp:6400:20
#8 0x61c13a in (anonymous namespace)::testDecode(lodepng::State&, unsigned char const*, unsigned long) /home/bupt/lodepng/./lodepng_fuzzer.cpp:55:10
#9 0x61bbdc in LLVMFuzzerTestOneInput /home/bupt/lodepng/./lodepng_fuzzer.cpp:82:20
#10 0x466def in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) /home/bupt/桌面/tools/llvm-12.0.1/llvm/projects/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:599
#11 0x46caa4 in fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned long, bool, fuzzer::InputInfo*, bool, bool*) /home/bupt/桌面/tools/llvm-12.0.1/llvm/projects/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:505
#12 0x46e10e in fuzzer::Fuzzer::MutateAndTestOne() /home/bupt/桌面/tools/llvm-12.0.1/llvm/projects/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:746
#13 0x471d3f in fuzzer::Fuzzer::Loop(std::__Fuzzer::vector<fuzzer::SizedFile, fuzzer::fuzzer_allocator<fuzzer::SizedFile> >&) /home/bupt/桌面/tools/llvm-12.0.1/llvm/projects/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:883
#14 0x45827d in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) /home/bupt/桌面/tools/llvm-12.0.1/llvm/projects/compiler-rt/lib/fuzzer/FuzzerDriver.cpp:906
#15 0x420cb2 in main /home/bupt/桌面/tools/llvm-12.0.1/llvm/projects/compiler-rt/lib/fuzzer/FuzzerMain.cpp:20
#16 0x7f1067d69c86 in __libc_start_main /build/glibc-uZu3wS/glibc-2.27/csu/../csu/libc-start.c:310

==93357==HINT: if you don't care about these errors you may set allocator_may_return_null=1 SUMMARY: AddressSanitizer: allocation-size-too-big /home/bupt/桌面/tools/llvm-12.0.1/llvm/projects/compiler-rt/lib/asan/asan_malloc_linux.cpp:164 in realloc ==93357==ABORTING MS: 1 InsertRepeatedBytes-; base unit: 8998bc5c20a834a66a360df3b0af13c6caa67f1e 0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x0,0x0,0x0,0x0,0xff,0xff,0x21,0xff,0xff,0xff,0xff,0xff,0xff,0xdf,0xff,0x2f,0xff, \x89PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\x10\x10\x10\x10\x10\x10\x10\x10\x00\x00\x00\x00\xff\xff!\xff\xff\xff\xff\xff\xff\xdf\xff/\xff artifact_prefix='./'; Test unit written to ./crash-a035941c68e4300728c51d72fa43243ea3046182 Base64: iVBORw0KGgoAAAANSUhEUgAQEBAQEBAQEAAAAAD//yH////////f/y// crash-a035941c68e4300728c51d72fa43243ea3046182.zip

lvandeve commented 2 years ago

It's trying to allocate a very large buffer because the header indicates 1052688x269488144 pixels. You can use a compile option to prevent large allocations for fuzzing: add -DLODEPNG_MAX_ALLOC=100000000 to the compiler flags.

It can be argued whether trying such large allocation is a vulnerability or not, but by default lodepng does not set a limit, say e.g. an image that requires 100GB of memory: there can be legit use cases, and legit machines that can decode it, while it'd still go out of memory on other machines.

Which is why the DLODEPNG_MAX_ALLOC compiler option is added, does -DLODEPNG_MAX_ALLOC=100000000 solve the issue for you?

Cvjark commented 2 years ago

yes, it is. I forgot to add a limit for the fuzzer, thank you for your reply.