Coverage Report

Created: 2026-10-17 06:27

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
0
{
35
0
    ZSTD_CCtx* cctx = ZSTD_createCCtx();
36
0
    if (refPrefix)
37
0
        FUZZ_ZASSERT(ZSTD_CCtx_refPrefix_advanced(
38
0
            cctx, dict, dictSize, dictContentType));
39
0
    else
40
0
        FUZZ_ZASSERT(ZSTD_CCtx_loadDictionary_advanced(
41
0
            cctx, dict, dictSize, dictLoadMethod, dictContentType));
42
0
    size_t const compressedSize = ZSTD_compress2(
43
0
            cctx, compressed, compressedCapacity, source, sourceSize);
44
0
    ZSTD_freeCCtx(cctx);
45
0
    return compressedSize;
46
0
}
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
0
{
55
0
    ZSTD_DCtx* dctx = ZSTD_createDCtx();
56
0
    if (refPrefix)
57
0
        FUZZ_ZASSERT(ZSTD_DCtx_refPrefix_advanced(
58
0
            dctx, dict, dictSize, dictContentType));
59
0
    else
60
0
        FUZZ_ZASSERT(ZSTD_DCtx_loadDictionary_advanced(
61
0
            dctx, dict, dictSize, dictLoadMethod, dictContentType));
62
0
    size_t const resultSize = ZSTD_decompressDCtx(
63
0
            dctx, result, resultCapacity, compressed, compressedSize);
64
0
    FUZZ_ZASSERT(resultSize);
65
0
    ZSTD_freeDCtx(dctx);
66
0
    return resultSize;
67
0
}
68
69
int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size)
70
0
{
71
0
    FUZZ_SEQ_PROD_SETUP();
72
0
    FUZZ_dataProducer_t *producer = FUZZ_dataProducer_create(src, size);
73
0
    int const refPrefix = FUZZ_dataProducer_uint32Range(producer, 0, 1) != 0;
74
0
    ZSTD_dictLoadMethod_e const dlm =
75
0
    size = FUZZ_dataProducer_uint32Range(producer, 0, 1);
76
0
    ZSTD_dictContentType_e const dct =
77
0
            FUZZ_dataProducer_uint32Range(producer, 0, 2);
78
0
    size = FUZZ_dataProducer_remainingBytes(producer);
79
80
0
    DEBUGLOG(4, "Dict load method %d", dlm);
81
0
    DEBUGLOG(4, "Dict content type %d", dct);
82
0
    DEBUGLOG(4, "Dict size %u", (unsigned)size);
83
84
0
    void* const rBuf = FUZZ_malloc(size);
85
0
    size_t const cBufSize = ZSTD_compressBound(size);
86
0
    void* const cBuf = FUZZ_malloc(cBufSize);
87
88
0
    size_t const cSize =
89
0
            compress(cBuf, cBufSize, src, size, src, size, dlm, dct, refPrefix);
90
    /* compression failing is okay */
91
0
    if (ZSTD_isError(cSize)) {
92
0
      FUZZ_ASSERT_MSG(dct != ZSTD_dct_rawContent, "Raw must always succeed!");
93
0
      goto out;
94
0
    }
95
0
    size_t const rSize =
96
0
            decompress(rBuf, size, cBuf, cSize, src, size, dlm, dct, refPrefix);
97
0
    FUZZ_ASSERT_MSG(rSize == size, "Incorrect regenerated size");
98
0
    FUZZ_ASSERT_MSG(!FUZZ_memcmp(src, rBuf, size), "Corruption!");
99
100
0
out:
101
0
    free(cBuf);
102
0
    free(rBuf);
103
0
    FUZZ_dataProducer_free(producer);
104
0
    FUZZ_SEQ_PROD_TEARDOWN();
105
0
    return 0;
106
0
}