Coverage Report

Created: 2026-08-25 19:22

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
179k
{
17
179k
    std::vector<std::byte> ret;
18
179k
    uint8_t next_byte{0};
19
179k
    int next_byte_bits{0};
20
181M
    for (uint8_t val : bits) {
  Branch (20:22): [True: 181M, False: 179k]
21
181M
        next_byte |= (val & 1) << (next_byte_bits++);
22
181M
        if (next_byte_bits == 8) {
  Branch (22:13): [True: 22.6M, False: 159M]
23
22.6M
            ret.push_back(std::byte(next_byte));
24
22.6M
            next_byte = 0;
25
22.6M
            next_byte_bits = 0;
26
22.6M
        }
27
181M
    }
28
179k
    if (next_byte_bits) ret.push_back(std::byte(next_byte));
  Branch (28:9): [True: 156k, False: 22.3k]
29
30
179k
    return ret;
31
179k
}
32
33
FUZZ_TARGET(asmap_direct)
34
313
{
35
    // Encoding: [asmap using 1 bit / byte] 0xFF [addr using 1 bit / byte]
36
313
    std::optional<size_t> sep_pos_opt;
37
209k
    for (size_t pos = 0; pos < buffer.size(); ++pos) {
  Branch (37:26): [True: 209k, False: 308]
38
209k
        uint8_t x = buffer[pos];
39
209k
        if ((x & 0xFE) == 0) continue;
  Branch (39:13): [True: 208k, False: 312]
40
312
        if (x == 0xFF) {
  Branch (40:13): [True: 308, False: 4]
41
308
            if (sep_pos_opt) return;
  Branch (41:17): [True: 1, False: 307]
42
307
            sep_pos_opt = pos;
43
307
        } else {
44
4
            return;
45
4
        }
46
312
    }
47
308
    if (!sep_pos_opt) return; // Needs exactly 1 separator
  Branch (47:9): [True: 2, False: 306]
48
306
    const size_t sep_pos{sep_pos_opt.value()};
49
306
    const size_t ip_len{buffer.size() - sep_pos - 1};
50
306
    if (ip_len > 128) return; // At most 128 bits in IP address
  Branch (50:9): [True: 1, False: 305]
51
52
    // Checks on asmap
53
305
    auto asmap = BitsToBytes(buffer.first(sep_pos));
54
305
    if (SanityCheckAsmap(asmap, ip_len)) {
  Branch (54:9): [True: 214, False: 91]
55
        // Verify that for valid asmaps, no prefix (except up to 7 zero padding bits) is valid.
56
178k
        for (size_t prefix_len = sep_pos - 1; prefix_len > 0; --prefix_len) {
  Branch (56:47): [True: 178k, False: 214]
57
178k
            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
178k
            if (prefix.size() == asmap.size()) continue;
  Branch (61:17): [True: 415, False: 178k]
62
178k
            assert(!SanityCheckAsmap(prefix, ip_len));
  Branch (62:13): [True: 178k, False: 0]
63
178k
        }
64
65
        // No address input should trigger assertions in interpreter
66
214
        auto addr = BitsToBytes(buffer.subspan(sep_pos + 1));
67
214
        (void)Interpret(asmap, addr);
68
214
    }
69
305
}