Project: qpdf (qpdf/qpdf), language: c++
Vulnerability instance: qpdf.cve-2017-18183
Sanitizer: address

================= Bug Report (1/1) ==================
## Source: GitHub Issue
## URL: https://github.com/qpdf/qpdf/issues/143
## Description:
Issue: qpdf/qpdf#143
Title: stack overflow / crash on malformed input in QPDFWriter::enqueueObject(QPDFObjectHandle)
State: closed
Created by: hannob
Created at: 2017-08-12 07:51:55+00:00

Issue Body:
The attached file will crash qpdf. It seems it's running into an endless recursion and thus a stack overflow.
Found with afl.

[qpdf-stackoverflow.zip](https://github.com/qpdf/qpdf/files/1219594/qpdf-stackoverflow.zip)

```
==24283==ERROR: AddressSanitizer: stack-overflow on address 0x7ffda4d32f78 (pc 0x00000050ba42 bp 0x7ffda4d337c0 sp 0x7ffda4d32f60 T0)
    #0 0x50ba41 in operator new(unsigned long) (/r/qpdf/qpdf+0x50ba41)
    #1 0x62c243 in PointerHolder<QPDFObject>::PointerHolder(QPDFObject*) /f/qpdf/include/qpdf/PointerHolder.hh:74:17
    #2 0x62c243 in QPDFObjectHandle::QPDFObjectHandle(QPDF*, int, int) /f/qpdf/libqpdf/QPDFObjectHandle.cc:46
    #3 0x62c243 in QPDFObjectHandle::newIndirect(QPDF*, int, int) /f/qpdf/libqpdf/QPDFObjectHandle.cc:1183
    #4 0x5b73af in QPDFObjectHandle::Factory::newIndirect(QPDF*, int, int) /f/qpdf/include/qpdf/QPDFObjectHandle.hh:520:13
    #5 0x5b73af in QPDF::getObjectByID(int, int) /f/qpdf/libqpdf/QPDF.cc:1889
    #6 0x674910 in QPDFWriter::enqueueObject(QPDFObjectHandle) /f/qpdf/libqpdf/QPDFWriter.cc:1057:27
    #7 0x67491b in QPDFWriter::enqueueObject(QPDFObjectHandle) /f/qpdf/libqpdf/QPDFWriter.cc:1057:3
    #8 0x67491b in QPDFWriter::enqueueObject(QPDFObjectHandle) /f/qpdf/libqpdf/QPDFWriter.cc:1057:3



Comments:
Comment by jberkenbilt on 2017-08-12 11:36:38+00:00:
You're doing me a great service by finding all these cases. I hope you keep it up. I should be releasing 7.0.0 pretty soon. It would be great to fix as many of these as possible. I've coded a fix for this, but I need to do some extra code inspection to make sure my fix is good. It definitely doesn't break any existing tests, and the test suite is very thorough, and it also catches this problem, but I'm not sure it fully addresses the underlying issue, so I'll do more checking before I push to master.

---

Comment by ghost on 2018-02-14 10:08:40+00:00:
This has been assigned CVE-2017-18183

Attachments:
https://github.com/qpdf/qpdf/files/1219594/qpdf-stackoverflow.zip

Build script:
#!/bin/bash -eu
# Minimized build script with only core build commands
set -eu
./configure --static --prefix="$WORK"
make -j$(nproc) all
make install -j$(nproc)
cmake . -DCMAKE_INSTALL_PREFIX="$WORK" -DENABLE_STATIC:bool=on
make -j$(nproc)
./configure \
  --enable-static \
  --disable-shared \
  --prefix="$WORK" \
  LDFLAGS="-L$WORK/lib" \
  CPPFLAGS="-I$WORK/include" \
  LIBS="-pthread"

Dockerfile:
FROM hwiwonlee/secb.base:latest
RUN apt-get update && apt-get install -y make autoconf automake libtool cmake nasm
RUN git clone https://github.com/qpdf/qpdf qpdf
RUN git -C qpdf checkout 36b3fe5af761b7032a506808cf6ce6d37c297bfc
WORKDIR $SRC/qpdf
COPY build.sh $SRC/

Additional files:
filename: qpdf_read_memory_fuzzer.cc
content: #include "qpdf/qpdf-c.h"

#include <cstddef>
#include <cstdint>
#include <cstdlib>
#include <string>
#include <vector>

extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
  _qpdf_data* qpdf = qpdf_init();
  const char* buffer = reinterpret_cast<const char*>(data);
  qpdf_read_memory(qpdf, /*description=*/"", buffer, size, /*password=*/"");
  qpdf_cleanup(&qpdf);
  return 0;
}