Coverage Report

Created: 2024-05-21 06:17

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