Coverage Report

Created: 2026-05-16 07:13

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/kea-fuzzer/fuzz_dhcp_pkt4.cc
Line
Count
Source
1
// Copyright (C) 2025 Ada Logcis Ltd.
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
#include <fuzzer/FuzzedDataProvider.h>
9
10
#include <dhcp/pkt4.h>
11
#include <dhcp/pkt4o6.h>
12
#include <dhcp/pkt6.h>
13
#include <dhcp/libdhcp++.h>
14
#include <dhcp/option.h>
15
#include <dhcp/protocol_util.h>
16
#include <dhcp4/ctrl_dhcp4_srv.h>
17
#include <dhcp/option_vendor.h>
18
#include <dhcp/option_vendor_class.h>
19
#include <log/logger_support.h>
20
#include <process/daemon.h>
21
#include <util/buffer.h>
22
#include <util/filesystem.h>
23
24
#include <cstddef>
25
#include <cstdint>
26
#include <vector>
27
#include <list>
28
#include <memory>
29
#include <iostream>
30
#include <filesystem>
31
#include <fstream>
32
#include <string>
33
#include <cstdio>
34
35
#include "helper_func.h"
36
37
using namespace isc::dhcp;
38
using namespace isc::hooks;
39
using namespace isc::util;
40
41
static thread_local FuzzedDataProvider* fdp = nullptr;
42
43
4.04k
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
44
4.04k
    if (size < 236) {
45
        // package size requires at least 236 bytes
46
15
        return 0;
47
15
    }
48
49
    // Randomly enable validatePath checking
50
4.02k
    fdp = new FuzzedDataProvider(data, size);
51
4.02k
    isc::util::file::PathChecker::enableEnforcement(fdp->ConsumeBool());
52
53
    // Initialise logging
54
4.02k
    setenv("KEA_LOGGER_DESTINATION", "/dev/null", 0);
55
4.02k
    setenv("KEA_LOCKFILE_DIR", "/tmp", 0);
56
4.02k
    setenv("KEA_PIDFILE_DIR", "/tmp", 0);
57
4.02k
    setenv("KEA_LFC_EXECUTABLE", "/bin/true", 0);
58
4.02k
    try {
59
4.02k
        isc::log::initLogger("fuzzer");
60
4.02k
        isc::process::Daemon::loggerInit("fuzzer", false);
61
4.02k
        isc::process::Daemon::setDefaultLoggerName("fuzzer");
62
4.02k
    } catch (...) {
63
        // Early exit if logging initialisation failed
64
0
        return 0;
65
0
    }
66
67
    // Create temporary configuration file
68
4.02k
    std::string path = fuzz::writeTempConfig(true);
69
4.02k
    if (path.empty()) {
70
        // Early exit if configuration file creation failed
71
0
        fuzz::deleteTempFile(path);
72
0
        return 0;
73
0
    }
74
75
4.02k
    OptionCollection options;
76
4.02k
    std::list<uint16_t> deferred;
77
4.02k
    std::unique_ptr<ControlledDhcpv4Srv> srv;
78
4.02k
    std::vector<uint8_t> buf(data, data + size);
79
80
4.02k
    try {
81
        // Package parsing
82
4.02k
        Pkt4Ptr pkt = Pkt4Ptr(new Pkt4(data, size));
83
4.02k
        pkt->toText(fdp->ConsumeBool());
84
4.02k
        pkt->getType();
85
4.02k
        pkt->getTransid();
86
4.02k
        pkt->unpack();
87
4.02k
        pkt->pack();
88
4.02k
        pkt->getName();
89
4.02k
        pkt->getName(fdp->ConsumeIntegral<uint8_t>());
90
4.02k
        pkt->getLabel();           
91
4.02k
        pkt->getMAC(fdp->ConsumeIntegral<uint16_t>());
92
4.02k
    } catch (...) {}
93
94
    // OptionVendorClass parsing
95
4.02k
    try {
96
4.02k
        OptionBuffer buf(data, data + size);
97
4.02k
        OptionVendorClassPtr vendor_class;
98
4.02k
        vendor_class = OptionVendorClassPtr(new OptionVendorClass(Option::V4,
99
4.02k
            buf.begin(),
100
4.02k
            buf.end()));
101
4.02k
    }catch(...){
102
4.01k
    }
103
104
4.02k
    try {
105
        // Package parsing for 4o6
106
4.02k
        Pkt4Ptr pkt4 = Pkt4Ptr(new Pkt4(data, size));
107
4.02k
        Pkt6Ptr pkt6 = Pkt6Ptr(new Pkt6(data, size));
108
4.02k
        Pkt4o6Ptr pkt = Pkt4o6Ptr(new Pkt4o6(pkt4, pkt6));
109
4.02k
        pkt->toText();
110
4.02k
        pkt->getType();
111
4.02k
        pkt->getTransid();
112
4.02k
        pkt->unpack();
113
4.02k
        pkt->pack();
114
4.02k
        pkt->getName();
115
4.02k
        pkt->getName(fdp->ConsumeIntegral<uint8_t>());
116
4.02k
        pkt->getLabel();   
117
4.02k
        pkt->getMAC(fdp->ConsumeIntegral<uint16_t>());
118
4.02k
    } catch (...) {}
119
120
4.02k
    try {
121
        // Protocol parsing
122
4.02k
        InputBuffer buf(data, size);
123
4.02k
        Pkt4Ptr pkt = Pkt4Ptr(new Pkt4(DHCPREQUEST, 1234));
124
4.02k
        decodeEthernetHeader(buf, pkt);
125
4.02k
        decodeIpUdpHeader(buf, pkt);
126
4.02k
        calcChecksum(data, size, fdp->ConsumeIntegral<uint32_t>());
127
4.02k
    } catch (...) {}
128
129
    // OptionVendor parsing
130
4.02k
    try{
131
4.02k
        OptionBuffer buf(data, data + size);
132
4.02k
        OptionVendorPtr vendor;
133
4.02k
        vendor.reset(new OptionVendor(Option::V4, buf.begin() + 2, buf.end()));
134
4.02k
        OutputBuffer output(0);
135
4.02k
        vendor->pack(output);
136
4.02k
    }
137
4.02k
    catch (...){}
138
139
4.02k
    try {
140
        // Package parsing
141
4.02k
        Pkt4Ptr pkt = Pkt4Ptr(new Pkt4(data, size));
142
143
        // Option parsing
144
4.02k
        LibDHCP::unpackOptions4(buf, DHCP4_OPTION_SPACE, options, deferred, false);
145
13.5k
        for (auto& kv : options) {
146
13.5k
            auto opt = kv.second;
147
13.5k
            if (!opt) {
148
0
                continue;
149
0
            }
150
13.5k
            opt->getType();
151
13.5k
            opt->toText();
152
13.5k
        }
153
/*
154
        // Server initialisation
155
        srv.reset(new ControlledDhcpv4Srv());
156
        srv->init(path);
157
158
        // Process packet
159
        if (srv) {
160
            srv->processPacket(pkt);
161
            srv->processDhcp4Query(pkt, fdp->ConsumeBool());
162
        }
163
*/
164
4.02k
    } catch (const isc::Exception& e) {
165
        // Slient exceptions
166
1.94k
    }
167
168
  //  srv.reset();
169
170
    // Remove temp configuration file
171
4.02k
    fuzz::deleteTempFile(path);
172
4.02k
    delete fdp;
173
4.02k
    return 0;
174
4.02k
}