• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) Facebook, Inc.
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 
24 /**
25  * Compresses the data and returns the compressed size or an error.
26  */
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)27 static size_t compress(void* compressed, size_t compressedCapacity,
28                        void const* source, size_t sourceSize,
29                        void const* dict, size_t dictSize,
30                        ZSTD_dictLoadMethod_e dictLoadMethod,
31                        ZSTD_dictContentType_e dictContentType,
32                        int const refPrefix)
33 {
34     ZSTD_CCtx* cctx = ZSTD_createCCtx();
35     if (refPrefix)
36         FUZZ_ZASSERT(ZSTD_CCtx_refPrefix_advanced(
37             cctx, dict, dictSize, dictContentType));
38     else
39         FUZZ_ZASSERT(ZSTD_CCtx_loadDictionary_advanced(
40             cctx, dict, dictSize, dictLoadMethod, dictContentType));
41     size_t const compressedSize = ZSTD_compress2(
42             cctx, compressed, compressedCapacity, source, sourceSize);
43     ZSTD_freeCCtx(cctx);
44     return compressedSize;
45 }
46 
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)47 static size_t decompress(void* result, size_t resultCapacity,
48                          void const* compressed, size_t compressedSize,
49                          void const* dict, size_t dictSize,
50                        ZSTD_dictLoadMethod_e dictLoadMethod,
51                          ZSTD_dictContentType_e dictContentType,
52                          int const refPrefix)
53 {
54     ZSTD_DCtx* dctx = ZSTD_createDCtx();
55     if (refPrefix)
56         FUZZ_ZASSERT(ZSTD_DCtx_refPrefix_advanced(
57             dctx, dict, dictSize, dictContentType));
58     else
59         FUZZ_ZASSERT(ZSTD_DCtx_loadDictionary_advanced(
60             dctx, dict, dictSize, dictLoadMethod, dictContentType));
61     size_t const resultSize = ZSTD_decompressDCtx(
62             dctx, result, resultCapacity, compressed, compressedSize);
63     FUZZ_ZASSERT(resultSize);
64     ZSTD_freeDCtx(dctx);
65     return resultSize;
66 }
67 
LLVMFuzzerTestOneInput(const uint8_t * src,size_t size)68 int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size)
69 {
70     FUZZ_dataProducer_t *producer = FUZZ_dataProducer_create(src, size);
71     int const refPrefix = FUZZ_dataProducer_uint32Range(producer, 0, 1) != 0;
72     ZSTD_dictLoadMethod_e const dlm =
73     size = FUZZ_dataProducer_uint32Range(producer, 0, 1);
74     ZSTD_dictContentType_e const dct =
75             FUZZ_dataProducer_uint32Range(producer, 0, 2);
76     size = FUZZ_dataProducer_remainingBytes(producer);
77 
78     DEBUGLOG(2, "Dict load method %d", dlm);
79     DEBUGLOG(2, "Dict content type %d", dct);
80     DEBUGLOG(2, "Dict size %u", (unsigned)size);
81 
82     void* const rBuf = FUZZ_malloc(size);
83     size_t const cBufSize = ZSTD_compressBound(size);
84     void* const cBuf = FUZZ_malloc(cBufSize);
85 
86     size_t const cSize =
87             compress(cBuf, cBufSize, src, size, src, size, dlm, dct, refPrefix);
88     /* compression failing is okay */
89     if (ZSTD_isError(cSize)) {
90       FUZZ_ASSERT_MSG(dct != ZSTD_dct_rawContent, "Raw must always succeed!");
91       goto out;
92     }
93     size_t const rSize =
94             decompress(rBuf, size, cBuf, cSize, src, size, dlm, dct, refPrefix);
95     FUZZ_ASSERT_MSG(rSize == size, "Incorrect regenerated size");
96     FUZZ_ASSERT_MSG(!FUZZ_memcmp(src, rBuf, size), "Corruption!");
97 
98 out:
99     free(cBuf);
100     free(rBuf);
101     FUZZ_dataProducer_free(producer);
102     return 0;
103 }
104