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