]> git.ipfire.org Git - thirdparty/zstd.git/commitdiff
Check that `dest` is valid for decompression (#3555)
authordaniellerozenblit <48103643+daniellerozenblit@users.noreply.github.com>
Sat, 1 Apr 2023 06:00:55 +0000 (02:00 -0400)
committerGitHub <noreply@github.com>
Sat, 1 Apr 2023 06:00:55 +0000 (23:00 -0700)
* add check for valid dest buffer and fuzz on random dest ptr when malloc 0

* add uptrval to linux-kernel

* remove bin files

* get rid of uptrval

* restrict max pointer value check to platforms where sizeof(size_t) == sizeof(void*)

lib/decompress/zstd_decompress_block.c
tests/fuzz/block_decompress.c
tests/fuzz/fuzz_data_producer.c
tests/fuzz/fuzz_data_producer.h
tests/fuzz/fuzz_helpers.c
tests/fuzz/fuzz_helpers.h

index f018271765d96a4d79634a16dc281db362ef23fe..09896a931e255483d1257eec1f2347f4b7742447 100644 (file)
@@ -2112,7 +2112,9 @@ ZSTD_decompressBlock_internal(ZSTD_DCtx* dctx,
         ip += seqHSize;
         srcSize -= seqHSize;
 
-        RETURN_ERROR_IF(dst == NULL && nbSeq > 0, dstSize_tooSmall, "NULL not handled");
+        RETURN_ERROR_IF((dst == NULL || dstCapacity == 0) && nbSeq > 0, dstSize_tooSmall, "NULL not handled");
+        RETURN_ERROR_IF(MEM_64bits() && sizeof(size_t) == sizeof(void*) && (size_t)(-1) - (size_t)dst < (size_t)(1 << 20), dstSize_tooSmall,
+                "invalid dst");
 
         /* If we could potentially have long offsets, or we might want to use the prefetch decoder,
          * compute information about the share of long offsets, and the maximum nbAdditionalBits.
index e4767b3f5091b67d0d67e3ec2689a9b3ee84d0f7..9cc6005c3b200d9c453b9501d3d3ee29f1600809 100644 (file)
@@ -13,6 +13,7 @@
  * decompression function to ensure the decompressor never crashes.
  */
 
+#include "fuzz_data_producer.h"
 #define ZSTD_STATIC_LINKING_ONLY
 
 #include <stddef.h>
@@ -28,11 +29,12 @@ static size_t bufSize = 0;
 int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size)
 {
     size_t const neededBufSize = ZSTD_BLOCKSIZE_MAX;
+    FUZZ_dataProducer_t *producer = FUZZ_dataProducer_create(src, size);
 
     /* Allocate all buffers and contexts if not already allocated */
     if (neededBufSize > bufSize) {
         free(rBuf);
-        rBuf = FUZZ_malloc(neededBufSize);
+        rBuf = FUZZ_malloc_rand(neededBufSize, producer);
         bufSize = neededBufSize;
     }
     if (!dctx) {
@@ -42,6 +44,8 @@ int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size)
     ZSTD_decompressBegin(dctx);
     ZSTD_decompressBlock(dctx, rBuf, neededBufSize, src, size);
 
+    FUZZ_dataProducer_free(producer);
+
 #ifndef STATEFUL_FUZZING
     ZSTD_freeDCtx(dctx); dctx = NULL;
 #endif
index a93e8ba950b590f522ce4c6f0807e3e9faa4e4fb..bf846b68f72b7effd8f16879fe20d6cda7171716 100644 (file)
@@ -8,6 +8,7 @@
  * You may select, at your option, one of the above-listed licenses.
  */
 
+#include "fuzz_helpers.h"
 #include "fuzz_data_producer.h"
 
 struct FUZZ_dataProducer_s{
index 8ca501f9b097a63f47aa69103a2649b0d161d055..f488ceb991b5386d614188c7c600085a906d2e2e 100644 (file)
@@ -24,7 +24,6 @@
 #include <stdio.h>
 #include <stdlib.h>
 
-#include "fuzz_helpers.h"
 
 /* Struct used for maintaining the state of the data */
 typedef struct FUZZ_dataProducer_s FUZZ_dataProducer_t;
index 1b6ad9736cb02c744f3e19fdc257f933aa11dc58..f47ff2eb4ff39c52a8242fff9fadf42ab3d04293 100644 (file)
@@ -23,6 +23,22 @@ void* FUZZ_malloc(size_t size)
     return NULL;
 }
 
+void* FUZZ_malloc_rand(size_t size, FUZZ_dataProducer_t *producer)
+{
+    if (size > 0) {
+        void* const mem = malloc(size);
+        FUZZ_ASSERT(mem);
+        return mem;
+    } else {
+        uintptr_t ptr = 0;
+        /* Add +- 1M 50% of the time */
+        if (FUZZ_dataProducer_uint32Range(producer, 0, 1))
+            FUZZ_dataProducer_int32Range(producer, -1000000, 1000000);
+        return (void*)ptr;
+    }
+
+}
+
 int FUZZ_memcmp(void const* lhs, void const* rhs, size_t size)
 {
     if (size == 0) {
index aaf4c1df45e463ed3d77e0ebb63ff84b1557640a..f21ec47516e721e01b954a0bb1fb871456d1d6ab 100644 (file)
@@ -19,6 +19,7 @@
 #include "fuzz.h"
 #include "xxhash.h"
 #include "zstd.h"
+#include "fuzz_data_producer.h"
 #include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -62,6 +63,12 @@ extern "C" {
  */
 void* FUZZ_malloc(size_t size);
 
+/**
+ * malloc except returns random pointer for zero sized data and FUZZ_ASSERT
+ * that malloc doesn't fail.
+ */
+void* FUZZ_malloc_rand(size_t size,  FUZZ_dataProducer_t *producer);
+
 /**
  * memcmp but accepts NULL.
  */