extlz4 0.2.4.2 → 0.3.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/HISTORY.ja.md +25 -0
- data/README.md +49 -41
- data/bin/extlz4 +1 -1
- data/contrib/lz4/INSTALL +1 -0
- data/contrib/lz4/Makefile.inc +87 -0
- data/contrib/lz4/NEWS +89 -0
- data/contrib/lz4/README.md +42 -36
- data/contrib/lz4/build/README.md +55 -0
- data/contrib/lz4/build/VS2010/datagen/datagen.vcxproj +169 -0
- data/contrib/lz4/build/VS2010/frametest/frametest.vcxproj +176 -0
- data/contrib/lz4/build/VS2010/fullbench-dll/fullbench-dll.vcxproj +180 -0
- data/contrib/lz4/build/VS2010/fullbench/fullbench.vcxproj +176 -0
- data/contrib/lz4/build/VS2010/fuzzer/fuzzer.vcxproj +173 -0
- data/contrib/lz4/build/VS2010/liblz4-dll/liblz4-dll.rc +51 -0
- data/contrib/lz4/build/VS2010/liblz4-dll/liblz4-dll.vcxproj +179 -0
- data/contrib/lz4/build/VS2010/liblz4/liblz4.vcxproj +175 -0
- data/contrib/lz4/build/VS2010/lz4.sln +98 -0
- data/contrib/lz4/build/VS2010/lz4/lz4.rc +51 -0
- data/contrib/lz4/build/VS2010/lz4/lz4.vcxproj +189 -0
- data/contrib/lz4/build/VS2017/datagen/datagen.vcxproj +173 -0
- data/contrib/lz4/build/VS2017/frametest/frametest.vcxproj +180 -0
- data/contrib/lz4/build/VS2017/fullbench-dll/fullbench-dll.vcxproj +184 -0
- data/contrib/lz4/build/VS2017/fullbench/fullbench.vcxproj +180 -0
- data/contrib/lz4/build/VS2017/fuzzer/fuzzer.vcxproj +177 -0
- data/contrib/lz4/build/VS2017/liblz4-dll/liblz4-dll.rc +51 -0
- data/contrib/lz4/build/VS2017/liblz4-dll/liblz4-dll.vcxproj +183 -0
- data/contrib/lz4/build/VS2017/liblz4/liblz4.vcxproj +179 -0
- data/contrib/lz4/build/VS2017/lz4.sln +103 -0
- data/contrib/lz4/build/VS2017/lz4/lz4.rc +51 -0
- data/contrib/lz4/build/VS2017/lz4/lz4.vcxproj +164 -0
- data/contrib/lz4/build/cmake/CMakeLists.txt +235 -0
- data/contrib/lz4/lib/README.md +98 -34
- data/contrib/lz4/lib/liblz4-dll.rc.in +35 -0
- data/contrib/lz4/lib/lz4.c +1698 -681
- data/contrib/lz4/lib/lz4.h +546 -235
- data/contrib/lz4/lib/lz4frame.c +608 -378
- data/contrib/lz4/lib/lz4frame.h +315 -83
- data/contrib/lz4/lib/lz4frame_static.h +4 -100
- data/contrib/lz4/lib/lz4hc.c +1090 -282
- data/contrib/lz4/lib/lz4hc.h +276 -141
- data/contrib/lz4/lib/xxhash.c +371 -235
- data/contrib/lz4/lib/xxhash.h +128 -93
- data/contrib/lz4/ossfuzz/Makefile +78 -0
- data/contrib/lz4/ossfuzz/compress_frame_fuzzer.c +48 -0
- data/contrib/lz4/ossfuzz/compress_fuzzer.c +58 -0
- data/contrib/lz4/ossfuzz/compress_hc_fuzzer.c +64 -0
- data/contrib/lz4/ossfuzz/decompress_frame_fuzzer.c +75 -0
- data/contrib/lz4/ossfuzz/decompress_fuzzer.c +62 -0
- data/contrib/lz4/ossfuzz/fuzz.h +48 -0
- data/contrib/lz4/ossfuzz/fuzz_data_producer.c +77 -0
- data/contrib/lz4/ossfuzz/fuzz_data_producer.h +36 -0
- data/contrib/lz4/ossfuzz/fuzz_helpers.h +94 -0
- data/contrib/lz4/ossfuzz/lz4_helpers.c +51 -0
- data/contrib/lz4/ossfuzz/lz4_helpers.h +13 -0
- data/contrib/lz4/ossfuzz/ossfuzz.sh +23 -0
- data/contrib/lz4/ossfuzz/round_trip_frame_fuzzer.c +43 -0
- data/contrib/lz4/ossfuzz/round_trip_fuzzer.c +57 -0
- data/contrib/lz4/ossfuzz/round_trip_hc_fuzzer.c +44 -0
- data/contrib/lz4/ossfuzz/round_trip_stream_fuzzer.c +302 -0
- data/contrib/lz4/ossfuzz/standaloneengine.c +74 -0
- data/contrib/lz4/ossfuzz/travisoss.sh +26 -0
- data/contrib/lz4/tmp +0 -0
- data/contrib/lz4/tmpsparse +0 -0
- data/ext/blockapi.c +5 -5
- data/ext/extlz4.c +2 -0
- data/ext/extlz4.h +5 -0
- data/ext/frameapi.c +1 -1
- data/ext/hashargs.c +2 -2
- data/ext/hashargs.h +1 -1
- data/ext/lz4_amalgam.c +0 -23
- data/gemstub.rb +5 -16
- data/lib/extlz4.rb +51 -3
- data/lib/extlz4/oldstream.rb +1 -1
- data/test/common.rb +2 -2
- metadata +73 -16
- data/contrib/lz4/circle.yml +0 -39
- data/contrib/lz4/lib/lz4opt.h +0 -366
- data/lib/extlz4/version.rb +0 -3
@@ -0,0 +1,51 @@
|
|
1
|
+
#include "fuzz_helpers.h"
|
2
|
+
#include "lz4_helpers.h"
|
3
|
+
#include "lz4hc.h"
|
4
|
+
|
5
|
+
LZ4F_frameInfo_t FUZZ_randomFrameInfo(uint32_t* seed)
|
6
|
+
{
|
7
|
+
LZ4F_frameInfo_t info = LZ4F_INIT_FRAMEINFO;
|
8
|
+
info.blockSizeID = FUZZ_rand32(seed, LZ4F_max64KB - 1, LZ4F_max4MB);
|
9
|
+
if (info.blockSizeID < LZ4F_max64KB) {
|
10
|
+
info.blockSizeID = LZ4F_default;
|
11
|
+
}
|
12
|
+
info.blockMode = FUZZ_rand32(seed, LZ4F_blockLinked, LZ4F_blockIndependent);
|
13
|
+
info.contentChecksumFlag = FUZZ_rand32(seed, LZ4F_noContentChecksum,
|
14
|
+
LZ4F_contentChecksumEnabled);
|
15
|
+
info.blockChecksumFlag = FUZZ_rand32(seed, LZ4F_noBlockChecksum,
|
16
|
+
LZ4F_blockChecksumEnabled);
|
17
|
+
return info;
|
18
|
+
}
|
19
|
+
|
20
|
+
LZ4F_preferences_t FUZZ_randomPreferences(uint32_t* seed)
|
21
|
+
{
|
22
|
+
LZ4F_preferences_t prefs = LZ4F_INIT_PREFERENCES;
|
23
|
+
prefs.frameInfo = FUZZ_randomFrameInfo(seed);
|
24
|
+
prefs.compressionLevel = FUZZ_rand32(seed, 0, LZ4HC_CLEVEL_MAX + 3) - 3;
|
25
|
+
prefs.autoFlush = FUZZ_rand32(seed, 0, 1);
|
26
|
+
prefs.favorDecSpeed = FUZZ_rand32(seed, 0, 1);
|
27
|
+
return prefs;
|
28
|
+
}
|
29
|
+
|
30
|
+
size_t FUZZ_decompressFrame(void* dst, const size_t dstCapacity,
|
31
|
+
const void* src, const size_t srcSize)
|
32
|
+
{
|
33
|
+
LZ4F_decompressOptions_t opts;
|
34
|
+
memset(&opts, 0, sizeof(opts));
|
35
|
+
opts.stableDst = 1;
|
36
|
+
LZ4F_dctx* dctx;
|
37
|
+
LZ4F_createDecompressionContext(&dctx, LZ4F_VERSION);
|
38
|
+
FUZZ_ASSERT(dctx);
|
39
|
+
|
40
|
+
size_t dstSize = dstCapacity;
|
41
|
+
size_t srcConsumed = srcSize;
|
42
|
+
size_t const rc =
|
43
|
+
LZ4F_decompress(dctx, dst, &dstSize, src, &srcConsumed, &opts);
|
44
|
+
FUZZ_ASSERT(!LZ4F_isError(rc));
|
45
|
+
FUZZ_ASSERT(rc == 0);
|
46
|
+
FUZZ_ASSERT(srcConsumed == srcSize);
|
47
|
+
|
48
|
+
LZ4F_freeDecompressionContext(dctx);
|
49
|
+
|
50
|
+
return dstSize;
|
51
|
+
}
|
@@ -0,0 +1,13 @@
|
|
1
|
+
#ifndef LZ4_HELPERS
|
2
|
+
#define LZ4_HELPERS
|
3
|
+
|
4
|
+
#include "lz4frame.h"
|
5
|
+
|
6
|
+
LZ4F_frameInfo_t FUZZ_randomFrameInfo(uint32_t* seed);
|
7
|
+
|
8
|
+
LZ4F_preferences_t FUZZ_randomPreferences(uint32_t* seed);
|
9
|
+
|
10
|
+
size_t FUZZ_decompressFrame(void* dst, const size_t dstCapacity,
|
11
|
+
const void* src, const size_t srcSize);
|
12
|
+
|
13
|
+
#endif /* LZ4_HELPERS */
|
@@ -0,0 +1,23 @@
|
|
1
|
+
#!/bin/bash -eu
|
2
|
+
|
3
|
+
# This script is called by the oss-fuzz main project when compiling the fuzz
|
4
|
+
# targets. This script is regression tested by travisoss.sh.
|
5
|
+
|
6
|
+
# Save off the current folder as the build root.
|
7
|
+
export BUILD_ROOT=$PWD
|
8
|
+
|
9
|
+
echo "CC: $CC"
|
10
|
+
echo "CXX: $CXX"
|
11
|
+
echo "LIB_FUZZING_ENGINE: $LIB_FUZZING_ENGINE"
|
12
|
+
echo "CFLAGS: $CFLAGS"
|
13
|
+
echo "CXXFLAGS: $CXXFLAGS"
|
14
|
+
echo "OUT: $OUT"
|
15
|
+
|
16
|
+
export MAKEFLAGS+="-j$(nproc)"
|
17
|
+
|
18
|
+
pushd ossfuzz
|
19
|
+
make V=1 all
|
20
|
+
popd
|
21
|
+
|
22
|
+
# Copy the fuzzers to the target directory.
|
23
|
+
cp -v ossfuzz/*_fuzzer $OUT/
|
@@ -0,0 +1,43 @@
|
|
1
|
+
/**
|
2
|
+
* This fuzz target performs a lz4 round-trip test (compress & decompress),
|
3
|
+
* compares the result with the original, and calls abort() on corruption.
|
4
|
+
*/
|
5
|
+
|
6
|
+
#include <stddef.h>
|
7
|
+
#include <stdint.h>
|
8
|
+
#include <stdlib.h>
|
9
|
+
#include <string.h>
|
10
|
+
|
11
|
+
#include "fuzz_helpers.h"
|
12
|
+
#include "lz4.h"
|
13
|
+
#include "lz4frame.h"
|
14
|
+
#include "lz4_helpers.h"
|
15
|
+
#include "fuzz_data_producer.h"
|
16
|
+
|
17
|
+
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
|
18
|
+
{
|
19
|
+
FUZZ_dataProducer_t* producer = FUZZ_dataProducer_create(data, size);
|
20
|
+
LZ4F_preferences_t const prefs = FUZZ_dataProducer_preferences(producer);
|
21
|
+
size = FUZZ_dataProducer_remainingBytes(producer);
|
22
|
+
|
23
|
+
size_t const dstCapacity = LZ4F_compressFrameBound(LZ4_compressBound(size), &prefs);
|
24
|
+
char* const dst = (char*)malloc(dstCapacity);
|
25
|
+
char* const rt = (char*)malloc(FUZZ_dataProducer_remainingBytes(producer));
|
26
|
+
|
27
|
+
FUZZ_ASSERT(dst);
|
28
|
+
FUZZ_ASSERT(rt);
|
29
|
+
|
30
|
+
/* Compression must succeed and round trip correctly. */
|
31
|
+
size_t const dstSize =
|
32
|
+
LZ4F_compressFrame(dst, dstCapacity, data, size, &prefs);
|
33
|
+
FUZZ_ASSERT(!LZ4F_isError(dstSize));
|
34
|
+
size_t const rtSize = FUZZ_decompressFrame(rt, size, dst, dstSize);
|
35
|
+
FUZZ_ASSERT_MSG(rtSize == size, "Incorrect regenerated size");
|
36
|
+
FUZZ_ASSERT_MSG(!memcmp(data, rt, size), "Corruption!");
|
37
|
+
|
38
|
+
free(dst);
|
39
|
+
free(rt);
|
40
|
+
FUZZ_dataProducer_free(producer);
|
41
|
+
|
42
|
+
return 0;
|
43
|
+
}
|
@@ -0,0 +1,57 @@
|
|
1
|
+
/**
|
2
|
+
* This fuzz target performs a lz4 round-trip test (compress & decompress),
|
3
|
+
* compares the result with the original, and calls abort() on corruption.
|
4
|
+
*/
|
5
|
+
|
6
|
+
#include <stddef.h>
|
7
|
+
#include <stdint.h>
|
8
|
+
#include <stdlib.h>
|
9
|
+
#include <string.h>
|
10
|
+
|
11
|
+
#include "fuzz_helpers.h"
|
12
|
+
#include "lz4.h"
|
13
|
+
#include "fuzz_data_producer.h"
|
14
|
+
|
15
|
+
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
|
16
|
+
{
|
17
|
+
FUZZ_dataProducer_t *producer = FUZZ_dataProducer_create(data, size);
|
18
|
+
size_t const partialCapacitySeed = FUZZ_dataProducer_retrieve32(producer);
|
19
|
+
size = FUZZ_dataProducer_remainingBytes(producer);
|
20
|
+
|
21
|
+
size_t const partialCapacity = FUZZ_getRange_from_uint32(partialCapacitySeed, 0, size);
|
22
|
+
size_t const dstCapacity = LZ4_compressBound(size);
|
23
|
+
|
24
|
+
char* const dst = (char*)malloc(dstCapacity);
|
25
|
+
char* const rt = (char*)malloc(size);
|
26
|
+
|
27
|
+
FUZZ_ASSERT(dst);
|
28
|
+
FUZZ_ASSERT(rt);
|
29
|
+
|
30
|
+
/* Compression must succeed and round trip correctly. */
|
31
|
+
int const dstSize = LZ4_compress_default((const char*)data, dst,
|
32
|
+
size, dstCapacity);
|
33
|
+
FUZZ_ASSERT(dstSize > 0);
|
34
|
+
|
35
|
+
int const rtSize = LZ4_decompress_safe(dst, rt, dstSize, size);
|
36
|
+
FUZZ_ASSERT_MSG(rtSize == size, "Incorrect size");
|
37
|
+
FUZZ_ASSERT_MSG(!memcmp(data, rt, size), "Corruption!");
|
38
|
+
|
39
|
+
/* Partial decompression must succeed. */
|
40
|
+
{
|
41
|
+
char* const partial = (char*)malloc(partialCapacity);
|
42
|
+
FUZZ_ASSERT(partial);
|
43
|
+
int const partialSize = LZ4_decompress_safe_partial(
|
44
|
+
dst, partial, dstSize, partialCapacity, partialCapacity);
|
45
|
+
FUZZ_ASSERT(partialSize >= 0);
|
46
|
+
FUZZ_ASSERT_MSG(partialSize == partialCapacity, "Incorrect size");
|
47
|
+
FUZZ_ASSERT_MSG(!memcmp(data, partial, partialSize), "Corruption!");
|
48
|
+
free(partial);
|
49
|
+
}
|
50
|
+
|
51
|
+
|
52
|
+
free(dst);
|
53
|
+
free(rt);
|
54
|
+
FUZZ_dataProducer_free(producer);
|
55
|
+
|
56
|
+
return 0;
|
57
|
+
}
|
@@ -0,0 +1,44 @@
|
|
1
|
+
/**
|
2
|
+
* This fuzz target performs a lz4 round-trip test (compress & decompress),
|
3
|
+
* compares the result with the original, and calls abort() on corruption.
|
4
|
+
*/
|
5
|
+
|
6
|
+
#include <stddef.h>
|
7
|
+
#include <stdint.h>
|
8
|
+
#include <stdlib.h>
|
9
|
+
#include <string.h>
|
10
|
+
|
11
|
+
#include "fuzz_helpers.h"
|
12
|
+
#include "fuzz_data_producer.h"
|
13
|
+
#include "lz4.h"
|
14
|
+
#include "lz4hc.h"
|
15
|
+
|
16
|
+
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
|
17
|
+
{
|
18
|
+
FUZZ_dataProducer_t *producer = FUZZ_dataProducer_create(data, size);
|
19
|
+
int const level = FUZZ_dataProducer_range32(producer,
|
20
|
+
LZ4HC_CLEVEL_MIN, LZ4HC_CLEVEL_MAX);
|
21
|
+
size = FUZZ_dataProducer_remainingBytes(producer);
|
22
|
+
|
23
|
+
size_t const dstCapacity = LZ4_compressBound(size);
|
24
|
+
char* const dst = (char*)malloc(dstCapacity);
|
25
|
+
char* const rt = (char*)malloc(size);
|
26
|
+
|
27
|
+
FUZZ_ASSERT(dst);
|
28
|
+
FUZZ_ASSERT(rt);
|
29
|
+
|
30
|
+
/* Compression must succeed and round trip correctly. */
|
31
|
+
int const dstSize = LZ4_compress_HC((const char*)data, dst, size,
|
32
|
+
dstCapacity, level);
|
33
|
+
FUZZ_ASSERT(dstSize > 0);
|
34
|
+
|
35
|
+
int const rtSize = LZ4_decompress_safe(dst, rt, dstSize, size);
|
36
|
+
FUZZ_ASSERT_MSG(rtSize == size, "Incorrect size");
|
37
|
+
FUZZ_ASSERT_MSG(!memcmp(data, rt, size), "Corruption!");
|
38
|
+
|
39
|
+
free(dst);
|
40
|
+
free(rt);
|
41
|
+
FUZZ_dataProducer_free(producer);
|
42
|
+
|
43
|
+
return 0;
|
44
|
+
}
|
@@ -0,0 +1,302 @@
|
|
1
|
+
/**
|
2
|
+
* This fuzz target performs a lz4 streaming round-trip test
|
3
|
+
* (compress & decompress), compares the result with the original, and calls
|
4
|
+
* abort() on corruption.
|
5
|
+
*/
|
6
|
+
|
7
|
+
#include <stddef.h>
|
8
|
+
#include <stdint.h>
|
9
|
+
#include <stdlib.h>
|
10
|
+
#include <string.h>
|
11
|
+
|
12
|
+
#include "fuzz_helpers.h"
|
13
|
+
#define LZ4_STATIC_LINKING_ONLY
|
14
|
+
#include "lz4.h"
|
15
|
+
#define LZ4_HC_STATIC_LINKING_ONLY
|
16
|
+
#include "lz4hc.h"
|
17
|
+
|
18
|
+
typedef struct {
|
19
|
+
char const* buf;
|
20
|
+
size_t size;
|
21
|
+
size_t pos;
|
22
|
+
} const_cursor_t;
|
23
|
+
|
24
|
+
typedef struct {
|
25
|
+
char* buf;
|
26
|
+
size_t size;
|
27
|
+
size_t pos;
|
28
|
+
} cursor_t;
|
29
|
+
|
30
|
+
typedef struct {
|
31
|
+
LZ4_stream_t* cstream;
|
32
|
+
LZ4_streamHC_t* cstreamHC;
|
33
|
+
LZ4_streamDecode_t* dstream;
|
34
|
+
const_cursor_t data;
|
35
|
+
cursor_t compressed;
|
36
|
+
cursor_t roundTrip;
|
37
|
+
uint32_t seed;
|
38
|
+
int level;
|
39
|
+
} state_t;
|
40
|
+
|
41
|
+
cursor_t cursor_create(size_t size)
|
42
|
+
{
|
43
|
+
cursor_t cursor;
|
44
|
+
cursor.buf = (char*)malloc(size);
|
45
|
+
cursor.size = size;
|
46
|
+
cursor.pos = 0;
|
47
|
+
FUZZ_ASSERT(cursor.buf);
|
48
|
+
return cursor;
|
49
|
+
}
|
50
|
+
|
51
|
+
typedef void (*round_trip_t)(state_t* state);
|
52
|
+
|
53
|
+
void cursor_free(cursor_t cursor)
|
54
|
+
{
|
55
|
+
free(cursor.buf);
|
56
|
+
}
|
57
|
+
|
58
|
+
state_t state_create(char const* data, size_t size, uint32_t seed)
|
59
|
+
{
|
60
|
+
state_t state;
|
61
|
+
|
62
|
+
state.seed = seed;
|
63
|
+
|
64
|
+
state.data.buf = (char const*)data;
|
65
|
+
state.data.size = size;
|
66
|
+
state.data.pos = 0;
|
67
|
+
|
68
|
+
/* Extra margin because we are streaming. */
|
69
|
+
state.compressed = cursor_create(1024 + 2 * LZ4_compressBound(size));
|
70
|
+
state.roundTrip = cursor_create(size);
|
71
|
+
|
72
|
+
state.cstream = LZ4_createStream();
|
73
|
+
FUZZ_ASSERT(state.cstream);
|
74
|
+
state.cstreamHC = LZ4_createStreamHC();
|
75
|
+
FUZZ_ASSERT(state.cstream);
|
76
|
+
state.dstream = LZ4_createStreamDecode();
|
77
|
+
FUZZ_ASSERT(state.dstream);
|
78
|
+
|
79
|
+
return state;
|
80
|
+
}
|
81
|
+
|
82
|
+
void state_free(state_t state)
|
83
|
+
{
|
84
|
+
cursor_free(state.compressed);
|
85
|
+
cursor_free(state.roundTrip);
|
86
|
+
LZ4_freeStream(state.cstream);
|
87
|
+
LZ4_freeStreamHC(state.cstreamHC);
|
88
|
+
LZ4_freeStreamDecode(state.dstream);
|
89
|
+
}
|
90
|
+
|
91
|
+
static void state_reset(state_t* state, uint32_t seed)
|
92
|
+
{
|
93
|
+
state->level = FUZZ_rand32(&seed, LZ4HC_CLEVEL_MIN, LZ4HC_CLEVEL_MAX);
|
94
|
+
LZ4_resetStream_fast(state->cstream);
|
95
|
+
LZ4_resetStreamHC_fast(state->cstreamHC, state->level);
|
96
|
+
LZ4_setStreamDecode(state->dstream, NULL, 0);
|
97
|
+
state->data.pos = 0;
|
98
|
+
state->compressed.pos = 0;
|
99
|
+
state->roundTrip.pos = 0;
|
100
|
+
state->seed = seed;
|
101
|
+
}
|
102
|
+
|
103
|
+
static void state_decompress(state_t* state, char const* src, int srcSize)
|
104
|
+
{
|
105
|
+
char* dst = state->roundTrip.buf + state->roundTrip.pos;
|
106
|
+
int const dstCapacity = state->roundTrip.size - state->roundTrip.pos;
|
107
|
+
int const dSize = LZ4_decompress_safe_continue(state->dstream, src, dst,
|
108
|
+
srcSize, dstCapacity);
|
109
|
+
FUZZ_ASSERT(dSize >= 0);
|
110
|
+
state->roundTrip.pos += dSize;
|
111
|
+
}
|
112
|
+
|
113
|
+
static void state_checkRoundTrip(state_t const* state)
|
114
|
+
{
|
115
|
+
char const* data = state->data.buf;
|
116
|
+
size_t const size = state->data.size;
|
117
|
+
FUZZ_ASSERT_MSG(size == state->roundTrip.pos, "Incorrect size!");
|
118
|
+
FUZZ_ASSERT_MSG(!memcmp(data, state->roundTrip.buf, size), "Corruption!");
|
119
|
+
}
|
120
|
+
|
121
|
+
/**
|
122
|
+
* Picks a dictionary size and trims the dictionary off of the data.
|
123
|
+
* We copy the dictionary to the roundTrip so our validation passes.
|
124
|
+
*/
|
125
|
+
static size_t state_trimDict(state_t* state)
|
126
|
+
{
|
127
|
+
/* 64 KB is the max dict size, allow slightly beyond that to test trim. */
|
128
|
+
uint32_t maxDictSize = MIN(70 * 1024, state->data.size);
|
129
|
+
size_t const dictSize = FUZZ_rand32(&state->seed, 0, maxDictSize);
|
130
|
+
DEBUGLOG(2, "dictSize = %zu", dictSize);
|
131
|
+
FUZZ_ASSERT(state->data.pos == 0);
|
132
|
+
FUZZ_ASSERT(state->roundTrip.pos == 0);
|
133
|
+
memcpy(state->roundTrip.buf, state->data.buf, dictSize);
|
134
|
+
state->data.pos += dictSize;
|
135
|
+
state->roundTrip.pos += dictSize;
|
136
|
+
return dictSize;
|
137
|
+
}
|
138
|
+
|
139
|
+
static void state_prefixRoundTrip(state_t* state)
|
140
|
+
{
|
141
|
+
while (state->data.pos != state->data.size) {
|
142
|
+
char const* src = state->data.buf + state->data.pos;
|
143
|
+
char* dst = state->compressed.buf + state->compressed.pos;
|
144
|
+
int const srcRemaining = state->data.size - state->data.pos;
|
145
|
+
int const srcSize = FUZZ_rand32(&state->seed, 0, srcRemaining);
|
146
|
+
int const dstCapacity = state->compressed.size - state->compressed.pos;
|
147
|
+
int const cSize = LZ4_compress_fast_continue(state->cstream, src, dst,
|
148
|
+
srcSize, dstCapacity, 0);
|
149
|
+
FUZZ_ASSERT(cSize > 0);
|
150
|
+
state->data.pos += srcSize;
|
151
|
+
state->compressed.pos += cSize;
|
152
|
+
state_decompress(state, dst, cSize);
|
153
|
+
}
|
154
|
+
}
|
155
|
+
|
156
|
+
static void state_extDictRoundTrip(state_t* state)
|
157
|
+
{
|
158
|
+
int i = 0;
|
159
|
+
cursor_t data2 = cursor_create(state->data.size);
|
160
|
+
memcpy(data2.buf, state->data.buf, state->data.size);
|
161
|
+
while (state->data.pos != state->data.size) {
|
162
|
+
char const* data = (i++ & 1) ? state->data.buf : data2.buf;
|
163
|
+
char const* src = data + state->data.pos;
|
164
|
+
char* dst = state->compressed.buf + state->compressed.pos;
|
165
|
+
int const srcRemaining = state->data.size - state->data.pos;
|
166
|
+
int const srcSize = FUZZ_rand32(&state->seed, 0, srcRemaining);
|
167
|
+
int const dstCapacity = state->compressed.size - state->compressed.pos;
|
168
|
+
int const cSize = LZ4_compress_fast_continue(state->cstream, src, dst,
|
169
|
+
srcSize, dstCapacity, 0);
|
170
|
+
FUZZ_ASSERT(cSize > 0);
|
171
|
+
state->data.pos += srcSize;
|
172
|
+
state->compressed.pos += cSize;
|
173
|
+
state_decompress(state, dst, cSize);
|
174
|
+
}
|
175
|
+
cursor_free(data2);
|
176
|
+
}
|
177
|
+
|
178
|
+
static void state_randomRoundTrip(state_t* state, round_trip_t rt0,
|
179
|
+
round_trip_t rt1)
|
180
|
+
{
|
181
|
+
if (FUZZ_rand32(&state->seed, 0, 1)) {
|
182
|
+
rt0(state);
|
183
|
+
} else {
|
184
|
+
rt1(state);
|
185
|
+
}
|
186
|
+
}
|
187
|
+
|
188
|
+
static void state_loadDictRoundTrip(state_t* state)
|
189
|
+
{
|
190
|
+
char const* dict = state->data.buf;
|
191
|
+
size_t const dictSize = state_trimDict(state);
|
192
|
+
LZ4_loadDict(state->cstream, dict, dictSize);
|
193
|
+
LZ4_setStreamDecode(state->dstream, dict, dictSize);
|
194
|
+
state_randomRoundTrip(state, state_prefixRoundTrip, state_extDictRoundTrip);
|
195
|
+
}
|
196
|
+
|
197
|
+
static void state_attachDictRoundTrip(state_t* state)
|
198
|
+
{
|
199
|
+
char const* dict = state->data.buf;
|
200
|
+
size_t const dictSize = state_trimDict(state);
|
201
|
+
LZ4_stream_t* dictStream = LZ4_createStream();
|
202
|
+
LZ4_loadDict(dictStream, dict, dictSize);
|
203
|
+
LZ4_attach_dictionary(state->cstream, dictStream);
|
204
|
+
LZ4_setStreamDecode(state->dstream, dict, dictSize);
|
205
|
+
state_randomRoundTrip(state, state_prefixRoundTrip, state_extDictRoundTrip);
|
206
|
+
LZ4_freeStream(dictStream);
|
207
|
+
}
|
208
|
+
|
209
|
+
static void state_prefixHCRoundTrip(state_t* state)
|
210
|
+
{
|
211
|
+
while (state->data.pos != state->data.size) {
|
212
|
+
char const* src = state->data.buf + state->data.pos;
|
213
|
+
char* dst = state->compressed.buf + state->compressed.pos;
|
214
|
+
int const srcRemaining = state->data.size - state->data.pos;
|
215
|
+
int const srcSize = FUZZ_rand32(&state->seed, 0, srcRemaining);
|
216
|
+
int const dstCapacity = state->compressed.size - state->compressed.pos;
|
217
|
+
int const cSize = LZ4_compress_HC_continue(state->cstreamHC, src, dst,
|
218
|
+
srcSize, dstCapacity);
|
219
|
+
FUZZ_ASSERT(cSize > 0);
|
220
|
+
state->data.pos += srcSize;
|
221
|
+
state->compressed.pos += cSize;
|
222
|
+
state_decompress(state, dst, cSize);
|
223
|
+
}
|
224
|
+
}
|
225
|
+
|
226
|
+
static void state_extDictHCRoundTrip(state_t* state)
|
227
|
+
{
|
228
|
+
int i = 0;
|
229
|
+
cursor_t data2 = cursor_create(state->data.size);
|
230
|
+
DEBUGLOG(2, "extDictHC");
|
231
|
+
memcpy(data2.buf, state->data.buf, state->data.size);
|
232
|
+
while (state->data.pos != state->data.size) {
|
233
|
+
char const* data = (i++ & 1) ? state->data.buf : data2.buf;
|
234
|
+
char const* src = data + state->data.pos;
|
235
|
+
char* dst = state->compressed.buf + state->compressed.pos;
|
236
|
+
int const srcRemaining = state->data.size - state->data.pos;
|
237
|
+
int const srcSize = FUZZ_rand32(&state->seed, 0, srcRemaining);
|
238
|
+
int const dstCapacity = state->compressed.size - state->compressed.pos;
|
239
|
+
int const cSize = LZ4_compress_HC_continue(state->cstreamHC, src, dst,
|
240
|
+
srcSize, dstCapacity);
|
241
|
+
FUZZ_ASSERT(cSize > 0);
|
242
|
+
DEBUGLOG(2, "srcSize = %d", srcSize);
|
243
|
+
state->data.pos += srcSize;
|
244
|
+
state->compressed.pos += cSize;
|
245
|
+
state_decompress(state, dst, cSize);
|
246
|
+
}
|
247
|
+
cursor_free(data2);
|
248
|
+
}
|
249
|
+
|
250
|
+
static void state_loadDictHCRoundTrip(state_t* state)
|
251
|
+
{
|
252
|
+
char const* dict = state->data.buf;
|
253
|
+
size_t const dictSize = state_trimDict(state);
|
254
|
+
LZ4_loadDictHC(state->cstreamHC, dict, dictSize);
|
255
|
+
LZ4_setStreamDecode(state->dstream, dict, dictSize);
|
256
|
+
state_randomRoundTrip(state, state_prefixHCRoundTrip,
|
257
|
+
state_extDictHCRoundTrip);
|
258
|
+
}
|
259
|
+
|
260
|
+
static void state_attachDictHCRoundTrip(state_t* state)
|
261
|
+
{
|
262
|
+
char const* dict = state->data.buf;
|
263
|
+
size_t const dictSize = state_trimDict(state);
|
264
|
+
LZ4_streamHC_t* dictStream = LZ4_createStreamHC();
|
265
|
+
LZ4_setCompressionLevel(dictStream, state->level);
|
266
|
+
LZ4_loadDictHC(dictStream, dict, dictSize);
|
267
|
+
LZ4_attach_HC_dictionary(state->cstreamHC, dictStream);
|
268
|
+
LZ4_setStreamDecode(state->dstream, dict, dictSize);
|
269
|
+
state_randomRoundTrip(state, state_prefixHCRoundTrip,
|
270
|
+
state_extDictHCRoundTrip);
|
271
|
+
LZ4_freeStreamHC(dictStream);
|
272
|
+
}
|
273
|
+
|
274
|
+
round_trip_t roundTrips[] = {
|
275
|
+
&state_prefixRoundTrip,
|
276
|
+
&state_extDictRoundTrip,
|
277
|
+
&state_loadDictRoundTrip,
|
278
|
+
&state_attachDictRoundTrip,
|
279
|
+
&state_prefixHCRoundTrip,
|
280
|
+
&state_extDictHCRoundTrip,
|
281
|
+
&state_loadDictHCRoundTrip,
|
282
|
+
&state_attachDictHCRoundTrip,
|
283
|
+
};
|
284
|
+
|
285
|
+
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
|
286
|
+
{
|
287
|
+
uint32_t seed = FUZZ_seed(&data, &size);
|
288
|
+
state_t state = state_create((char const*)data, size, seed);
|
289
|
+
const int n = sizeof(roundTrips) / sizeof(round_trip_t);
|
290
|
+
int i;
|
291
|
+
|
292
|
+
for (i = 0; i < n; ++i) {
|
293
|
+
DEBUGLOG(2, "Round trip %d", i);
|
294
|
+
state_reset(&state, seed);
|
295
|
+
roundTrips[i](&state);
|
296
|
+
state_checkRoundTrip(&state);
|
297
|
+
}
|
298
|
+
|
299
|
+
state_free(state);
|
300
|
+
|
301
|
+
return 0;
|
302
|
+
}
|