diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 14506516..2e236476 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -11,4 +11,5 @@ add_subdirectory(unit) add_subdirectory(xmltester) add_subdirectory(bigtest) +add_subdirectory(fuzz) diff --git a/tests/fuzz/CMakeLists.txt b/tests/fuzz/CMakeLists.txt new file mode 100644 index 00000000..d0bd7a02 --- /dev/null +++ b/tests/fuzz/CMakeLists.txt @@ -0,0 +1,15 @@ +################################################################################ +# Part of CMake configuration for GEOS +# +# Copyright (C) 2018 Mateusz Loskot +# +# This is free software; you can redistribute and/or modify it under +# the terms of the GNU Lesser General Public Licence as published +# by the Free Software Foundation. +# See the COPYING file for more information. +################################################################################ +if(DEFINED ENV{LIB_FUZZING_ENGINE}) + add_executable(fuzz_geo2 fuzz_geo2.c) + target_include_directories(fuzz_geo2 PUBLIC $) + target_link_libraries(fuzz_geo2 geos_c $ENV{LIB_FUZZING_ENGINE}) +endif() diff --git a/tests/fuzz/fuzz_geo2.c b/tests/fuzz/fuzz_geo2.c new file mode 100644 index 00000000..ceee7ea6 --- /dev/null +++ b/tests/fuzz/fuzz_geo2.c @@ -0,0 +1,69 @@ +#include +#include +#include +#include +#include + +#include "geos_c.h" + +static int initialized = 0; +FILE * flogOut; + +void +notice(const char *fmt, ...) { + va_list ap; + fprintf( flogOut, "NOTICE: "); + va_start (ap, fmt); + vfprintf( flogOut, fmt, ap); + va_end(ap); + fprintf( flogOut, "\n" ); +} + +void +log_and_exit(const char *fmt, ...) { + va_list ap; + fprintf( flogOut, "ERROR: "); + va_start (ap, fmt); + vfprintf( flogOut, fmt, ap); + va_end(ap); + fprintf( flogOut, "\n" ); +} + +int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + if (initialized == 0) { + flogOut = fopen("/dev/null", "wb"); + initGEOS(notice, log_and_exit); + initialized = 1; + } + size_t sep; + for (sep = 0; sep < Size; sep ++) { + if (Data[sep] == 0) { + break; + } + } + if (sep == Size) { + return 0; + } + GEOSGeometry *g1 = GEOSGeomFromWKT(Data); + + if (g1 != NULL) { + GEOSGeometry *g2 = GEOSGeomFromWKB_buf(Data+sep, Size-sep); + if (g2 != NULL) { + size_t usize; + GEOSGeometry *g3 = GEOSIntersection(g1, g2); + GEOSGeom_destroy(g3); + g3 = GEOSDifference(g1, g2); + GEOSGeom_destroy(g3); + g3 = GEOSUnion(g1, g2); + GEOSGeom_destroy(g3); + unsigned char* uptr = GEOSGeomToWKB_buf(g1, &usize); + free(uptr); + GEOSGeom_destroy(g2); + } + char * r = GEOSGeomToWKT(g1); + free(r); + GEOSGeom_destroy(g1); + } + return 0; +} +