mirror of https://github.com/google/oss-fuzz.git
Improve the xpdf pdf fuzzer (#7241)
- Do not fail silently on compilation issues - Use a static version of freetype - Render the PDF on a bitmap, to exercise more code paths. - I'm planning on adding more outputs (maybe in new fuzzers) for Postscript for example - Exercise more metadata gathering functions - Use a stream instead of a file, to speed the fuzzer up - Allocate the PDFDoc on the stack instead of the heap - Don't install recommended packages Co-authored-by: Autofuzz team <security-tps@google.com>
This commit is contained in:
parent
35d3c728c3
commit
04a13fdefc
|
@ -15,7 +15,9 @@
|
|||
################################################################################
|
||||
|
||||
FROM gcr.io/oss-fuzz-base/base-builder
|
||||
RUN apt-get update && apt-get install software-properties-common -y && apt-get update && apt-get install -y make wget cmake libpng-dev libfreetype-dev zlib1g-dev
|
||||
RUN git clone --depth 1 https://gitlab.freedesktop.org/freetype/freetype
|
||||
RUN apt-get update
|
||||
RUN apt-get install --no-install-recommends -y make wget cmake qtbase5-dev libcups2-dev autoconf automake autotools-dev libtool
|
||||
RUN wget https://dl.xpdfreader.com/xpdf-latest.tar.gz
|
||||
|
||||
WORKDIR $SRC
|
||||
|
|
|
@ -20,23 +20,37 @@ tar -zxf xpdf-latest.tar.gz
|
|||
dir_name=`tar -tzf xpdf-latest.tar.gz | head -1 | cut -f1 -d"/"`
|
||||
cd $dir_name
|
||||
|
||||
PREFIX=$WORK/prefix
|
||||
mkdir -p $PREFIX
|
||||
|
||||
export PKG_CONFIG="`which pkg-config` --static"
|
||||
export PKG_CONFIG_PATH=$PREFIX/lib/pkgconfig
|
||||
export PATH=$PREFIX/bin:$PATH
|
||||
pushd $SRC/freetype
|
||||
./autogen.sh
|
||||
./configure --prefix="$PREFIX" --disable-shared PKG_CONFIG_PATH="$PKG_CONFIG_PATH" --with-png=no --with-zlib=no
|
||||
make -j$(nproc)
|
||||
make install
|
||||
popd
|
||||
|
||||
# Make minor change in the CMakeFiles file.
|
||||
sed -i 's/#--- object files needed by XpdfWidget/add_library(testXpdfStatic STATIC $<TARGET_OBJECTS:xpdf_objs>)\n#--- object files needed by XpdfWidget/' ./xpdf/CMakeLists.txt
|
||||
sed -i 's/#--- pdftops/add_library(testXpdfWidgetStatic STATIC $<TARGET_OBJECTS:xpdf_widget_objs>\n $<TARGET_OBJECTS:splash_objs>\n $<TARGET_OBJECTS:xpdf_objs>\n ${FREETYPE_LIBRARY}\n ${FREETYPE_OTHER_LIBS})\n#--- pdftops/' ./xpdf/CMakeLists.txt
|
||||
|
||||
# Build the project
|
||||
mkdir build && cd build
|
||||
export LD=$CXX
|
||||
cmake ../ -DCMAKE_C_FLAGS="$CFLAGS" -DCMAKE_CXX_FLAGS="$CXXFLAGS" \
|
||||
-DOPI_SUPPORT=ON -DMULTITHREADED=0 -DCMAKE_DISABLE_FIND_PACKAGE_Qt4=1 \
|
||||
-DCMAKE_DISABLE_FIND_PACKAGE_Qt5Widgets=1 -DSPLASH_CMYK=ON
|
||||
make -i || true
|
||||
-DOPI_SUPPORT=ON -DSPLASH_CMYK=ON -DMULTITHREADED=ON \
|
||||
-DUSE_EXCEPTIONS=ON -DXPDFWIDGET_PRINTING=ON -DFREETYPE_DIR="$PREFIX"
|
||||
make
|
||||
|
||||
# Build fuzzers
|
||||
for fuzzer in zxdoc pdfload; do
|
||||
cp ../../fuzz_$fuzzer.cc .
|
||||
$CXX fuzz_$fuzzer.cc -o $OUT/fuzz_$fuzzer $CXXFLAGS $LIB_FUZZING_ENGINE \
|
||||
./xpdf/libtestXpdfStatic.a ./fofi/libfofi.a ./goo/libgoo.a \
|
||||
-I../ -I../goo -I../fofi -I. -I../xpdf
|
||||
./xpdf/libtestXpdfStatic.a ./fofi/libfofi.a ./goo/libgoo.a ./splash/libsplash.a ./xpdf/libtestXpdfWidgetStatic.a /work/prefix/lib/libfreetype.a \
|
||||
-I../ -I../goo -I../fofi -I. -I../xpdf -I../splash
|
||||
done
|
||||
|
||||
# Copy over options files
|
||||
|
|
|
@ -12,57 +12,92 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <fuzzer/FuzzedDataProvider.h>
|
||||
|
||||
#include <vector>
|
||||
#include <aconf.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <exception>
|
||||
#include "PDFDoc.h"
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <png.h>
|
||||
|
||||
#include "gmem.h"
|
||||
#include "gmempp.h"
|
||||
#include "parseargs.h"
|
||||
#include "GString.h"
|
||||
#include "gfile.h"
|
||||
#include "GlobalParams.h"
|
||||
#include "Zoox.h"
|
||||
#include "Object.h"
|
||||
#include "PDFDoc.h"
|
||||
#include "SplashBitmap.h"
|
||||
#include "Splash.h"
|
||||
#include "SplashOutputDev.h"
|
||||
#include "Stream.h"
|
||||
#include "config.h"
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
|
||||
{
|
||||
char filename[256];
|
||||
sprintf(filename, "/tmp/libfuzzer.%d", getpid());
|
||||
FILE *fp = fopen(filename, "wb");
|
||||
if (!fp)
|
||||
return 0;
|
||||
fwrite(data, size, 1, fp);
|
||||
fclose(fp);
|
||||
FuzzedDataProvider fdp (data, size);
|
||||
double hdpi = fdp.ConsumeFloatingPoint<double>();
|
||||
double vdpi = fdp.ConsumeFloatingPoint<double>();
|
||||
int rotate = fdp.ConsumeIntegral<int>();
|
||||
bool useMediaBox = fdp.ConsumeBool();
|
||||
bool crop = fdp.ConsumeBool();
|
||||
bool printing = fdp.ConsumeBool();
|
||||
std::vector<char> payload = fdp.ConsumeRemainingBytes<char>();
|
||||
|
||||
Object xpdf_obj;
|
||||
xpdf_obj.initNull();
|
||||
BaseStream *stream = new MemStream(payload.data(), 0, payload.size(), &xpdf_obj);
|
||||
|
||||
// Main fuzzing logic
|
||||
Object info, xfa;
|
||||
Object *acroForm;
|
||||
globalParams = new GlobalParams(NULL);
|
||||
globalParams->setErrQuiet(1);
|
||||
globalParams->setupBaseFonts(NULL);
|
||||
char yes[] = "yes";
|
||||
globalParams->setEnableFreeType(yes); // Yes, it's a string and not a bool.
|
||||
globalParams->setErrQuiet(1);
|
||||
|
||||
PDFDoc *doc = NULL;
|
||||
try {
|
||||
doc = new PDFDoc(filename, NULL, NULL);
|
||||
if (doc->isOk() == gTrue)
|
||||
PDFDoc doc(stream);
|
||||
if (doc.isOk() == gTrue)
|
||||
{
|
||||
doc->getNumPages();
|
||||
doc->getOutline();
|
||||
doc->getStructTreeRoot();
|
||||
doc->getXRef();
|
||||
doc->readMetadata();
|
||||
doc.getNumPages();
|
||||
doc.getOutline();
|
||||
doc.getStructTreeRoot();
|
||||
doc.getXRef();
|
||||
doc.okToPrint(gTrue);
|
||||
doc.okToCopy(gTrue);
|
||||
doc.okToChange(gTrue);
|
||||
doc.okToAddNotes(gTrue);
|
||||
doc.isLinearized();
|
||||
doc.getPDFVersion();
|
||||
|
||||
GString *metadata;
|
||||
if ((metadata = doc.readMetadata())) {
|
||||
(void)metadata->getCString();
|
||||
}
|
||||
delete metadata;
|
||||
|
||||
Object info;
|
||||
doc->getDocInfo(&info);
|
||||
doc.getDocInfo(&info);
|
||||
if (info.isDict()) {
|
||||
info.getDict();
|
||||
}
|
||||
info.free();
|
||||
|
||||
if ((acroForm = doc->getCatalog()->getAcroForm())->isDict()) {
|
||||
if ((acroForm = doc.getCatalog()->getAcroForm())->isDict()) {
|
||||
acroForm->dictLookup("XFA", &xfa);
|
||||
xfa.free();
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < doc->getNumPages(); i++) {
|
||||
doc->getLinks(i);
|
||||
auto page = doc->getCatalog()->getPage(i);
|
||||
for (size_t i = 0; i < doc.getNumPages(); i++) {
|
||||
doc.getLinks(i);
|
||||
auto page = doc.getCatalog()->getPage(i);
|
||||
if (!page->isOk()) {
|
||||
continue;
|
||||
}
|
||||
|
@ -70,18 +105,24 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
|
|||
page->getMetadata();
|
||||
page->getResourceDict();
|
||||
}
|
||||
|
||||
SplashColor paperColor = {0xff, 0xff, 0xff};
|
||||
SplashOutputDev *splashOut = new SplashOutputDev(splashModeRGB8, 1, gFalse, paperColor);
|
||||
splashOut->setNoComposite(gTrue);
|
||||
splashOut->startDoc(doc.getXRef());
|
||||
for (size_t i = 0; i <= doc.getNumPages(); ++i) {
|
||||
doc.displayPage(splashOut, i, hdpi, vdpi, rotate, useMediaBox, crop, printing);
|
||||
}
|
||||
(void)splashOut->getBitmap();
|
||||
|
||||
delete splashOut;
|
||||
}
|
||||
} catch (...) {
|
||||
|
||||
}
|
||||
|
||||
// Cleanup
|
||||
if (doc != NULL)
|
||||
delete doc;
|
||||
delete globalParams;
|
||||
|
||||
// cleanup temporary file
|
||||
unlink(filename);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue