diff --git a/libmspack/test/fuzzing/README.md b/libmspack/test/fuzzing/README.md new file mode 100644 index 0000000..eee9b9b --- /dev/null +++ b/libmspack/test/fuzzing/README.md @@ -0,0 +1,7 @@ +This directory includes a fuzzing function that could be linked into Google's OSS-Fuzz project + +https://google.github.io/oss-fuzz/ + +This integration is not yet complete, see: +* https://github.com/kyz/libmspack/pull/44 +* https://github.com/google/oss-fuzz/pull/5085 diff --git a/libmspack/test/fuzzing/extract_fuzzer.c b/libmspack/test/fuzzing/extract_fuzzer.c new file mode 100644 index 0000000..91f1ec3 --- /dev/null +++ b/libmspack/test/fuzzing/extract_fuzzer.c @@ -0,0 +1,111 @@ +/* This file is part of libmspack. + * (C) 2021 Stuart Caie. + * + * libmspack is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License (LGPL) version 2.1 + * + * For further details, see the file COPYING.LIB distributed with libmspack + */ + +#include +#include +#include +#include +#include + +/* mspack_system implementation which reads memory and writes nothing */ +struct mem_buf { + const uint8_t *data; + size_t length; +}; +struct mem_file { + char *data; + size_t length, posn; +}; +static struct mspack_file *m_open(struct mspack_system *self, const char *filename, int mode) { + struct mem_buf *fn = (struct mem_buf *) filename; + struct mem_file *fh; + if ((mode != MSPACK_SYS_OPEN_READ && mode != MSPACK_SYS_OPEN_WRITE) || + (mode == MSPACK_SYS_OPEN_READ && fn == NULL)) return NULL; + + if ((fh = (struct mem_file *) malloc(sizeof(struct mem_file)))) { + if (mode == MSPACK_SYS_OPEN_READ) { + fh->data = (char *) fn->data; + fh->length = fn->length; + } + else { + fh->data = NULL; + fh->length = 0; + } + fh->posn = 0; + return (struct mspack_file *) fh; + } + return NULL; +} +static void m_close(struct mspack_file *file) { + free(file); +} +static int m_read(struct mspack_file *file, void *buffer, int bytes) { + struct mem_file *fh = (struct mem_file *) file; + int avail; + if (!fh || !buffer || bytes < 0) return -1; + avail = fh->length - fh->posn; + if (bytes > avail) bytes = avail; + if (bytes > 0) memcpy(buffer, &fh->data[fh->posn], bytes); + fh->posn += bytes; + return bytes; +} +static int m_write(struct mspack_file *file, void *buffer, int bytes) { + return (!file || !buffer || bytes < 0) ? -1 : bytes; +} +static int m_seek(struct mspack_file *file, off_t offset, int mode) { + struct mem_file *fh = (struct mem_file *) file; + if (!fh) return 1; + switch (mode) { + case MSPACK_SYS_SEEK_START: break; + case MSPACK_SYS_SEEK_CUR: offset += (off_t) fh->posn; break; + case MSPACK_SYS_SEEK_END: offset += (off_t) fh->length; break; + default: return 1; + } + if ((offset < 0) || (offset > (off_t) fh->length)) return 1; + fh->posn = (size_t) offset; + return 0; +} +static off_t m_tell(struct mspack_file *file) { + struct mem_file *fh = (struct mem_file *) file; + return (fh) ? (off_t) fh->posn : -1; +} +static void m_msg(struct mspack_file *file, const char *format, ...) { +} +static void *m_alloc(struct mspack_system *self, size_t bytes) { + return malloc(bytes); +} +static void m_free(void *buffer) { + free(buffer); +} +static void m_copy(void *src, void *dest, size_t bytes) { + memcpy(dest, src, bytes); +} +static struct mspack_system mem_system = { + &m_open, &m_close, &m_read, &m_write, &m_seek, &m_tell, + &m_msg, &m_alloc, &m_free, &m_copy, NULL +}; + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + struct mscab_decompressor *cabd; + struct mscabd_cabinet *cab; + struct mscabd_file *file; + struct mem_buf source = { data, size }; + + if ((cabd = mspack_create_cab_decompressor(&mem_system))) { + if ((cab = cabd->open(cabd, (char *) &source))) { + /* attempt to extract all files (to nowhere) */ + for (file = cab->files; file; file = file->next) { + cabd->extract(cabd, file, NULL); + } + cabd->close(cabd, cab); + } + } + mspack_destroy_cab_decompressor(cabd); + return 0; +} diff --git a/libmspack/test/fuzzing/oss_fuzz_build.sh b/libmspack/test/fuzzing/oss_fuzz_build.sh new file mode 100755 index 0000000..51681dc --- /dev/null +++ b/libmspack/test/fuzzing/oss_fuzz_build.sh @@ -0,0 +1,12 @@ +#!/bin/bash -eu + +cd libmspack +./autogen.sh +./configure +make -j$(nproc) + +find . -name "*.o" -exec ar rcs fuzz_lib.a {} \; +$CXX $CXXFLAGS -I./mspack -c $SRC/extract_fuzzer.c -o extract_fuzzer.o +$CXX $CXXFLAGS $LIB_FUZZING_ENGINE extract_fuzzer.o -o $OUT/extract_fuzzer fuzz_lib.a + +zip $OUT/extract_fuzzer_seed_corpus.zip $SRC/libmspack/libmspack/test/test_files/cabd/partial_shortfile1.cab