Merge pull request #1590 from terrelln/frame-info-fuzz
[fuzzer] Fuzz frame info functions
This commit is contained in:
commit
af3531ee35
@ -360,8 +360,11 @@ static size_t readSkippableFrameSize(void const* src, size_t srcSize)
|
|||||||
sizeU32 = MEM_readLE32((BYTE const*)src + ZSTD_FRAMEIDSIZE);
|
sizeU32 = MEM_readLE32((BYTE const*)src + ZSTD_FRAMEIDSIZE);
|
||||||
RETURN_ERROR_IF((U32)(sizeU32 + ZSTD_SKIPPABLEHEADERSIZE) < sizeU32,
|
RETURN_ERROR_IF((U32)(sizeU32 + ZSTD_SKIPPABLEHEADERSIZE) < sizeU32,
|
||||||
frameParameter_unsupported);
|
frameParameter_unsupported);
|
||||||
|
{
|
||||||
return skippableHeaderSize + sizeU32;
|
size_t const skippableSize = skippableHeaderSize + sizeU32;
|
||||||
|
RETURN_ERROR_IF(skippableSize > srcSize, srcSize_wrong);
|
||||||
|
return skippableSize;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** ZSTD_findDecompressedSize() :
|
/** ZSTD_findDecompressedSize() :
|
||||||
@ -378,11 +381,10 @@ unsigned long long ZSTD_findDecompressedSize(const void* src, size_t srcSize)
|
|||||||
|
|
||||||
if ((magicNumber & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) {
|
if ((magicNumber & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) {
|
||||||
size_t const skippableSize = readSkippableFrameSize(src, srcSize);
|
size_t const skippableSize = readSkippableFrameSize(src, srcSize);
|
||||||
if (ZSTD_isError(skippableSize))
|
if (ZSTD_isError(skippableSize)) {
|
||||||
return skippableSize;
|
|
||||||
if (srcSize < skippableSize) {
|
|
||||||
return ZSTD_CONTENTSIZE_ERROR;
|
return ZSTD_CONTENTSIZE_ERROR;
|
||||||
}
|
}
|
||||||
|
assert(skippableSize <= srcSize);
|
||||||
|
|
||||||
src = (const BYTE *)src + skippableSize;
|
src = (const BYTE *)src + skippableSize;
|
||||||
srcSize -= skippableSize;
|
srcSize -= skippableSize;
|
||||||
@ -467,6 +469,8 @@ static ZSTD_frameSizeInfo ZSTD_findFrameSizeInfo(const void* src, size_t srcSize
|
|||||||
if ((srcSize >= ZSTD_SKIPPABLEHEADERSIZE)
|
if ((srcSize >= ZSTD_SKIPPABLEHEADERSIZE)
|
||||||
&& (MEM_readLE32(src) & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) {
|
&& (MEM_readLE32(src) & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) {
|
||||||
frameSizeInfo.compressedSize = readSkippableFrameSize(src, srcSize);
|
frameSizeInfo.compressedSize = readSkippableFrameSize(src, srcSize);
|
||||||
|
assert(ZSTD_isError(frameSizeInfo.compressedSize) ||
|
||||||
|
frameSizeInfo.compressedSize <= srcSize);
|
||||||
return frameSizeInfo;
|
return frameSizeInfo;
|
||||||
} else {
|
} else {
|
||||||
const BYTE* ip = (const BYTE*)src;
|
const BYTE* ip = (const BYTE*)src;
|
||||||
@ -529,7 +533,6 @@ size_t ZSTD_findFrameCompressedSize(const void *src, size_t srcSize)
|
|||||||
return frameSizeInfo.compressedSize;
|
return frameSizeInfo.compressedSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** ZSTD_decompressBound() :
|
/** ZSTD_decompressBound() :
|
||||||
* compatible with legacy mode
|
* compatible with legacy mode
|
||||||
* `src` must point to the start of a ZSTD frame or a skippeable frame
|
* `src` must point to the start of a ZSTD frame or a skippeable frame
|
||||||
@ -546,6 +549,7 @@ unsigned long long ZSTD_decompressBound(const void* src, size_t srcSize)
|
|||||||
unsigned long long const decompressedBound = frameSizeInfo.decompressedBound;
|
unsigned long long const decompressedBound = frameSizeInfo.decompressedBound;
|
||||||
if (ZSTD_isError(compressedSize) || decompressedBound == ZSTD_CONTENTSIZE_ERROR)
|
if (ZSTD_isError(compressedSize) || decompressedBound == ZSTD_CONTENTSIZE_ERROR)
|
||||||
return ZSTD_CONTENTSIZE_ERROR;
|
return ZSTD_CONTENTSIZE_ERROR;
|
||||||
|
assert(srcSize >= compressedSize);
|
||||||
src = (const BYTE*)src + compressedSize;
|
src = (const BYTE*)src + compressedSize;
|
||||||
srcSize -= compressedSize;
|
srcSize -= compressedSize;
|
||||||
bound += decompressedBound;
|
bound += decompressedBound;
|
||||||
@ -738,9 +742,8 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
|
|||||||
(unsigned)magicNumber, ZSTD_MAGICNUMBER);
|
(unsigned)magicNumber, ZSTD_MAGICNUMBER);
|
||||||
if ((magicNumber & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) {
|
if ((magicNumber & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) {
|
||||||
size_t const skippableSize = readSkippableFrameSize(src, srcSize);
|
size_t const skippableSize = readSkippableFrameSize(src, srcSize);
|
||||||
if (ZSTD_isError(skippableSize))
|
FORWARD_IF_ERROR(skippableSize);
|
||||||
return skippableSize;
|
assert(skippableSize <= srcSize);
|
||||||
RETURN_ERROR_IF(srcSize < skippableSize, srcSize_wrong);
|
|
||||||
|
|
||||||
src = (const BYTE *)src + skippableSize;
|
src = (const BYTE *)src + skippableSize;
|
||||||
srcSize -= skippableSize;
|
srcSize -= skippableSize;
|
||||||
|
@ -238,6 +238,10 @@ MEM_STATIC ZSTD_frameSizeInfo ZSTD_findFrameSizeInfoLegacy(const void *src, size
|
|||||||
frameSizeInfo.decompressedBound = ZSTD_CONTENTSIZE_ERROR;
|
frameSizeInfo.decompressedBound = ZSTD_CONTENTSIZE_ERROR;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (!ZSTD_isError(frameSizeInfo.compressedSize) && frameSizeInfo.compressedSize > srcSize) {
|
||||||
|
frameSizeInfo.compressedSize = ERROR(srcSize_wrong);
|
||||||
|
frameSizeInfo.decompressedBound = ZSTD_CONTENTSIZE_ERROR;
|
||||||
|
}
|
||||||
return frameSizeInfo;
|
return frameSizeInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,7 +69,8 @@ FUZZ_TARGETS := \
|
|||||||
stream_decompress \
|
stream_decompress \
|
||||||
block_decompress \
|
block_decompress \
|
||||||
dictionary_round_trip \
|
dictionary_round_trip \
|
||||||
dictionary_decompress
|
dictionary_decompress \
|
||||||
|
zstd_frame_info
|
||||||
|
|
||||||
all: $(FUZZ_TARGETS)
|
all: $(FUZZ_TARGETS)
|
||||||
|
|
||||||
@ -100,6 +101,9 @@ dictionary_round_trip: $(FUZZ_HEADERS) $(FUZZ_OBJ) dictionary_round_trip.o
|
|||||||
dictionary_decompress: $(FUZZ_HEADERS) $(FUZZ_OBJ) dictionary_decompress.o
|
dictionary_decompress: $(FUZZ_HEADERS) $(FUZZ_OBJ) dictionary_decompress.o
|
||||||
$(CXX) $(FUZZ_TARGET_FLAGS) $(FUZZ_OBJ) dictionary_decompress.o $(LIB_FUZZING_ENGINE) -o $@
|
$(CXX) $(FUZZ_TARGET_FLAGS) $(FUZZ_OBJ) dictionary_decompress.o $(LIB_FUZZING_ENGINE) -o $@
|
||||||
|
|
||||||
|
zstd_frame_info: $(FUZZ_HEADERS) $(FUZZ_OBJ) zstd_frame_info.o
|
||||||
|
$(CXX) $(FUZZ_TARGET_FLAGS) $(FUZZ_OBJ) zstd_frame_info.o $(LIB_FUZZING_ENGINE) -o $@
|
||||||
|
|
||||||
libregression.a: $(FUZZ_HEADERS) $(PRGDIR)/util.h $(PRGDIR)/util.c regression_driver.o
|
libregression.a: $(FUZZ_HEADERS) $(PRGDIR)/util.h $(PRGDIR)/util.c regression_driver.o
|
||||||
$(AR) $(FUZZ_ARFLAGS) $@ regression_driver.o
|
$(AR) $(FUZZ_ARFLAGS) $@ regression_driver.o
|
||||||
|
|
||||||
@ -122,6 +126,9 @@ corpora/%: corpora/%_seed_corpus.zip
|
|||||||
.PHONY: corpora
|
.PHONY: corpora
|
||||||
corpora: $(patsubst %,corpora/%,$(FUZZ_TARGETS))
|
corpora: $(patsubst %,corpora/%,$(FUZZ_TARGETS))
|
||||||
|
|
||||||
|
.PHONY: seedcorpora
|
||||||
|
seedcorpora: $(patsubst %,corpora/%_seed_corpus.zip,$(FUZZ_TARGETS))
|
||||||
|
|
||||||
regressiontest: corpora
|
regressiontest: corpora
|
||||||
CC="$(CC)" CXX="$(CXX)" CFLAGS="$(CFLAGS)" CXXFLAGS="$(CXXFLAGS)" LDFLAGS="$(LDFLAGS)" $(PYTHON) ./fuzz.py build all
|
CC="$(CC)" CXX="$(CXX)" CFLAGS="$(CFLAGS)" CXXFLAGS="$(CXXFLAGS)" LDFLAGS="$(LDFLAGS)" $(PYTHON) ./fuzz.py build all
|
||||||
$(PYTHON) ./fuzz.py regression all
|
$(PYTHON) ./fuzz.py regression all
|
||||||
|
@ -36,6 +36,7 @@ TARGETS = [
|
|||||||
'block_decompress',
|
'block_decompress',
|
||||||
'dictionary_round_trip',
|
'dictionary_round_trip',
|
||||||
'dictionary_decompress',
|
'dictionary_decompress',
|
||||||
|
'zstd_frame_info',
|
||||||
]
|
]
|
||||||
ALL_TARGETS = TARGETS + ['all']
|
ALL_TARGETS = TARGETS + ['all']
|
||||||
FUZZ_RNG_SEED_SIZE = 4
|
FUZZ_RNG_SEED_SIZE = 4
|
||||||
|
43
tests/fuzz/zstd_frame_info.c
Normal file
43
tests/fuzz/zstd_frame_info.c
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2016-present, Facebook, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This source code is licensed under both the BSD-style license (found in the
|
||||||
|
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
|
||||||
|
* in the COPYING file in the root directory of this source tree).
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This fuzz target fuzzes all of the helper functions that consume compressed
|
||||||
|
* input.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "fuzz_helpers.h"
|
||||||
|
#include "zstd_helpers.h"
|
||||||
|
|
||||||
|
int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size)
|
||||||
|
{
|
||||||
|
ZSTD_frameHeader zfh;
|
||||||
|
/* Consume the seed to be compatible with the corpora of other decompression
|
||||||
|
* fuzzers.
|
||||||
|
*/
|
||||||
|
FUZZ_seed(&src, &size);
|
||||||
|
/* You can fuzz any helper functions here that are fast, and take zstd
|
||||||
|
* compressed data as input. E.g. don't expect the input to be a dictionary,
|
||||||
|
* so don't fuzz ZSTD_getDictID_fromDict().
|
||||||
|
*/
|
||||||
|
ZSTD_getFrameContentSize(src, size);
|
||||||
|
ZSTD_getDecompressedSize(src, size);
|
||||||
|
ZSTD_findFrameCompressedSize(src, size);
|
||||||
|
ZSTD_getDictID_fromFrame(src, size);
|
||||||
|
ZSTD_findDecompressedSize(src, size);
|
||||||
|
ZSTD_decompressBound(src, size);
|
||||||
|
ZSTD_frameHeaderSize(src, size);
|
||||||
|
ZSTD_isFrame(src, size);
|
||||||
|
ZSTD_getFrameHeader(&zfh, src, size);
|
||||||
|
ZSTD_getFrameHeader_advanced(&zfh, src, size, ZSTD_f_zstd1);
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user