Hi!
While doing fuzzing I found out that FreeImage_LoadFromMemory tries to allocate huge amount of memory:
==60==ERROR: AddressSanitizer: allocator is out of memory trying to allocate 0x1f0aa262a0 bytes
#0 0x4e3add in malloc /llvm-project/compiler-rt/lib/asan/asan_malloc_linux.cpp:129:3
#1 0x522802 in FreeImage_Aligned_Malloc(unsigned long, unsigned long) /freeimage-svn/FreeImage/trunk/Source/FreeImage/BitmapAccess.cpp:183:19
#2 0x523ef1 in FreeImage_AllocateBitmap(int, unsigned char*, unsigned int, FREE_IMAGE_TYPE, int, int, int, unsigned int, unsigned int, unsigned int) /freeimage-svn/FreeImage/trunk/Source/FreeImage/BitmapAccess.cpp:390:26
#3 0x527793 in FreeImage_AllocateHeader /freeimage-svn/FreeImage/trunk/Source/FreeImage/BitmapAccess.cpp:482:9
#4 0x74ee12 in Load(FreeImageIO*, void*, int, int, void*) /freeimage-svn/FreeImage/trunk/Source/FreeImage/PluginPNM.cpp:290:12
#5 0x589d39 in FreeImage_LoadFromHandle /freeimage-svn/FreeImage/trunk/Source/FreeImage/Plugin.cpp:386:24
#6 0x575160 in FreeImage_LoadFromMemory /freeimage-svn/FreeImage/trunk/Source/FreeImage/MemoryIO.cpp:88:10
#7 0x51d137 in LLVMFuzzerTestOneInput /load_from_memory_fuzzer.cc:35:26
#8 0x449c01 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) /llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:611:15
#9 0x43421c in fuzzer::RunOneTest(fuzzer::Fuzzer*, char const*, unsigned long) /llvm-project/compiler-rt/lib/fuzzer/FuzzerDriver.cpp:324:6
#10 0x439f8b in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) /llvm-project/compiler-rt/lib/fuzzer/FuzzerDriver.cpp:860:9
#11 0x462cd2 in main /llvm-project/compiler-rt/lib/fuzzer/FuzzerMain.cpp:20:10
#12 0x7f086a1f70b2 in __libc_start_main /build/glibc-eX1tMB/glibc-2.31/csu/../csu/libc-start.c:308:16
Also, there are inputs that coud pass sanitizer's checks. For example 28 byte input tries allocates about 13Gb memory (because height parameter is very big).
In function Load located at Source/FreeImage/PluginPNM.cpp:215 there is no checks for big width and height
245 const int width = GetInt(io, handle);
(gdb) n
246 const int height = GetInt(io, handle);
(gdb) n
247 int maxval = 1;
(gdb) p width
$1 = 66666
(gdb) p height
$2 = 666612
(gdb) n
249 if (width < 0 || height < 0) {
(gdb)
There are only checks that values are negative, may be we need some checks like:
width * height * some_value < image_size
How to reporduce:
/load_from_memory_fuzzer /fuzz/crashes/crash-34f40ef0993115491a23a66478f380d7abc236b7