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