Skip to content

Commit

Permalink
Check that dest is valid for decompression (#3555)
Browse files Browse the repository at this point in the history
* 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*)
  • Loading branch information
daniellerozenblit authored Apr 1, 2023
1 parent 7b828aa commit fcaf06d
Show file tree
Hide file tree
Showing 6 changed files with 32 additions and 3 deletions.
4 changes: 3 additions & 1 deletion lib/decompress/zstd_decompress_block.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
6 changes: 5 additions & 1 deletion tests/fuzz/block_decompress.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand All @@ -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) {
Expand All @@ -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
Expand Down
1 change: 1 addition & 0 deletions tests/fuzz/fuzz_data_producer.c
Original file line number Diff line number Diff line change
Expand Up @@ -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{
Expand Down
1 change: 0 additions & 1 deletion tests/fuzz/fuzz_data_producer.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
16 changes: 16 additions & 0 deletions tests/fuzz/fuzz_helpers.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
7 changes: 7 additions & 0 deletions tests/fuzz/fuzz_helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -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.
*/
Expand Down

0 comments on commit fcaf06d

Please sign in to comment.