/src/zstd/tests/fuzz/dictionary_loader.c
Line | Count | Source |
1 | | /* |
2 | | * Copyright (c) Meta Platforms, Inc. and affiliates. |
3 | | * All rights reserved. |
4 | | * |
5 | | * This source code is licensed under both the BSD-style license (found in the |
6 | | * LICENSE file in the root directory of this source tree) and the GPLv2 (found |
7 | | * in the COPYING file in the root directory of this source tree). |
8 | | * You may select, at your option, one of the above-listed licenses. |
9 | | */ |
10 | | |
11 | | /** |
12 | | * This fuzz target makes sure that whenever a compression dictionary can be |
13 | | * loaded, the data can be round tripped. |
14 | | */ |
15 | | |
16 | | #include <stddef.h> |
17 | | #include <stdlib.h> |
18 | | #include <stdio.h> |
19 | | #include <string.h> |
20 | | #include "fuzz_helpers.h" |
21 | | #include "zstd_helpers.h" |
22 | | #include "fuzz_data_producer.h" |
23 | | #include "fuzz_third_party_seq_prod.h" |
24 | | |
25 | | /** |
26 | | * Compresses the data and returns the compressed size or an error. |
27 | | */ |
28 | | static size_t compress(void* compressed, size_t compressedCapacity, |
29 | | void const* source, size_t sourceSize, |
30 | | void const* dict, size_t dictSize, |
31 | | ZSTD_dictLoadMethod_e dictLoadMethod, |
32 | | ZSTD_dictContentType_e dictContentType, |
33 | | int const refPrefix) |
34 | 9.98k | { |
35 | 9.98k | ZSTD_CCtx* cctx = ZSTD_createCCtx(); |
36 | 9.98k | if (refPrefix) |
37 | 9.98k | FUZZ_ZASSERT(ZSTD_CCtx_refPrefix_advanced( |
38 | 4.74k | cctx, dict, dictSize, dictContentType)); |
39 | 4.74k | else |
40 | 9.98k | FUZZ_ZASSERT(ZSTD_CCtx_loadDictionary_advanced( |
41 | 9.98k | cctx, dict, dictSize, dictLoadMethod, dictContentType)); |
42 | 9.98k | size_t const compressedSize = ZSTD_compress2( |
43 | 9.98k | cctx, compressed, compressedCapacity, source, sourceSize); |
44 | 9.98k | ZSTD_freeCCtx(cctx); |
45 | 9.98k | return compressedSize; |
46 | 9.98k | } |
47 | | |
48 | | static size_t decompress(void* result, size_t resultCapacity, |
49 | | void const* compressed, size_t compressedSize, |
50 | | void const* dict, size_t dictSize, |
51 | | ZSTD_dictLoadMethod_e dictLoadMethod, |
52 | | ZSTD_dictContentType_e dictContentType, |
53 | | int const refPrefix) |
54 | 9.54k | { |
55 | 9.54k | ZSTD_DCtx* dctx = ZSTD_createDCtx(); |
56 | 9.54k | if (refPrefix) |
57 | 9.54k | FUZZ_ZASSERT(ZSTD_DCtx_refPrefix_advanced( |
58 | 4.47k | dctx, dict, dictSize, dictContentType)); |
59 | 4.47k | else |
60 | 9.54k | FUZZ_ZASSERT(ZSTD_DCtx_loadDictionary_advanced( |
61 | 9.54k | dctx, dict, dictSize, dictLoadMethod, dictContentType)); |
62 | 9.54k | size_t const resultSize = ZSTD_decompressDCtx( |
63 | 9.54k | dctx, result, resultCapacity, compressed, compressedSize); |
64 | 9.54k | FUZZ_ZASSERT(resultSize); |
65 | 9.54k | ZSTD_freeDCtx(dctx); |
66 | 9.54k | return resultSize; |
67 | 9.54k | } |
68 | | |
69 | | int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size) |
70 | 9.98k | { |
71 | 9.98k | FUZZ_SEQ_PROD_SETUP(); |
72 | 9.98k | FUZZ_dataProducer_t *producer = FUZZ_dataProducer_create(src, size); |
73 | 9.98k | int const refPrefix = FUZZ_dataProducer_uint32Range(producer, 0, 1) != 0; |
74 | 9.98k | ZSTD_dictLoadMethod_e const dlm = |
75 | 9.98k | size = FUZZ_dataProducer_uint32Range(producer, 0, 1); |
76 | 9.98k | ZSTD_dictContentType_e const dct = |
77 | 9.98k | FUZZ_dataProducer_uint32Range(producer, 0, 2); |
78 | 9.98k | size = FUZZ_dataProducer_remainingBytes(producer); |
79 | | |
80 | 9.98k | DEBUGLOG(2, "Dict load method %d", dlm); |
81 | 9.98k | DEBUGLOG(2, "Dict content type %d", dct); |
82 | 9.98k | DEBUGLOG(2, "Dict size %u", (unsigned)size); |
83 | | |
84 | 9.98k | void* const rBuf = FUZZ_malloc(size); |
85 | 9.98k | size_t const cBufSize = ZSTD_compressBound(size); |
86 | 9.98k | void* const cBuf = FUZZ_malloc(cBufSize); |
87 | | |
88 | 9.98k | size_t const cSize = |
89 | 9.98k | compress(cBuf, cBufSize, src, size, src, size, dlm, dct, refPrefix); |
90 | | /* compression failing is okay */ |
91 | 9.98k | if (ZSTD_isError(cSize)) { |
92 | 439 | FUZZ_ASSERT_MSG(dct != ZSTD_dct_rawContent, "Raw must always succeed!"); |
93 | 439 | goto out; |
94 | 439 | } |
95 | 9.54k | size_t const rSize = |
96 | 9.54k | decompress(rBuf, size, cBuf, cSize, src, size, dlm, dct, refPrefix); |
97 | 9.54k | FUZZ_ASSERT_MSG(rSize == size, "Incorrect regenerated size"); |
98 | 9.54k | FUZZ_ASSERT_MSG(!FUZZ_memcmp(src, rBuf, size), "Corruption!"); |
99 | | |
100 | 9.98k | out: |
101 | 9.98k | free(cBuf); |
102 | 9.98k | free(rBuf); |
103 | 9.98k | FUZZ_dataProducer_free(producer); |
104 | 9.98k | FUZZ_SEQ_PROD_TEARDOWN(); |
105 | 9.98k | return 0; |
106 | 9.54k | } |