summaryrefslogtreecommitdiffstats
path: root/ossfuzz
diff options
context:
space:
mode:
authorYann Collet <Cyan4973@users.noreply.github.com>2022-07-05 22:07:36 (GMT)
committerGitHub <noreply@github.com>2022-07-05 22:07:36 (GMT)
commit4da5c4dd30ccc584b0c6fafe948375b00b5fb2bd (patch)
treef89fd17c2b9db0ea0fc50f060cec97e9b818f90e /ossfuzz
parentf745a01cfd6363093de97e6969661cbe99e2393d (diff)
parent0ac3c74de1b6de584c361f3e9485dde35f10c756 (diff)
downloadlz4-4da5c4dd30ccc584b0c6fafe948375b00b5fb2bd.zip
lz4-4da5c4dd30ccc584b0c6fafe948375b00b5fb2bd.tar.gz
lz4-4da5c4dd30ccc584b0c6fafe948375b00b5fb2bd.tar.bz2
Merge pull request #1094 from alexmohr/add-uncompressed-api
frame-api: add function to insert uncomressed data
Diffstat (limited to 'ossfuzz')
-rw-r--r--ossfuzz/Makefile1
-rw-r--r--ossfuzz/round_trip_frame_uncompressed_fuzzer.c138
2 files changed, 139 insertions, 0 deletions
diff --git a/ossfuzz/Makefile b/ossfuzz/Makefile
index 2ec1675..deb2938 100644
--- a/ossfuzz/Makefile
+++ b/ossfuzz/Makefile
@@ -45,6 +45,7 @@ FUZZERS := \
round_trip_hc_fuzzer \
compress_frame_fuzzer \
round_trip_frame_fuzzer \
+ round_trip_frame_uncompressed_fuzzer \
decompress_frame_fuzzer
.PHONY: all
diff --git a/ossfuzz/round_trip_frame_uncompressed_fuzzer.c b/ossfuzz/round_trip_frame_uncompressed_fuzzer.c
new file mode 100644
index 0000000..e578052
--- /dev/null
+++ b/ossfuzz/round_trip_frame_uncompressed_fuzzer.c
@@ -0,0 +1,138 @@
+/**
+ * This fuzz target performs a lz4 round-trip test (compress & decompress),
+ * compares the result with the original, and calls abort() on corruption.
+ */
+
+#include <stddef.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "fuzz_data_producer.h"
+#include "fuzz_helpers.h"
+#include "lz4.h"
+#include "lz4_helpers.h"
+#include "lz4frame.h"
+#include "lz4frame_static.h"
+
+static void decompress(LZ4F_dctx *dctx, void *src, void *dst,
+ size_t dstCapacity, size_t readSize) {
+ size_t ret = 1;
+ const void *srcPtr = (const char *)src;
+ void *dstPtr = (char *)dst;
+ const void *const srcEnd = (const char *)srcPtr + readSize;
+
+ while (ret != 0) {
+ while (srcPtr < srcEnd && ret != 0) {
+ /* Any data within dst has been flushed at this stage */
+ size_t dstSize = dstCapacity;
+ size_t srcSize = (const char *)srcEnd - (const char *)srcPtr;
+ ret = LZ4F_decompress(dctx, dstPtr, &dstSize, srcPtr, &srcSize,
+ /* LZ4F_decompressOptions_t */ NULL);
+ FUZZ_ASSERT(!LZ4F_isError(ret));
+
+ /* Update input */
+ srcPtr = (const char *)srcPtr + srcSize;
+ dstPtr = (char *)dstPtr + dstSize;
+ }
+
+ FUZZ_ASSERT(srcPtr <= srcEnd);
+ }
+}
+
+static void compress_round_trip(const uint8_t* data, size_t size,
+ FUZZ_dataProducer_t *producer, LZ4F_preferences_t const prefs) {
+ size = FUZZ_dataProducer_remainingBytes(producer);
+
+ uint8_t *uncompressedData = malloc(size);
+ size_t uncompressedOffset = rand() % (size + 1);
+
+ FUZZ_dataProducer_t *uncompressedProducer =
+ FUZZ_dataProducer_create(uncompressedData, size);
+ size_t uncompressedSize =
+ FUZZ_dataProducer_remainingBytes(uncompressedProducer);
+
+ size_t const dstCapacity =
+ LZ4F_compressFrameBound(LZ4_compressBound(size), &prefs) +
+ uncompressedSize;
+ char *const dst = (char *)malloc(dstCapacity);
+ size_t rtCapacity = dstCapacity;
+ char *const rt = (char *)malloc(rtCapacity);
+
+ FUZZ_ASSERT(dst);
+ FUZZ_ASSERT(rt);
+
+ /* Compression must succeed and round trip correctly. */
+ LZ4F_compressionContext_t ctx;
+ size_t const ctxCreation = LZ4F_createCompressionContext(&ctx, LZ4F_VERSION);
+ FUZZ_ASSERT(!LZ4F_isError(ctxCreation));
+
+ size_t const headerSize = LZ4F_compressBegin(ctx, dst, dstCapacity, &prefs);
+ FUZZ_ASSERT(!LZ4F_isError(headerSize));
+ size_t compressedSize = headerSize;
+
+ /* Compress data before uncompressed offset */
+ size_t lz4Return = LZ4F_compressUpdate(ctx, dst + compressedSize, dstCapacity,
+ data, uncompressedOffset, NULL);
+ FUZZ_ASSERT(!LZ4F_isError(lz4Return));
+ compressedSize += lz4Return;
+
+ /* Add uncompressed data */
+ lz4Return = LZ4F_uncompressedUpdate(ctx, dst + compressedSize, dstCapacity,
+ uncompressedData, uncompressedSize, NULL);
+ FUZZ_ASSERT(!LZ4F_isError(lz4Return));
+ compressedSize += lz4Return;
+
+ /* Compress data after uncompressed offset */
+ lz4Return = LZ4F_compressUpdate(ctx, dst + compressedSize, dstCapacity,
+ data + uncompressedOffset,
+ size - uncompressedOffset, NULL);
+ FUZZ_ASSERT(!LZ4F_isError(lz4Return));
+ compressedSize += lz4Return;
+
+ /* Finish compression */
+ lz4Return = LZ4F_compressEnd(ctx, dst + compressedSize, dstCapacity, NULL);
+ FUZZ_ASSERT(!LZ4F_isError(lz4Return));
+ compressedSize += lz4Return;
+
+ LZ4F_decompressOptions_t opts;
+ memset(&opts, 0, sizeof(opts));
+ opts.stableDst = 1;
+ LZ4F_dctx *dctx;
+ LZ4F_createDecompressionContext(&dctx, LZ4F_VERSION);
+ FUZZ_ASSERT(dctx);
+
+ decompress(dctx, dst, rt, rtCapacity, compressedSize);
+
+ LZ4F_freeDecompressionContext(dctx);
+
+ char *const expectedData = (char *)malloc(size + uncompressedSize);
+ memcpy(expectedData, data, uncompressedOffset);
+ memcpy(expectedData + uncompressedOffset, uncompressedData, uncompressedSize);
+ memcpy(expectedData + uncompressedOffset + uncompressedSize,
+ data + uncompressedOffset, size - uncompressedOffset);
+
+ FUZZ_ASSERT_MSG(!memcmp(expectedData, rt, size), "Corruption!");
+ free(expectedData);
+
+ free(dst);
+ free(rt);
+ free(uncompressedData);
+
+ FUZZ_dataProducer_free(producer);
+ FUZZ_dataProducer_free(uncompressedProducer);
+ LZ4F_freeCompressionContext(ctx);
+}
+
+static void compress_independent_block_mode(const uint8_t* data, size_t size) {
+ FUZZ_dataProducer_t *producer = FUZZ_dataProducer_create(data, size);
+ LZ4F_preferences_t prefs = FUZZ_dataProducer_preferences(producer);
+ prefs.frameInfo.blockMode = LZ4F_blockIndependent;
+ compress_round_trip(data, size, producer, prefs);
+}
+
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+ compress_independent_block_mode(data, size);
+ return 0;
+}