[32-bit only] Integer overflow in Stream.h:BaseMemStream::BaseMemStream()
There is an integer overflow in the method BaseMemStream::BaseMemStream() in Stream.h:
BaseMemStream(T *bufA, Goffset startA, Goffset lengthA, Object &&dictA) : BaseStream(std::move(dictA), lengthA) {
buf = bufA;
start = startA;
length = lengthA;
bufEnd = buf + start + length;
bufPtr = buf + start;
}
If the project is compiled in 32 bit, bufPtr and buf are char pointers whose size is 4, and start's type is long long whose size is 8. So there is an integer overflow here.
PoC
Here is the PoC: poc-BaseMemStream.zip
Version
The tested version is git commit 165bfbe2.
Environment
root@pen:~/fuzz/fuzz_poppler# lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 18.04.3 LTS
Release: 18.04
Codename: bionic
root@pen:~/fuzz/fuzz_poppler# uname -a
Linux pen 4.15.0-72-generic #81-Ubuntu SMP Tue Nov 26 12:20:02 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux
Compilation
Let's compile poppler in 32 bit:
- Add the following to CMakeList.txt:
add_compile_options(-m32 -O0 -ggdb3 -fsanitize=address)
link_libraries(-m32)
- Configure:
CC=gcc CXX=g++ cmake -DCMAKE_BUILD_TYPE=debug -DBUILD_SHARED_LIBS=OFF -DFONT_CONFIGURATION=generic -DENABLE_DCTDECODER=none -DENABLE_LIBOPENJPEG=none -DENABLE_CMS=none -DENABLE_LIBPNG=OFF -DENABLE_ZLIB=OFF -DENABLE_LIBTIFF=OFF -DENABLE_LIBJPEG=OFF -DENABLE_GLIB=OFF -DENABLE_LIBCURL=OFF -DENABLE_QT5=OFF -DENABLE_UTILS=OFF -DWITH_Cairo=OFF -DWITH_NSS3=OFF ../poppler
- Make project:
make poppler poppler-cpp
- Compile the PoC:
g++ -O0 -ggdb3 -fsanitize=address -m32 -std=c++11 -I poppler/cpp pdf_read.cc -o pdf_read-gcc-asan-32 poppler-gcc-asan-32/cpp/libpoppler-cpp.a poppler-gcc-asan-32/libpoppler.a -lfreetype -lpng16
Crash Log
root@pen:~/fuzz/fuzz_poppler# ./pdf_read-gcc-asan-32 crash-BaseMemStream.pdf
ASAN:DEADLYSIGNAL
=================================================================
==27751==ERROR: AddressSanitizer: SEGV on unknown address 0x5ba2082a (pc 0x56658cf0 bp 0xffe7ece8 sp 0xffe7ecc0 T0)
==27751==The signal is caused by a READ memory access.
#0 0x56658cef in BaseMemStream<char const>::getChar() /root/fuzz/fuzz_poppler/poppler/poppler/Stream.h:605
#1 0x566b3c0d in Object::streamGetChar() const /root/fuzz/fuzz_poppler/poppler/poppler/Object.h:404
#2 0x567d860a in Lexer::getChar(bool) /root/fuzz/fuzz_poppler/poppler/poppler/Lexer.cc:120
#3 0x567d8bc8 in Lexer::getObj(int) /root/fuzz/fuzz_poppler/poppler/poppler/Lexer.cc:166
#4 0x5680bfc3 in Parser::Parser(XRef*, Stream*, bool) /root/fuzz/fuzz_poppler/poppler/poppler/Parser.cc:49
#5 0x568f3907 in XRef::readXRef(long long*, std::vector<long long, std::allocator<long long> >*, std::vector<int, std::allocator<int> >*) /root/fuzz/fuzz_poppler/poppler/poppler/XRef.cc:464
#6 0x568f0d82 in XRef::XRef(BaseStream*, long long, long long, bool*, bool) /root/fuzz/fuzz_poppler/poppler/poppler/XRef.cc:282
#7 0x56810a1b in PDFDoc::setup(GooString const*, GooString const*) /root/fuzz/fuzz_poppler/poppler/poppler/PDFDoc.cc:272
#8 0x56810417 in PDFDoc::PDFDoc(BaseStream*, GooString const*, GooString const*, void*) /root/fuzz/fuzz_poppler/poppler/poppler/PDFDoc.cc:241
#9 0x56647953 in poppler::document_private::document_private(char const*, int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) /root/fuzz/fuzz_poppler/poppler/cpp/poppler-document.cpp:134
#10 0x5664e3c9 in poppler::document::load_from_raw_data(char const*, int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) /root/fuzz/fuzz_poppler/poppler/cpp/poppler-document.cpp:1179
#11 0x56645aba in readPdf(unsigned char const*, unsigned int) /root/fuzz/fuzz_poppler/pdf_read.cc:16
#12 0x566462f5 in main /root/fuzz/fuzz_poppler/pdf_read.cc:65
#13 0xf73d8e80 in __libc_start_main (/lib/i386-linux-gnu/libc.so.6+0x18e80)
#14 0x56645850 (/root/fuzz/fuzz_poppler/pdf_read-gcc-asan-32+0x64850)
AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV /root/fuzz/fuzz_poppler/poppler/poppler/Stream.h:605 in BaseMemStream<char const>::getChar()
==27751==ABORTING