diff options
-rw-r--r-- | .travis.yml | 6 | ||||
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | ossfuzz/Makefile | 59 | ||||
-rw-r--r-- | ossfuzz/compress_fuzzer.c | 25 | ||||
-rw-r--r-- | ossfuzz/decompress_fuzzer.c | 28 | ||||
-rwxr-xr-x | ossfuzz/ossfuzz.sh | 23 | ||||
-rw-r--r-- | ossfuzz/standaloneengine.c | 74 | ||||
-rw-r--r-- | ossfuzz/testinput.h | 15 | ||||
-rwxr-xr-x | ossfuzz/travisoss.sh | 24 |
9 files changed, 256 insertions, 0 deletions
diff --git a/.travis.yml b/.travis.yml index 8d23214..af5cf0f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -206,5 +206,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 @@ -34,6 +34,7 @@ LZ4DIR = lib PRGDIR = programs TESTDIR = tests EXDIR = examples +FUZZDIR = ossfuzz include Makefile.inc @@ -76,6 +77,7 @@ clean: @$(MAKE) -C $(PRGDIR) $@ > $(VOID) @$(MAKE) -C $(TESTDIR) $@ > $(VOID) @$(MAKE) -C $(EXDIR) $@ > $(VOID) + @$(MAKE) -C $(FUZZDIR) $@ > $(VOID) @$(MAKE) -C contrib/gen_manual $@ > $(VOID) @$(RM) lz4$(EXT) @echo Cleaning completed diff --git a/ossfuzz/Makefile b/ossfuzz/Makefile new file mode 100644 index 0000000..bd01123 --- /dev/null +++ b/ossfuzz/Makefile @@ -0,0 +1,59 @@ +# ########################################################################## +# 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 +# ########################################################################## +# compress_fuzzer : OSS Fuzz test tool +# decompress_fuzzer : OSS Fuzz test tool +# ########################################################################## + +LZ4DIR := ../lib +LIB_FUZZING_ENGINE ?= standaloneengine.o + +DEBUGLEVEL?= 1 +DEBUGFLAGS = -g -DLZ4_DEBUG=$(DEBUGLEVEL) + +LZ4_CFLAGS = $(CFLAGS) $(DEBUGFLAGS) $(MOREFLAGS) +LZ4_CXXFLAGS = $(CXXFLAGS) $(DEBUGFLAGS) $(MOREFLAGS) +LZ4_CPPFLAGS = $(CPPFLAGS) -I$(LZ4DIR) -DXXH_NAMESPACE=LZ4_ + +# Include a rule to build the static library if calling this target +# directly. +$(LZ4DIR)/liblz4.a: + $(MAKE) -C $(LZ4DIR) CFLAGS="$(LZ4_CFLAGS)" liblz4.a + +%.o: %.c + $(CC) -c $(LZ4_CFLAGS) $(LZ4_CPPFLAGS) $< -o $@ + +# Generic rule for generating fuzzers +%_fuzzer: %_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" + $(CC) -c $(LZ4_CFLAGS) $(LZ4_CPPFLAGS) standaloneengine.c -o standaloneengine.o + + # Now compile the actual fuzzer. + $(CXX) $(LZ4_CXXFLAGS) $(LZ4_CPPFLAGS) $(LDFLAGS) $(LIB_FUZZING_ENGINE) $^ -o $@$(EXT) + +%_fuzzer_clean: + $(RM) $*_fuzzer $*_fuzzer.o standaloneengine.o + +.PHONY: clean +clean: compress_fuzzer_clean decompress_fuzzer_clean diff --git a/ossfuzz/compress_fuzzer.c b/ossfuzz/compress_fuzzer.c new file mode 100644 index 0000000..3908534 --- /dev/null +++ b/ossfuzz/compress_fuzzer.c @@ -0,0 +1,25 @@ +#include <stddef.h> +#include <stdint.h> +#include <stdlib.h> +#include "lz4.h" + +#define CHECK(COND) if (!(COND)) { abort(); } + +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); + + CHECK(dest_buffer != NULL); + + // Allocation succeeded, try compressing the incoming data. + int result = LZ4_compress_default((const char*)data, + dest_buffer, + size, + compressed_dest_size); + CHECK(result != 0); + + free(dest_buffer); + + return 0; +} diff --git a/ossfuzz/decompress_fuzzer.c b/ossfuzz/decompress_fuzzer.c new file mode 100644 index 0000000..e6e14c4 --- /dev/null +++ b/ossfuzz/decompress_fuzzer.c @@ -0,0 +1,28 @@ +#include <stddef.h> +#include <stdint.h> +#include <stdlib.h> +#include "lz4.h" + +#define CHECK(COND) if (!(COND)) { abort(); } + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + // TODO: Size input buffer pseudo-randomly based on seed extracted from input + size_t const buffer_size = 10 * 1024 * 1024; + char *const dest_buffer = (char *)malloc(buffer_size); + + CHECK(dest_buffer != NULL); + + // Allocation succeeded, try decompressing the incoming data. + int result = LZ4_decompress_safe((const char*)data, + dest_buffer, + size, + buffer_size); + + // Ignore the result of decompression. + (void)result; + + free(dest_buffer); + + return 0; +} diff --git a/ossfuzz/ossfuzz.sh b/ossfuzz/ossfuzz.sh new file mode 100755 index 0000000..a76b0d6 --- /dev/null +++ b/ossfuzz/ossfuzz.sh @@ -0,0 +1,23 @@ +#!/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 + +echo "CC: $CC" +echo "CXX: $CXX" +echo "LIB_FUZZING_ENGINE: $LIB_FUZZING_ENGINE" +echo "CFLAGS: $CFLAGS" +echo "CXXFLAGS: $CXXFLAGS" +echo "OUT: $OUT" + +export MAKEFLAGS+="-j$(nproc)" + +pushd ossfuzz +make V=1 compress_fuzzer decompress_fuzzer +popd + +# Copy the fuzzers to the target directory. +cp -v ossfuzz/compress_fuzzer ossfuzz/decompress_fuzzer $OUT/ diff --git a/ossfuzz/standaloneengine.c b/ossfuzz/standaloneengine.c new file mode 100644 index 0000000..175360e --- /dev/null +++ b/ossfuzz/standaloneengine.c @@ -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 index 0000000..0e50a3c --- /dev/null +++ b/ossfuzz/testinput.h @@ -0,0 +1,15 @@ +#ifndef TESTINPUT_H_INCLUDED +#define TESTINPUT_H_INCLUDED + +#include <inttypes.h> + +#if defined (__cplusplus) +extern "C" { +#endif + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size); + +#if defined(__cplusplus) +} +#endif +#endif diff --git a/ossfuzz/travisoss.sh b/ossfuzz/travisoss.sh new file mode 100755 index 0000000..3b2f26f --- /dev/null +++ b/ossfuzz/travisoss.sh @@ -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 |