To Reproduce
./ddjvu ./poc.djvu
Debug Info
# ./ddjvu ./poc.djvu
AddressSanitizer:DEADLYSIGNAL
=================================================================
==27444==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc 0x00000080286b bp 0x7ffff2865320 sp 0x7ffff2865140 T2)
==27444==The signal is caused by a WRITE memory access.
==27444==Hint: address points to the zero page.
#0 0x80286b in DJVU::filter_bv(short*, int, int, int, int) /src/djvulibre-ddjvu/libdjvu/IW44Image.cpp:309:24
#1 0x7e7da2 in DJVU::IW44Image::Transform::Decode::backward(short*, int, int, int, int, int) /src/djvulibre-ddjvu/libdjvu/IW44Image.cpp:1883:7
#2 0x7e62af in DJVU::IW44Image::Map::image(signed char*, int, int, int) /src/djvulibre-ddjvu/libdjvu/IW44Image.cpp:714:7
#3 0x7fbd6d in DJVU::IWPixmap::get_pixmap() /src/djvulibre-ddjvu/libdjvu/IW44Image.cpp:1656:9
#4 0x621319 in DJVU::DjVuFile::decode_chunk(DJVU::GUTF8String const&, DJVU::GP<DJVU::ByteStream> const&, bool, bool, bool) /src/djvulibre-ddjvu/libdjvu/DjVuFile.cpp:984:15
#5 0x61835b in DJVU::DjVuFile::decode(DJVU::GP<DJVU::ByteStream> const&) /src/djvulibre-ddjvu/libdjvu/DjVuFile.cpp:1255:25
#6 0x616b2d in DJVU::DjVuFile::decode_func() /src/djvulibre-ddjvu/libdjvu/DjVuFile.cpp:484:5
#7 0x61689b in DJVU::DjVuFile::static_decode_func(void*) /src/djvulibre-ddjvu/libdjvu/DjVuFile.cpp:464:9
#8 0x77b07a in DJVU::GThread::start(void*) /src/djvulibre-ddjvu/libdjvu/GThreads.cpp:392:11
#9 0x7ffff6ceb6b9 in start_thread /build/glibc-e6zv40/glibc-2.23/nptl/pthread_create.c:333
#10 0x7ffff66014dc in clone /build/glibc-e6zv40/glibc-2.23/misc/../sysdeps/unix/sysv/linux/x86_64/clone.S:109
AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV /src/djvulibre-ddjvu/libdjvu/IW44Image.cpp:309:24 in DJVU::filter_bv(short*, int, int, int, int)
Thread T2 created by T0 here:
#0 0x4838ba in pthread_create /local/mnt/workspace/tmp/final/llvm-project/compiler-rt/lib/asan/asan_interceptors.cpp:214:3
#1 0x77b5a0 in DJVU::GThread::create(void (*)(void*), void*) /src/djvulibre-ddjvu/libdjvu/GThreads.cpp:440:13
#2 0x62552c in DJVU::DjVuFile::start_decode() /src/djvulibre-ddjvu/libdjvu/DjVuFile.cpp:1341:22
#3 0x62499b in DJVU::DjVuFile::resume_decode(bool) /src/djvulibre-ddjvu/libdjvu/DjVuFile.cpp:1366:7
#4 0x5fa9dd in DJVU::DjVuDocument::get_page(int, bool, DJVU::DjVuPort*) const /src/djvulibre-ddjvu/libdjvu/DjVuDocument.cpp:1070:12
#5 0x569f7a in DJVU::DjVuDocument::get_page(int, bool, DJVU::DjVuPort*) /src/djvulibre-ddjvu/libdjvu/./DjVuDocument.h:604:53
#6 0x5363cd in ddjvu_page_create(DJVU::ddjvu_document_s*, DJVU::ddjvu_job_s*, char const*, int) /src/djvulibre-ddjvu/libdjvu/ddjvuapi.cpp:1580:23
#7 0x4d33f6 in dopage(int) /src/djvulibre-ddjvu/tools/ddjvu.cpp:733:17
#8 0x4d4717 in parse_pagespec(char const*, int, void (*)(int)) /src/djvulibre-ddjvu/tools/ddjvu.cpp:825:11
#9 0x4df19b in main /src/djvulibre-ddjvu/tools/ddjvu.cpp:1214:3
#10 0x7ffff651a83f in __libc_start_main /build/glibc-e6zv40/glibc-2.23/csu/../csu/libc-start.c:291
==27444==ABORTING
I think unchecked variables data16 is the root cause of this vulnerability:
void
IW44Image::Map::image(signed char *img8, int rowsize, int pixsep, int fast)
{
// Allocate reconstruction buffer
short *data16;
size_t sz = bw * bh;
if (sz / (size_t)bw != (size_t)bh) // multiplication overflow
G_THROW("IW44Image: image size exceeds maximum (corrupted file?)");
GPBuffer<short> gdata16(data16,sz);
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
...
if (fast)
{
IW44Image::Transform::Decode::backward(data16, iw, ih, bw, 32, 2);
p = data16;
for (i=0; i<bh; i+=2,p+=bw)
for (int jj=0; jj<bw; jj+=2,p+=2)
p[bw] = p[bw+1] = p[1] = p[0];
}
else
{
IW44Image::Transform::Decode::backward(data16, iw, ih, bw, 32, 1);
}
Environment:
Credit: 1vanChen of NSFOCUS Security Team