Coverage Report

Created: 2026-06-09 19:51

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/root/bitcoin/src/test/fuzz/asmap_direct.cpp
Line
Count
Source
1
// Copyright (c) 2020-present The Bitcoin Core developers
2
// Distributed under the MIT software license, see the accompanying
3
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4
5
#include <netaddress.h>
6
#include <util/asmap.h>
7
#include <test/fuzz/fuzz.h>
8
9
#include <cstdint>
10
#include <optional>
11
#include <vector>
12
13
#include <cassert>
14
15
std::vector<std::byte> BitsToBytes(std::span<const uint8_t> bits) noexcept
16
0
{
17
0
    std::vector<std::byte> ret;
18
0
    uint8_t next_byte{0};
19
0
    int next_byte_bits{0};
20
0
    for (uint8_t val : bits) {
  Branch (20:22): [True: 0, False: 0]
21
0
        next_byte |= (val & 1) << (next_byte_bits++);
22
0
        if (next_byte_bits == 8) {
  Branch (22:13): [True: 0, False: 0]
23
0
            ret.push_back(std::byte(next_byte));
24
0
            next_byte = 0;
25
0
            next_byte_bits = 0;
26
0
        }
27
0
    }
28
0
    if (next_byte_bits) ret.push_back(std::byte(next_byte));
  Branch (28:9): [True: 0, False: 0]
29
30
0
    return ret;
31
0
}
32
33
FUZZ_TARGET(asmap_direct)
34
0
{
35
    // Encoding: [asmap using 1 bit / byte] 0xFF [addr using 1 bit / byte]
36
0
    std::optional<size_t> sep_pos_opt;
37
0
    for (size_t pos = 0; pos < buffer.size(); ++pos) {
  Branch (37:26): [True: 0, False: 0]
38
0
        uint8_t x = buffer[pos];
39
0
        if ((x & 0xFE) == 0) continue;
  Branch (39:13): [True: 0, False: 0]
40
0
        if (x == 0xFF) {
  Branch (40:13): [True: 0, False: 0]
41
0
            if (sep_pos_opt) return;
  Branch (41:17): [True: 0, False: 0]
42
0
            sep_pos_opt = pos;
43
0
        } else {
44
0
            return;
45
0
        }
46
0
    }
47
0
    if (!sep_pos_opt) return; // Needs exactly 1 separator
  Branch (47:9): [True: 0, False: 0]
48
0
    const size_t sep_pos{sep_pos_opt.value()};
49
0
    const size_t ip_len{buffer.size() - sep_pos - 1};
50
0
    if (ip_len > 128) return; // At most 128 bits in IP address
  Branch (50:9): [True: 0, False: 0]
51
52
    // Checks on asmap
53
0
    auto asmap = BitsToBytes(buffer.first(sep_pos));
54
0
    if (SanityCheckAsmap(asmap, ip_len)) {
  Branch (54:9): [True: 0, False: 0]
55
        // Verify that for valid asmaps, no prefix (except up to 7 zero padding bits) is valid.
56
0
        for (size_t prefix_len = sep_pos - 1; prefix_len > 0; --prefix_len) {
  Branch (56:47): [True: 0, False: 0]
57
0
            auto prefix = BitsToBytes(buffer.first(prefix_len));
58
            // We have to skip the prefixes of the same length as the original
59
            // asmap, since they will contain some zero padding bits in the last
60
            // byte.
61
0
            if (prefix.size() == asmap.size()) continue;
  Branch (61:17): [True: 0, False: 0]
62
0
            assert(!SanityCheckAsmap(prefix, ip_len));
  Branch (62:13): [True: 0, False: 0]
63
0
        }
64
65
        // No address input should trigger assertions in interpreter
66
0
        auto addr = BitsToBytes(buffer.subspan(sep_pos + 1));
67
0
        (void)Interpret(asmap, addr);
68
0
    }
69
0
}