diff options
Diffstat (limited to 'fluent-bit/lib/jansson-e23f558/test/ossfuzz')
7 files changed, 310 insertions, 0 deletions
diff --git a/fluent-bit/lib/jansson-e23f558/test/ossfuzz/.gitignore b/fluent-bit/lib/jansson-e23f558/test/ossfuzz/.gitignore new file mode 100644 index 000000000..7fbb8677b --- /dev/null +++ b/fluent-bit/lib/jansson-e23f558/test/ossfuzz/.gitignore @@ -0,0 +1 @@ +json_load_dump_fuzzer diff --git a/fluent-bit/lib/jansson-e23f558/test/ossfuzz/Makefile.am b/fluent-bit/lib/jansson-e23f558/test/ossfuzz/Makefile.am new file mode 100644 index 000000000..a2e802e86 --- /dev/null +++ b/fluent-bit/lib/jansson-e23f558/test/ossfuzz/Makefile.am @@ -0,0 +1,32 @@ +AM_CPPFLAGS = -I$(top_builddir)/src -I$(top_srcdir)/src +LDADD = $(top_builddir)/src/libjansson.la + +if USE_OSSFUZZ_FLAG +FUZZ_FLAG = $(LIB_FUZZING_ENGINE) +else +if USE_OSSFUZZ_STATIC +LDADD += $(LIB_FUZZING_ENGINE) +FUZZ_FLAG = +else +LDADD += libstandaloneengine.a +FUZZ_FLAG = +endif +endif + +noinst_PROGRAMS = +noinst_LIBRARIES = + +if USE_OSSFUZZERS +noinst_PROGRAMS += \ + json_load_dump_fuzzer + +noinst_LIBRARIES += \ + libstandaloneengine.a +endif + +json_load_dump_fuzzer_SOURCES = json_load_dump_fuzzer.cc testinput.h +json_load_dump_fuzzer_CXXFLAGS = $(AM_CXXFLAGS) $(FUZZ_FLAG) +json_load_dump_fuzzer_LDFLAGS = $(AM_LDFLAGS) -static + +libstandaloneengine_a_SOURCES = standaloneengine.cc +libstandaloneengine_a_CXXFLAGS = $(AM_CXXFLAGS) diff --git a/fluent-bit/lib/jansson-e23f558/test/ossfuzz/json_load_dump_fuzzer.cc b/fluent-bit/lib/jansson-e23f558/test/ossfuzz/json_load_dump_fuzzer.cc new file mode 100644 index 000000000..bc3844e75 --- /dev/null +++ b/fluent-bit/lib/jansson-e23f558/test/ossfuzz/json_load_dump_fuzzer.cc @@ -0,0 +1,132 @@ +#include <stdint.h> +#include <stdlib.h> +#include <sys/types.h> +#include <inttypes.h> + +#include "jansson.h" + +static int enable_diags; + +#define FUZZ_DEBUG(FMT, ...) \ + if (enable_diags) \ + { \ + fprintf(stderr, FMT, ##__VA_ARGS__); \ + fprintf(stderr, "\n"); \ + } + + +static int json_dump_counter(const char *buffer, size_t size, void *data) +{ + uint64_t *counter = reinterpret_cast<uint64_t *>(data); + *counter += size; + return 0; +} + + +#define NUM_COMMAND_BYTES (sizeof(size_t) + sizeof(size_t) + 1) + +#define FUZZ_DUMP_CALLBACK 0x00 +#define FUZZ_DUMP_STRING 0x01 + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + json_error_t error; + unsigned char dump_mode; + + // Enable or disable diagnostics based on the FUZZ_VERBOSE environment flag. + enable_diags = (getenv("FUZZ_VERBOSE") != NULL); + + FUZZ_DEBUG("Input data length: %zd", size); + + if (size < NUM_COMMAND_BYTES) + { + return 0; + } + + // Use the first sizeof(size_t) bytes as load flags. + size_t load_flags = *(const size_t*)data; + data += sizeof(size_t); + + FUZZ_DEBUG("load_flags: 0x%zx\n" + "& JSON_REJECT_DUPLICATES = 0x%zx\n" + "& JSON_DECODE_ANY = 0x%zx\n" + "& JSON_DISABLE_EOF_CHECK = 0x%zx\n" + "& JSON_DECODE_INT_AS_REAL = 0x%zx\n" + "& JSON_ALLOW_NUL = 0x%zx\n", + load_flags, + load_flags & JSON_REJECT_DUPLICATES, + load_flags & JSON_DECODE_ANY, + load_flags & JSON_DISABLE_EOF_CHECK, + load_flags & JSON_DECODE_INT_AS_REAL, + load_flags & JSON_ALLOW_NUL); + + // Use the next sizeof(size_t) bytes as dump flags. + size_t dump_flags = *(const size_t*)data; + data += sizeof(size_t); + + FUZZ_DEBUG("dump_flags: 0x%zx\n" + "& JSON_MAX_INDENT = 0x%zx\n" + "& JSON_COMPACT = 0x%zx\n" + "& JSON_ENSURE_ASCII = 0x%zx\n" + "& JSON_SORT_KEYS = 0x%zx\n" + "& JSON_PRESERVE_ORDER = 0x%zx\n" + "& JSON_ENCODE_ANY = 0x%zx\n" + "& JSON_ESCAPE_SLASH = 0x%zx\n" + "& JSON_REAL_PRECISION = 0x%zx\n" + "& JSON_EMBED = 0x%zx\n", + dump_flags, + dump_flags & JSON_MAX_INDENT, + dump_flags & JSON_COMPACT, + dump_flags & JSON_ENSURE_ASCII, + dump_flags & JSON_SORT_KEYS, + dump_flags & JSON_PRESERVE_ORDER, + dump_flags & JSON_ENCODE_ANY, + dump_flags & JSON_ESCAPE_SLASH, + ((dump_flags >> 11) & 0x1F) << 11, + dump_flags & JSON_EMBED); + + // Use the next byte as the dump mode. + dump_mode = data[0]; + data++; + + FUZZ_DEBUG("dump_mode: 0x%x", (unsigned int)dump_mode); + + // Remove the command bytes from the size total. + size -= NUM_COMMAND_BYTES; + + // Attempt to load the remainder of the data with the given load flags. + const char* text = reinterpret_cast<const char *>(data); + json_t* jobj = json_loadb(text, size, load_flags, &error); + + if (jobj == NULL) + { + return 0; + } + + if (dump_mode & FUZZ_DUMP_STRING) + { + // Dump as a string. Remove indents so that we don't run out of memory. + char *out = json_dumps(jobj, dump_flags & ~JSON_MAX_INDENT); + if (out != NULL) + { + free(out); + } + } + else + { + // Default is callback mode. + // + // Attempt to dump the loaded json object with the given dump flags. + uint64_t counter = 0; + + json_dump_callback(jobj, json_dump_counter, &counter, dump_flags); + FUZZ_DEBUG("Counter function counted %" PRIu64 " bytes.", counter); + } + + if (jobj) + { + json_decref(jobj); + } + + return 0; +} diff --git a/fluent-bit/lib/jansson-e23f558/test/ossfuzz/ossfuzz.sh b/fluent-bit/lib/jansson-e23f558/test/ossfuzz/ossfuzz.sh new file mode 100755 index 000000000..59740c253 --- /dev/null +++ b/fluent-bit/lib/jansson-e23f558/test/ossfuzz/ossfuzz.sh @@ -0,0 +1,30 @@ +#!/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)" + +# Install dependencies +apt-get -y install automake libtool + +# Compile the fuzzer. +autoreconf -i +./configure --enable-ossfuzzers +make + +# Copy the fuzzer to the output directory. +cp -v test/ossfuzz/json_load_dump_fuzzer $OUT/ + +# Zip up all input files to use as a test corpus +find test/suites -name "input" -print | zip $OUT/json_load_dump_fuzzer_seed_corpus.zip -@ diff --git a/fluent-bit/lib/jansson-e23f558/test/ossfuzz/standaloneengine.cc b/fluent-bit/lib/jansson-e23f558/test/ossfuzz/standaloneengine.cc new file mode 100644 index 000000000..175360e4a --- /dev/null +++ b/fluent-bit/lib/jansson-e23f558/test/ossfuzz/standaloneengine.cc @@ -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/fluent-bit/lib/jansson-e23f558/test/ossfuzz/testinput.h b/fluent-bit/lib/jansson-e23f558/test/ossfuzz/testinput.h new file mode 100644 index 000000000..6ab9b515e --- /dev/null +++ b/fluent-bit/lib/jansson-e23f558/test/ossfuzz/testinput.h @@ -0,0 +1,3 @@ +#include <inttypes.h> + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size); diff --git a/fluent-bit/lib/jansson-e23f558/test/ossfuzz/travisoss.sh b/fluent-bit/lib/jansson-e23f558/test/ossfuzz/travisoss.sh new file mode 100755 index 000000000..ddcfa075a --- /dev/null +++ b/fluent-bit/lib/jansson-e23f558/test/ossfuzz/travisoss.sh @@ -0,0 +1,38 @@ +#!/bin/bash + +set -ex + +PROJECT_NAME=jansson + +# Clone the oss-fuzz repository +git clone https://github.com/google/oss-fuzz.git /tmp/ossfuzz + +if [[ ! -d /tmp/ossfuzz/projects/${PROJECT_NAME} ]] +then + echo "Could not find the ${PROJECT_NAME} project in ossfuzz" + + # Exit with a success code while the jansson project is not expected to exist + # on oss-fuzz. + exit 0 +fi + +# Work out which repo to clone from, inside Docker +if [[ ${TRAVIS_PULL_REQUEST} != "false" ]] +then + # Pull-request branch + REPO=${TRAVIS_PULL_REQUEST_SLUG} + BRANCH=${TRAVIS_PULL_REQUEST_BRANCH} +else + # Push build. + REPO=${TRAVIS_REPO_SLUG} + BRANCH=${TRAVIS_BRANCH} +fi + +# Modify the oss-fuzz Dockerfile so that we're checking out the current branch on travis. +sed -i "s@https://github.com/akheron/jansson.git@-b ${BRANCH} https://github.com/${REPO}.git@" /tmp/ossfuzz/projects/${PROJECT_NAME}/Dockerfile + +# Try and build the fuzzers +pushd /tmp/ossfuzz +python infra/helper.py build_image --pull ${PROJECT_NAME} +python infra/helper.py build_fuzzers ${PROJECT_NAME} +popd |