]> git.ipfire.org Git - thirdparty/zstd.git/commitdiff
[fuzz] Fix stream_decompress timeouts 2285/head
authorNick Terrell <terrelln@fb.com>
Wed, 26 Aug 2020 00:10:04 +0000 (17:10 -0700)
committerNick Terrell <terrelln@fb.com>
Wed, 26 Aug 2020 00:13:09 +0000 (17:13 -0700)
tests/fuzz/fuzz_data_producer.c
tests/fuzz/fuzz_data_producer.h
tests/fuzz/stream_decompress.c

index 6518af30900146782af0dcc575219d5377607305..f2d5a1b51584ba7c45ed8d4dd38fb899a58dacbb 100644 (file)
@@ -66,6 +66,10 @@ size_t FUZZ_dataProducer_remainingBytes(FUZZ_dataProducer_t *producer){
     return producer->size;
 }
 
+int FUZZ_dataProducer_empty(FUZZ_dataProducer_t *producer) {
+    return producer->size == 0;
+}
+
 size_t FUZZ_dataProducer_contract(FUZZ_dataProducer_t *producer, size_t newSize)
 {
     newSize = newSize > producer->size ? producer->size : newSize;
index 41e0b52d5d11c20f9145a76294d55046bd99021c..25cc937fcce07e3648cc727b1cff40690e967068 100644 (file)
@@ -49,6 +49,9 @@ int32_t FUZZ_dataProducer_int32Range(FUZZ_dataProducer_t *producer,
 /* Returns the size of the remaining bytes of data in the producer */
 size_t FUZZ_dataProducer_remainingBytes(FUZZ_dataProducer_t *producer);
 
+/* Returns true if the data producer is out of bytes */
+int FUZZ_dataProducer_empty(FUZZ_dataProducer_t *producer);
+
 /* Restricts the producer to only the last newSize bytes of data.
 If newSize > current data size, nothing happens. Returns the number of bytes
 the producer won't use anymore, after contracting. */
index 25901b1eb37c9eb9553e0d62b31be30d1c8b2fd2..5d2bb2aaf41c2965b8ee52ea00c2911bc3ec4a91 100644 (file)
 #include "zstd.h"
 #include "fuzz_data_producer.h"
 
-static size_t const kBufSize = ZSTD_BLOCKSIZE_MAX;
-
 static ZSTD_DStream *dstream = NULL;
-static void* buf = NULL;
 uint32_t seed;
 
-static ZSTD_outBuffer makeOutBuffer(FUZZ_dataProducer_t *producer, uint32_t min)
+static ZSTD_outBuffer makeOutBuffer(FUZZ_dataProducer_t *producer, void* buf, size_t bufSize)
 {
   ZSTD_outBuffer buffer = { buf, 0, 0 };
 
-  buffer.size = (FUZZ_dataProducer_uint32Range(producer, min, kBufSize));
-  FUZZ_ASSERT(buffer.size <= kBufSize);
+  if (FUZZ_dataProducer_empty(producer)) {
+    buffer.size = bufSize;
+  } else {
+    buffer.size = (FUZZ_dataProducer_uint32Range(producer, 0, bufSize));
+  }
+  FUZZ_ASSERT(buffer.size <= bufSize);
 
   if (buffer.size == 0) {
     buffer.dst = NULL;
@@ -43,13 +44,16 @@ static ZSTD_outBuffer makeOutBuffer(FUZZ_dataProducer_t *producer, uint32_t min)
 }
 
 static ZSTD_inBuffer makeInBuffer(const uint8_t **src, size_t *size,
-                                  FUZZ_dataProducer_t *producer,
-                                  uint32_t min)
+                                  FUZZ_dataProducer_t *producer)
 {
   ZSTD_inBuffer buffer = { *src, 0, 0 };
 
   FUZZ_ASSERT(*size > 0);
-  buffer.size = (FUZZ_dataProducer_uint32Range(producer, min, *size));
+  if (FUZZ_dataProducer_empty(producer)) {
+    buffer.size = *size;
+  } else {
+    buffer.size = (FUZZ_dataProducer_uint32Range(producer, 0, *size));
+  }
   FUZZ_ASSERT(buffer.size <= *size);
   *src += buffer.size;
   *size -= buffer.size;
@@ -66,18 +70,15 @@ int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size)
     /* Give a random portion of src data to the producer, to use for
     parameter generation. The rest will be used for (de)compression */
     FUZZ_dataProducer_t *producer = FUZZ_dataProducer_create(src, size);
-    /* Guarantee forward progress by refusing to generate 2 zero sized
-     * buffers in a row. */
-    int prevInWasZero = 0;
-    int prevOutWasZero = 0;
     int stableOutBuffer;
     ZSTD_outBuffer out;
+    void* buf;
+    size_t bufSize;
     size = FUZZ_dataProducer_reserveDataPrefix(producer);
+    bufSize = MAX(10 * size, ZSTD_BLOCKSIZE_MAX);
 
     /* Allocate all buffers and contexts if not already allocated */
-    if (!buf) {
-        buf = FUZZ_malloc(kBufSize);
-    }
+    buf = FUZZ_malloc(bufSize);
 
     if (!dstream) {
         dstream = ZSTD_createDStream();
@@ -90,18 +91,19 @@ int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size)
     if (stableOutBuffer) {
       FUZZ_ZASSERT(ZSTD_DCtx_setParameter(dstream, ZSTD_d_stableOutBuffer, 1));
       out.dst = buf;
-      out.size = kBufSize;
+      out.size = bufSize;
       out.pos = 0;
+    } else {
+      out = makeOutBuffer(producer, buf, bufSize);
     }
 
     while (size > 0) {
-        ZSTD_inBuffer in = makeInBuffer(&src, &size, producer, prevInWasZero ? 1 : 0);
-        prevInWasZero = in.size == 0;
+        ZSTD_inBuffer in = makeInBuffer(&src, &size, producer);
         while (in.pos != in.size) {
-            if (!stableOutBuffer || prevOutWasZero || FUZZ_dataProducer_uint32Range(producer, 0, 100) == 55) {
-              out = makeOutBuffer(producer, prevOutWasZero ? 1 : 0);
+            if (out.pos == out.size) {
+                if (stableOutBuffer) goto error;
+                out = makeOutBuffer(producer, buf, bufSize);
             }
-            prevOutWasZero = out.size == 0;
             size_t const rc = ZSTD_decompressStream(dstream, &out, &in);
             if (ZSTD_isError(rc)) goto error;
         }
@@ -112,5 +114,6 @@ error:
     ZSTD_freeDStream(dstream); dstream = NULL;
 #endif
     FUZZ_dataProducer_free(producer);
+    free(buf);
     return 0;
 }