aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaksym Vatsyk <maksym.vatsyk@leviathansecurity.com>2023-12-05 16:31:09 +0100
committerJia Tan <jiat0218@gmail.com>2023-12-07 20:06:57 +0800
commit483bb90eec7c83e1c2bcd06287714afd62d8c17d (patch)
tree564bc54167b763a5c69604e1f7fa2db2721b9b41
parentTests: Add fuzz_decode_alone OSS-Fuzz target (diff)
downloadxz-483bb90eec7c83e1c2bcd06287714afd62d8c17d.tar.xz
Tests: Add fuzz_encode_stream ossfuzz target.
This fuzz target handles .xz stream encoding. The first byte of input is used to dynamically set the preset level in order to increase the fuzz coverage of complex critical code paths.
-rw-r--r--tests/ossfuzz/config/fuzz_encode_stream.options2
-rw-r--r--tests/ossfuzz/fuzz_encode_stream.c79
2 files changed, 81 insertions, 0 deletions
diff --git a/tests/ossfuzz/config/fuzz_encode_stream.options b/tests/ossfuzz/config/fuzz_encode_stream.options
new file mode 100644
index 00000000..9fda93fc
--- /dev/null
+++ b/tests/ossfuzz/config/fuzz_encode_stream.options
@@ -0,0 +1,2 @@
+[libfuzzer]
+max_len = 4096
diff --git a/tests/ossfuzz/fuzz_encode_stream.c b/tests/ossfuzz/fuzz_encode_stream.c
new file mode 100644
index 00000000..8ae8780e
--- /dev/null
+++ b/tests/ossfuzz/fuzz_encode_stream.c
@@ -0,0 +1,79 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file fuzz_encode_stream.c
+/// \brief Fuzz test program for liblzma lzma_stream_encoder() w/ LZMA2
+//
+// Author: Maksym Vatsyk
+//
+// Based on Lasse Collin's original fuzzer for liblzma
+//
+// This file has been put into the public domain.
+// You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include <inttypes.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include "lzma.h"
+#include "fuzz_common.h"
+
+
+extern int
+LLVMFuzzerTestOneInput(const uint8_t *inbuf, size_t inbuf_size)
+{
+ if (inbuf_size == 0) {
+ fprintf(stderr, "no input data provided\n");
+ return 0;
+ }
+
+ // set LZMA preset level based on the first input byte
+ uint32_t preset_level;
+ uint8_t decider = inbuf[0];
+ switch (decider) {
+ case 0:
+ case 1:
+ case 5:
+ preset_level = (uint32_t)decider;
+ break;
+ case 6:
+ preset_level = 0 | LZMA_PRESET_EXTREME;
+ break;
+ case 7:
+ preset_level = 3 | LZMA_PRESET_EXTREME;
+ break;
+ default:
+ return 0;
+ }
+
+ // Initialize lzma_options with the above preset level
+ lzma_options_lzma opt_lzma;
+ if (lzma_lzma_preset(&opt_lzma, preset_level)){
+ fprintf(stderr, "lzma_lzma_preset() failed\n");
+ abort();
+ }
+
+ // Initialize filter chain for lzma_stream_decoder() call
+ // Use single LZMA2 filter for encoding
+ lzma_filter filters[2];
+ filters[0].id = LZMA_FILTER_LZMA2;
+ filters[0].options = &opt_lzma;
+ filters[1].id = LZMA_VLI_UNKNOWN;
+
+ // initialize empty LZMA stream
+ lzma_stream strm = LZMA_STREAM_INIT;
+
+ // Initialize the stream encoder using the above
+ // stream, filter chain and CRC64.
+ if (lzma_stream_encoder(&strm,
+ filters, LZMA_CHECK_CRC64) != LZMA_OK) {
+ fprintf(stderr, "lzma_stream_encoder() failed\n");
+ abort();
+ }
+
+ fuzz_code(&strm, inbuf + 1, inbuf_size - 1);
+
+ // Free the allocated memory.
+ lzma_end(&strm);
+ return 0;
+}