Coverage Report

Created: 2025-07-11 06:35

/src/zstd/tests/fuzz/block_round_trip.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 performs a zstd round-trip test (compress & decompress),
13
 * compares the result with the original, and calls abort() on corruption.
14
 */
15
16
#define ZSTD_STATIC_LINKING_ONLY
17
18
#include <stddef.h>
19
#include <stdlib.h>
20
#include <stdio.h>
21
#include <string.h>
22
#include "fuzz_helpers.h"
23
#include "zstd.h"
24
#include "zstd_helpers.h"
25
#include "fuzz_data_producer.h"
26
#include "fuzz_third_party_seq_prod.h"
27
28
static ZSTD_CCtx *cctx = NULL;
29
static ZSTD_DCtx *dctx = NULL;
30
static void* cBuf = NULL;
31
static void* rBuf = NULL;
32
static size_t bufSize = 0;
33
34
static size_t roundTripTest(void *result, size_t resultCapacity,
35
                            void *compressed, size_t compressedCapacity,
36
                            const void *src, size_t srcSize,
37
                            int cLevel)
38
16.3k
{
39
16.3k
    ZSTD_parameters const params = ZSTD_getParams(cLevel, srcSize, 0);
40
16.3k
    size_t ret = ZSTD_compressBegin_advanced(cctx, NULL, 0, params, srcSize);
41
16.3k
    FUZZ_ZASSERT(ret);
42
43
16.3k
    ret = ZSTD_compressBlock(cctx, compressed, compressedCapacity, src, srcSize);
44
16.3k
    FUZZ_ZASSERT(ret);
45
16.3k
    if (ret == 0) {
46
5.67k
        FUZZ_ASSERT(resultCapacity >= srcSize);
47
5.67k
        if (srcSize > 0) {
48
5.65k
            memcpy(result, src, srcSize);
49
5.65k
        }
50
5.67k
        return srcSize;
51
5.67k
    }
52
10.6k
    ZSTD_decompressBegin(dctx);
53
10.6k
    return ZSTD_decompressBlock(dctx, result, resultCapacity, compressed, ret);
54
16.3k
}
55
56
int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size)
57
16.3k
{
58
16.3k
    FUZZ_SEQ_PROD_SETUP();
59
60
    /* Give a random portion of src data to the producer, to use for
61
    parameter generation. The rest will be used for (de)compression */
62
16.3k
    FUZZ_dataProducer_t *producer = FUZZ_dataProducer_create(src, size);
63
16.3k
    size = FUZZ_dataProducer_reserveDataPrefix(producer);
64
65
16.3k
    int const cLevel = FUZZ_dataProducer_int32Range(producer, kMinClevel, kMaxClevel);
66
67
16.3k
    size_t neededBufSize = size;
68
16.3k
    if (size > ZSTD_BLOCKSIZE_MAX)
69
125
        size = ZSTD_BLOCKSIZE_MAX;
70
71
    /* Allocate all buffers and contexts if not already allocated */
72
16.3k
    if (neededBufSize > bufSize || !cBuf || !rBuf) {
73
2.26k
        free(cBuf);
74
2.26k
        free(rBuf);
75
2.26k
        cBuf = FUZZ_malloc(neededBufSize);
76
2.26k
        rBuf = FUZZ_malloc(neededBufSize);
77
2.26k
        bufSize = neededBufSize;
78
2.26k
    }
79
16.3k
    if (!cctx) {
80
16.3k
        cctx = ZSTD_createCCtx();
81
16.3k
        FUZZ_ASSERT(cctx);
82
16.3k
    }
83
16.3k
    if (!dctx) {
84
16.3k
        dctx = ZSTD_createDCtx();
85
16.3k
        FUZZ_ASSERT(dctx);
86
16.3k
    }
87
88
16.3k
    {
89
16.3k
        size_t const result =
90
16.3k
            roundTripTest(rBuf, neededBufSize, cBuf, neededBufSize, src, size,
91
16.3k
              cLevel);
92
16.3k
        FUZZ_ZASSERT(result);
93
16.3k
        FUZZ_ASSERT_MSG(result == size, "Incorrect regenerated size");
94
16.3k
        FUZZ_ASSERT_MSG(!FUZZ_memcmp(src, rBuf, size), "Corruption!");
95
16.3k
    }
96
16.3k
    FUZZ_dataProducer_free(producer);
97
16.3k
#ifndef STATEFUL_FUZZING
98
16.3k
    ZSTD_freeCCtx(cctx); cctx = NULL;
99
16.3k
    ZSTD_freeDCtx(dctx); dctx = NULL;
100
16.3k
#endif
101
16.3k
    FUZZ_SEQ_PROD_TEARDOWN();
102
16.3k
    return 0;
103
16.3k
}