Coverage Report

Created: 2025-11-24 06:18

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/zstd/tests/fuzz/fse_read_ncount.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 round trips the FSE normalized count with FSE_writeNCount()
13
 * and FSE_readNcount() to ensure that it can always round trip correctly.
14
 */
15
16
#define FSE_STATIC_LINKING_ONLY
17
#define ZSTD_STATIC_LINKING_ONLY
18
19
#include <stddef.h>
20
#include <stdlib.h>
21
#include <stdio.h>
22
#include <string.h>
23
#include "fuzz_helpers.h"
24
#include "zstd_helpers.h"
25
#include "fuzz_data_producer.h"
26
#include "fse.h"
27
28
int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size)
29
218
{
30
218
    FUZZ_dataProducer_t *producer = FUZZ_dataProducer_create(src, size);
31
32
    /* Pick a random tableLog and maxSymbolValue */
33
218
    unsigned const tableLog = FUZZ_dataProducer_uint32Range(producer, FSE_MIN_TABLELOG, FSE_MAX_TABLELOG);
34
218
    unsigned const maxSymbolValue = FUZZ_dataProducer_uint32Range(producer, 0, 255);
35
36
218
    unsigned remainingWeight = (1u << tableLog) - 1;
37
218
    size_t dataSize;
38
218
    BYTE data[512];
39
218
    short ncount[256];
40
41
    /* Randomly fill the normalized count */
42
218
    memset(ncount, 0, sizeof(ncount));
43
218
    {
44
218
        unsigned s;
45
13.1k
        for (s = 0; s < maxSymbolValue && remainingWeight > 0; ++s) {
46
12.8k
            short n = (short)FUZZ_dataProducer_int32Range(producer, -1, remainingWeight);
47
12.8k
            ncount[s] = n;
48
12.8k
            if (n < 0) {
49
9.61k
                remainingWeight -= 1;
50
9.61k
            } else {
51
3.26k
                assert((unsigned)n <= remainingWeight);
52
3.26k
                remainingWeight -= n;
53
3.26k
            }
54
12.8k
        }
55
        /* Ensure ncount[maxSymbolValue] != 0 and the sum is (1<<tableLog) */
56
218
        ncount[maxSymbolValue] = remainingWeight + 1;
57
218
        if (ncount[maxSymbolValue] == 1 && FUZZ_dataProducer_uint32Range(producer, 0, 1) == 1) {
58
9
            ncount[maxSymbolValue] = -1;
59
9
        }
60
218
    }
61
    /* Write the normalized count */
62
218
    {
63
218
        FUZZ_ASSERT(sizeof(data) >= FSE_NCountWriteBound(maxSymbolValue, tableLog));
64
218
        dataSize = FSE_writeNCount(data, sizeof(data), ncount, maxSymbolValue, tableLog);
65
218
        FUZZ_ZASSERT(dataSize);
66
218
    }
67
    /* Read & validate the normalized count */
68
218
    {
69
218
        short rtNcount[256];
70
218
        unsigned rtMaxSymbolValue = 255;
71
218
        unsigned rtTableLog;
72
        /* Copy into a buffer with a random amount of random data at the end */
73
218
        size_t const buffSize = (size_t)FUZZ_dataProducer_uint32Range(producer, dataSize, sizeof(data));
74
218
        BYTE* const buff = FUZZ_malloc(buffSize);
75
218
        size_t rtDataSize;
76
218
        memcpy(buff, data, dataSize); 
77
218
        {
78
218
            size_t b;
79
9.91k
            for (b = dataSize; b < buffSize; ++b) {
80
9.70k
                buff[b] = (BYTE)FUZZ_dataProducer_uint32Range(producer, 0, 255);
81
9.70k
            }
82
218
        }
83
84
218
        rtDataSize = FSE_readNCount(rtNcount, &rtMaxSymbolValue, &rtTableLog, buff, buffSize);
85
218
        FUZZ_ZASSERT(rtDataSize);
86
218
        FUZZ_ASSERT(rtDataSize == dataSize);
87
218
        FUZZ_ASSERT(rtMaxSymbolValue == maxSymbolValue);
88
218
        FUZZ_ASSERT(rtTableLog == tableLog);
89
218
        {
90
218
            unsigned s;
91
23.3k
            for (s = 0; s <= maxSymbolValue; ++s) {
92
23.1k
                FUZZ_ASSERT(ncount[s] == rtNcount[s]);
93
23.1k
            }
94
218
        }
95
218
        free(buff);
96
218
    }
97
98
0
    FUZZ_dataProducer_free(producer);
99
218
    return 0;
100
218
}