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