Coverage Report

Created: 2026-02-14 07:22

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/kea/fuzz/fuzz_packets_kea_dhcp4.cc
Line
Count
Source
1
// Copyright (C) 2024-2025 Internet Systems Consortium, Inc. ("ISC")
2
//
3
// This Source Code Form is subject to the terms of the Mozilla Public
4
// License, v. 2.0. If a copy of the MPL was not distributed with this
5
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
6
7
#include <config.h>
8
9
#include <fuzz.h>
10
11
#include <cc/command_interpreter.h>
12
#include <cc/user_context.h>
13
#include <dhcp4/ctrl_dhcp4_srv.h>
14
#include <dhcp4/json_config_parser.h>
15
#include <dhcp4/parser_context.h>
16
#include <dhcpsrv/packet_fuzzer.h>
17
#include <util/encode/encode.h>
18
19
#include <cassert>
20
#include <cstdlib>
21
#include <util/filesystem.h>
22
#include <vector>
23
24
using namespace isc;
25
using namespace isc::config;
26
using namespace isc::util;
27
using namespace std;
28
29
namespace {
30
31
static string const KEA_DHCP4_CONF(KEA_FUZZ_DIR() + "/kea-dhcp4.conf");
32
static string KEA_DHCP4_FUZZING_INTERFACE;
33
static string KEA_DHCP4_FUZZING_ADDRESS;
34
35
}  // namespace
36
37
extern "C" {
38
39
int
40
4
LLVMFuzzerInitialize() {
41
4
    static bool initialized(DoInitialization());
42
4
    assert(initialized);
43
44
4
    setenv("KEA_DHCP4_FUZZING_ROTATE_PORT", "true", 0);
45
46
4
    if (if_nametoindex("lo") > 0) {
47
4
        KEA_DHCP4_FUZZING_INTERFACE = string("lo");
48
4
    } else if (if_nametoindex("lo0") > 0) {
49
0
        KEA_DHCP4_FUZZING_INTERFACE = string("lo0");
50
0
    }
51
52
4
    char const* iface(getenv("KEA_DHCP4_FUZZING_INTERFACE"));
53
4
    if (iface) {
54
0
        KEA_DHCP4_FUZZING_INTERFACE = string(iface);
55
0
    }
56
57
4
    char const* address(getenv("KEA_DHCP4_FUZZING_ADDRESS"));
58
4
    KEA_DHCP4_FUZZING_ADDRESS = string(address ? address : "127.0.0.1");
59
60
4
    writeToFile(KEA_DHCP4_CONF, R"(
61
4
      {
62
4
        "Dhcp4": {
63
4
          "interfaces-config": {
64
4
            "dhcp-socket-type": "udp",
65
4
            "interfaces": [
66
4
              ")" + KEA_DHCP4_FUZZING_INTERFACE + R"("
67
4
            ]
68
4
          },
69
4
          "lease-database": {
70
4
            "persist": false,
71
4
            "type": "memfile"
72
4
          },
73
4
          "subnet4": [
74
4
            {
75
4
              "id": 1,
76
4
              "pools": [
77
4
                {
78
4
                  "pool": "10.0.0.0/8"
79
4
                }
80
4
              ],
81
4
              "subnet": "10.0.0.0/8"
82
4
            }
83
4
          ]
84
4
        }
85
4
      }
86
4
    )");
87
88
    // Iterate through the interfaces and expect no errors.
89
8
    for (IfacePtr const& interface : IfaceMgr::instance().getIfaces()) {
90
8
        for (string const& error : interface->getErrors()) {
91
0
            cout << error << endl;
92
0
        }
93
8
        assert(interface->getErrors().empty());
94
8
    }
95
96
4
    return 0;
97
4
}
98
99
int
100
8
LLVMFuzzerTearDown() {
101
8
    try {
102
8
        remove(KEA_DHCP4_CONF.c_str());
103
8
    } catch (...) {
104
0
    }
105
8
    return 0;
106
8
}
107
108
int
109
746
LLVMFuzzerTestOneInput(uint8_t const* data, size_t size) {
110
746
    vector<uint8_t> byte_stream;
111
746
    bool const valid(byteStreamToPacketData(data, size, byte_stream));
112
746
    if (!valid) {
113
271
        cout << "Invalid input. Skipping..." << endl;
114
271
        return 0;
115
271
    }
116
117
475
    ControlledDhcpv4Srv server;
118
475
    server.init(KEA_DHCP4_CONF);
119
120
    // Fuzz.
121
475
    PacketFuzzer fuzzer(ControlledDhcpv4Srv::getInstance()->getServerPort(),
122
475
                        KEA_DHCP4_FUZZING_INTERFACE, KEA_DHCP4_FUZZING_ADDRESS);
123
475
    fuzzer.transfer(byte_stream.data(), byte_stream.size());
124
475
    ControlledDhcpv4Srv::getInstance()->runOne();
125
126
475
    return 0;
127
746
}
128
129
}  // extern "C"