Skip to content

Commit

Permalink
Add fuzzers infrastructure
Browse files Browse the repository at this point in the history
  • Loading branch information
rouault committed Jul 2, 2017
1 parent b4d03f0 commit 0181a28
Show file tree
Hide file tree
Showing 10 changed files with 599 additions and 0 deletions.
10 changes: 10 additions & 0 deletions fuzzers/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
clean:
$(RM) -f *.o *.a

fuzzingengine.o: fuzzingengine.c
$(CC) $(CFLAGS) -c -o $@ $<

dummyfuzzers: fuzzingengine.o
$(AR) r libFuzzingEngine.a fuzzingengine.o
CXX="${CXX}" CXXFLAGS="-L. ${CXXFLAGS}" SRC=/tmp OUT=/tmp ./build_google_oss_fuzzers.sh
OUT=/tmp ./build_seed_corpus.sh
38 changes: 38 additions & 0 deletions fuzzers/README.TXT
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
This directory contain fuzzer main functions and scripts for the
Google OSS Fuzz project: https://github.com/google/oss-fuzz/

The main build scripts are in:
https://github.com/google/oss-fuzz/tree/master/projects/postgis
and call scripts in this directory.

The list of issues is in:
https://bugs.chromium.org/p/oss-fuzz/issues/list?q=postgis

- Simulate the build of (dummy) fuzzers like OSS Fuzz does:
$ make dummyfuzzers
They are created in /tmp/*_fuzzer as well as with the
/tmp/*_fuzzer_seed_corpus.zip files

Run one:
$ /tmp/wkt_import_fuzzer a_file_name

- Run locally OSS Fuzz:
$ git clone https://github.com/google/oss-fuzz.git
$ cd oss-fuzz
$ python infra/helper.py build_image postgis

Build fuzzers with the address sanitizer (could use undefined, etc...)
$ python infra/helper.py build_fuzzers --sanitizer address postgis

Test a particular fuzzer (replace wkt_import_fuzzer by other fuzzers
like the ones generated in /tmp by "make dummyfuzzers")
$ python infra/helper.py run_fuzzerpostgis wkt_import_fuzzer


How to deal with issues reported in https://bugs.chromium.org/p/oss-fuzz/issues/list?q=postgis ?

1. Leave a comment in (chromium database) bug entry to indicate that you work on it
2. Work
3. Commit a bug fix with log including "Credit to OSS-Fuzz" and a link to the bugs.chromium.org ticket
4. Add in the bugs.chromium.org ticket a link to the Trac changeset implementing the fix.
5. Check chromium closed the bug (after one or two days typically)
40 changes: 40 additions & 0 deletions fuzzers/build_google_oss_fuzzers.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#!/bin/bash

set -e

if [ "$SRC" == "" ]; then
echo "SRC env var not defined"
exit 1
fi

if [ "$OUT" == "" ]; then
echo "OUT env var not defined"
exit 1
fi

if [ "$CXX" == "" ]; then
echo "CXX env var not defined"
exit 1
fi

SRC_DIR=$(dirname $0)/..

build_fuzzer()
{
fuzzerName=$1
sourceFilename=$2
shift
shift
echo "Building fuzzer $fuzzerName"
$CXX $CXXFLAGS -std=c++11 -I$SRC_DIR/liblwgeom \
$sourceFilename $* -o $OUT/$fuzzerName \
-lFuzzingEngine -lstdc++ $SRC_DIR/liblwgeom/.libs/liblwgeom.a
}

fuzzerFiles=$(dirname $0)/*.cpp
for F in $fuzzerFiles; do
fuzzerName=$(basename $F .cpp)
build_fuzzer $fuzzerName $F
done

cp $(dirname $0)/*.dict $(dirname $0)/*.options $OUT/
10 changes: 10 additions & 0 deletions fuzzers/build_seed_corpus.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#!/bin/bash

set -e

if [ "$OUT" == "" ]; then
echo "OUT env var not defined"
exit 1
fi

# Nothing for now
69 changes: 69 additions & 0 deletions fuzzers/fuzzingengine.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/******************************************************************************
*
* Project: GDAL
* Purpose: Fuzzer
* Author: Even Rouault, even.rouault at spatialys.com
*
******************************************************************************
* Copyright (c) 2017, Even Rouault <even.rouault at spatialys.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
****************************************************************************/

#include <stdlib.h>
#include <stdio.h>

int LLVMFuzzerTestOneInput(void *buf, size_t len);
int LLVMFuzzerInitialize(int* argc, char*** argv);

int main(int argc, char* argv[])
{
LLVMFuzzerInitialize(&argc, &argv);
if( argc < 2 )
{
return LLVMFuzzerTestOneInput(" ", 1);
}
else
{
int nRet = 0;
void* buf = NULL;
int nLen = 0;
FILE* f = fopen(argv[1], "rb");
if( !f )
{
fprintf(stderr, "%s does not exist.\n", argv[1]);
exit(1);
}
fseek(f, 0, SEEK_END);
nLen = (int)ftell(f);
fseek(f, 0, SEEK_SET);
buf = malloc(nLen);
if( !buf )
{
fprintf(stderr, "malloc failed.\n");
fclose(f);
exit(1);
}
fread(buf, nLen, 1, f);
fclose(f);
nRet = LLVMFuzzerTestOneInput(buf, nLen);
free(buf);
return nRet;
}
}
199 changes: 199 additions & 0 deletions fuzzers/wkb_import_fuzzer.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
/******************************************************************************
*
* Project: PostGIS
* Purpose: Fuzzer
* Author: Even Rouault, even.rouault at spatialys.com
*
******************************************************************************
* Copyright (c) 2017, Even Rouault <even.rouault at spatialys.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
****************************************************************************/

#include <assert.h>
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <setjmp.h>

#include <set>

extern "C"
{
#include "liblwgeom.h"

void GEOSCoordSeq_destroy() { assert(0); }
void GEOSClipByRect() { assert(0); }
void GEOSUnion() { assert(0); }
void GEOSCoordSeq_getDimensions() { assert(0); }
void GEOSPreparedCovers() { assert(0); }
void GEOSPreparedContains() { assert(0); }
void GEOSSymDifference() { assert(0); }
void GEOSUnionCascaded() { assert(0); }
void GEOSGetExteriorRing() { assert(0); }
void GEOSCoordSeq_setX() { assert(0); }
void GEOSGeom_createLineString() { assert(0); }
void GEOSCoordSeq_getY() { assert(0); }
void GEOSEquals() { assert(0); }
void GEOSRelatePatternMatch() { assert(0); }
void GEOSGeom_createCollection() { assert(0); }
void GEOSGeom_extractUniquePoints() { assert(0); }
void GEOSNormalize() { assert(0); }
void GEOSVoronoiDiagram() { assert(0); }
void GEOSArea() { assert(0); }
void GEOSLineMerge() { assert(0); }
void GEOSGeom_createPolygon() { assert(0); }
void GEOSGetCentroid() { assert(0); }
void GEOSCoordSeq_create() { assert(0); }
void GEOSFree() { assert(0); }
void initGEOS() { assert(0); }
void GEOSIntersection() { assert(0); }
void GEOSEnvelope() { assert(0); }
void GEOSGetGeometryN() { assert(0); }
void GEOSSTRtree_insert() { assert(0); }
void GEOSGeomTypeId() { assert(0); }
void GEOSBoundary() { assert(0); }
void GEOSversion() { assert(0); }
void GEOSGetInteriorRingN() { assert(0); }
void GEOSCoordSeq_setY() { assert(0); }
void GEOSGetSRID() { assert(0); }
void GEOSGeom_destroy() { assert(0); }
void GEOSGeom_createEmptyPolygon() { assert(0); }
void GEOSPolygonize() { assert(0); }
void GEOSCoordSeq_getX() { assert(0); }
void GEOSSharedPaths() { assert(0); }
void GEOSSTRtree_create() { assert(0); }
void GEOSGeom_clone() { assert(0); }
void GEOSRelateBoundaryNodeRule() { assert(0); }
void GEOSSnap() { assert(0); }
void GEOSRelatePattern() { assert(0); }
void GEOSSetSRID() { assert(0); }
void GEOSisValid() { assert(0); }
void GEOSContains() { assert(0); }
void GEOSPreparedGeom_destroy() { assert(0); }
void GEOSCoordSeq_setZ() { assert(0); }
void GEOSOffsetCurve() { assert(0); }
void GEOSUnaryUnion() { assert(0); }
void GEOSPrepare() { assert(0); }
void GEOSCoordSeq_getSize() { assert(0); }
void GEOSGetNumInteriorRings() { assert(0); }
void GEOSGetNumGeometries() { assert(0); }
void GEOSisSimple() { assert(0); }
void GEOSDifference() { assert(0); }
void GEOSPreparedIntersects() { assert(0); }
void GEOSisEmpty() { assert(0); }
void GEOSPointOnSurface() { assert(0); }
void GEOSSTRtree_query() { assert(0); }
void GEOSGeom_createPoint() { assert(0); }
void GEOSSTRtree_destroy() { assert(0); }
void GEOSIntersects() { assert(0); }
void GEOSHasZ() { assert(0); }
void GEOSGeom_getCoordSeq() { assert(0); }
void GEOSCoordSeq_getZ() { assert(0); }
void GEOSGeom_createLinearRing() { assert(0); }
void GEOSGeomType() { assert(0); }
void GEOSDelaunayTriangulation() { assert(0); }

void geod_init() { assert(0); }
void geod_inverse() { assert(0); }
void geod_direct() { assert(0); }
void geod_polygon_init() { assert(0); }
void geod_polygon_addpoint() { assert(0); }
void geod_polygon_compute() { assert(0); }

}

extern "C" int LLVMFuzzerInitialize(int* argc, char*** argv);

// Keep active heap allocated memory corresponding to returns of allocator()
// and reallocator()
std::set<void*> oSetPointers;
jmp_buf jmpBuf;

extern "C"
{
static void *
allocator(size_t size)
{
void *mem = malloc(size);
oSetPointers.insert(mem);
return mem;
}

static void
freeor(void *mem)
{
oSetPointers.erase(mem);
free(mem);
}

static void *
reallocator(void *mem, size_t size)
{
oSetPointers.erase(mem);
void *ret = realloc(mem, size);
oSetPointers.insert(ret);
return ret;
}

static void
noticereporter(const char *, va_list )
{
}

static void
errorreporter(const char *, va_list )
{
// Cleanup any heap-allocated memory still active
for(std::set<void*>::iterator oIter = oSetPointers.begin();
oIter != oSetPointers.end(); ++oIter )
{
free(*oIter);
}
oSetPointers.clear();
// Abort everything to jump to setjmp() call
longjmp(jmpBuf, 1);
}

static void
debuglogger(int, const char *, va_list)
{
}

}

int LLVMFuzzerInitialize(int* /*argc*/, char*** /*argv*/)
{
lwgeom_set_handlers(allocator, reallocator, freeor, errorreporter, noticereporter);
lwgeom_set_debuglogger(debuglogger);
return 0;
}

extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len);

int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len)
{
if( setjmp(jmpBuf) )
return 0;
LWGEOM* lwgeom = lwgeom_from_wkb(buf, len, LW_PARSER_CHECK_NONE);
lwgeom_free(lwgeom);
//assert( oSetPointers.empty() );
return 0;
}
2 changes: 2 additions & 0 deletions fuzzers/wkb_import_fuzzer.options
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[libfuzzer]
max_len = 100000
Loading

0 comments on commit 0181a28

Please sign in to comment.