Add a fuzzing target that compiles in the oss-fuzz environment
authorMax Dymond <cmeister2@gmail.com>
Tue, 25 Jun 2019 16:22:02 +0000 (17:22 +0100)
committerMax Dymond <cmeister2@gmail.com>
Fri, 28 Jun 2019 07:30:02 +0000 (08:30 +0100)
.travis.yml
Makefile
ossfuzz/Makefile [new file with mode: 0644]
ossfuzz/compress_fuzzer.cc [new file with mode: 0644]
ossfuzz/ossfuzz.sh [new file with mode: 0755]
ossfuzz/standaloneengine.cc [new file with mode: 0644]
ossfuzz/testinput.h [new file with mode: 0644]
ossfuzz/travisoss.sh [new file with mode: 0755]

index ee643e5..4d45e89 100644 (file)
@@ -194,5 +194,11 @@ matrix:
         - pushd build
         - DESTDIR=./staging ninja install
         - tree ./staging
+
+    # oss-fuzz compilation test
+    - name: Compile OSS-Fuzz targets
+      script:
+        - ./ossfuzz/travisoss.sh
+
   allow_failures:
     - env: ALLOW_FAILURES=true
index e24cec5..34835fd 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -34,6 +34,7 @@ LZ4DIR  = lib
 PRGDIR  = programs
 TESTDIR = tests
 EXDIR   = examples
+FUZZDIR = ossfuzz
 
 include Makefile.inc
 
diff --git a/ossfuzz/Makefile b/ossfuzz/Makefile
new file mode 100644 (file)
index 0000000..94829b2
--- /dev/null
@@ -0,0 +1,54 @@
+# ##########################################################################
+# LZ4 oss fuzzer - Makefile
+#
+# GPL v2 License
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# You can contact the author at :
+#  - LZ4 homepage : http://www.lz4.org
+#  - LZ4 source repository : https://github.com/lz4/lz4
+# ##########################################################################
+# lz4_fuzzer : OSS Fuzz test tool
+# ##########################################################################
+
+LZ4DIR  := ../lib
+LIB_FUZZING_ENGINE ?= standaloneengine.o
+
+DEBUGLEVEL?= 1
+DEBUGFLAGS = -g -DLZ4_DEBUG=$(DEBUGLEVEL)
+
+CFLAGS  += -I$(LZ4DIR) $(DEBUGFLAGS) $(MOREFLAGS)
+CPPFLAGS+= -I$(LZ4DIR) -DXXH_NAMESPACE=LZ4_
+FLAGS    = $(CFLAGS) $(CPPFLAGS) $(LDFLAGS)
+
+include ../Makefile.inc
+
+# Include a rule to build the static library if calling this target
+# directly.
+$(LZ4DIR)/liblz4.a:
+       $(MAKE) -C $(LZ4DIR) CFLAGS="$(CFLAGS)" liblz4.a
+
+%.o: %.cc
+       $(CXX) -c $(CFLAGS) $(CPPFLAGS) $< -o $@
+
+.PHONY: compress_fuzzer
+compress_fuzzer: compress_fuzzer.o $(LZ4DIR)/liblz4.a
+       # Compile the standalone code just in case. The OSS-Fuzz code might
+       # override the LIB_FUZZING_ENGINE value to "-fsanitize=fuzzer"
+       $(CXX) -c $(CFLAGS) $(CPPFLAGS) standaloneengine.cc -o standaloneengine.o
+
+       # Now compile the actual fuzzer.
+       $(CXX) $(FLAGS) $(LIB_FUZZING_ENGINE) $^ -o $@$(EXT)
diff --git a/ossfuzz/compress_fuzzer.cc b/ossfuzz/compress_fuzzer.cc
new file mode 100644 (file)
index 0000000..006a0ab
--- /dev/null
@@ -0,0 +1,22 @@
+#include <stddef.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include "lz4.h"
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
+{
+  size_t const compressed_dest_size = LZ4_compressBound(size);
+  char *const dest_buffer = (char *)malloc(compressed_dest_size);
+
+  int result = LZ4_compress_default((const char*)data, dest_buffer,
+                                    size, compressed_dest_size);
+
+  if (result == 0)
+  {
+    abort();
+  }
+
+  free(dest_buffer);
+
+  return 0;
+}
diff --git a/ossfuzz/ossfuzz.sh b/ossfuzz/ossfuzz.sh
new file mode 100755 (executable)
index 0000000..e0cb63c
--- /dev/null
@@ -0,0 +1,26 @@
+#!/bin/bash -eu
+
+# This script is called by the oss-fuzz main project when compiling the fuzz
+# targets. This script is regression tested by travisoss.sh.
+
+# Save off the current folder as the build root.
+export BUILD_ROOT=$PWD
+
+# lz4 uses CPPFLAGS rather than CXX flags.
+export CPPFLAGS="${CXXFLAGS}"
+
+echo "CC: $CC"
+echo "CXX: $CXX"
+echo "LIB_FUZZING_ENGINE: $LIB_FUZZING_ENGINE"
+echo "CFLAGS: $CFLAGS"
+echo "CPPFLAGS: $CPPFLAGS"
+echo "OUT: $OUT"
+
+export MAKEFLAGS+="-j$(nproc)"
+
+pushd ossfuzz
+make V=1 compress_fuzzer
+popd
+
+# Copy the fuzzers to the target directory.
+cp -v ossfuzz/compress_fuzzer $OUT/
diff --git a/ossfuzz/standaloneengine.cc b/ossfuzz/standaloneengine.cc
new file mode 100644 (file)
index 0000000..175360e
--- /dev/null
@@ -0,0 +1,74 @@
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "testinput.h"
+
+/**
+ * Main procedure for standalone fuzzing engine.
+ *
+ * Reads filenames from the argument array. For each filename, read the file
+ * into memory and then call the fuzzing interface with the data.
+ */
+int main(int argc, char **argv)
+{
+  int ii;
+  for(ii = 1; ii < argc; ii++)
+  {
+    FILE *infile;
+    printf("[%s] ", argv[ii]);
+
+    /* Try and open the file. */
+    infile = fopen(argv[ii], "rb");
+    if(infile)
+    {
+      uint8_t *buffer = NULL;
+      size_t buffer_len;
+
+      printf("Opened.. ");
+
+      /* Get the length of the file. */
+      fseek(infile, 0L, SEEK_END);
+      buffer_len = ftell(infile);
+
+      /* Reset the file indicator to the beginning of the file. */
+      fseek(infile, 0L, SEEK_SET);
+
+      /* Allocate a buffer for the file contents. */
+      buffer = (uint8_t *)calloc(buffer_len, sizeof(uint8_t));
+      if(buffer)
+      {
+        /* Read all the text from the file into the buffer. */
+        fread(buffer, sizeof(uint8_t), buffer_len, infile);
+        printf("Read %zu bytes, fuzzing.. ", buffer_len);
+
+        /* Call the fuzzer with the data. */
+        LLVMFuzzerTestOneInput(buffer, buffer_len);
+
+        printf("complete !!");
+
+        /* Free the buffer as it's no longer needed. */
+        free(buffer);
+        buffer = NULL;
+      }
+      else
+      {
+        fprintf(stderr,
+                "[%s] Failed to allocate %zu bytes \n",
+                argv[ii],
+                buffer_len);
+      }
+
+      /* Close the file as it's no longer needed. */
+      fclose(infile);
+      infile = NULL;
+    }
+    else
+    {
+      /* Failed to open the file. Maybe wrong name or wrong permissions? */
+      fprintf(stderr, "[%s] Open failed. \n", argv[ii]);
+    }
+
+    printf("\n");
+  }
+}
diff --git a/ossfuzz/testinput.h b/ossfuzz/testinput.h
new file mode 100644 (file)
index 0000000..6ab9b51
--- /dev/null
@@ -0,0 +1,3 @@
+#include <inttypes.h>
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
diff --git a/ossfuzz/travisoss.sh b/ossfuzz/travisoss.sh
new file mode 100755 (executable)
index 0000000..3b2f26f
--- /dev/null
@@ -0,0 +1,24 @@
+#!/bin/bash
+
+set -ex
+
+# Clone the oss-fuzz repository
+git clone https://github.com/google/oss-fuzz.git /tmp/ossfuzz
+
+if [[ ! -d /tmp/ossfuzz/projects/lz4 ]]
+then
+    echo "Could not find the lz4 project in ossfuzz"
+
+    # Exit with a success code while the lz4 project is not expected to exist
+    # on oss-fuzz.
+    exit 0
+fi
+
+# Modify the oss-fuzz Dockerfile so that we're checking out the current branch on travis.
+sed -i "s@https://github.com/lz4/lz4.git@-b $TRAVIS_BRANCH https://github.com/lz4/lz4.git@" /tmp/ossfuzz/projects/lz4/Dockerfile
+
+# Try and build the fuzzers
+pushd /tmp/ossfuzz
+python infra/helper.py build_image --pull lz4
+python infra/helper.py build_fuzzers lz4
+popd