Coverage Report

Created: 2024-09-08 06:32

/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
}