Coverage Report

Created: 2025-11-16 07:29

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
2.93k
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
44
2.93k
    if (size < 236) {
45
        // package size requires at least 236 bytes
46
15
        return 0;
47
15
    }
48
49
    // Randomly enable validatePath checking
50
2.91k
    fdp = new FuzzedDataProvider(data, size);
51
2.91k
    isc::util::file::PathChecker::enableEnforcement(fdp->ConsumeBool());
52
53
    // Initialise logging
54
2.91k
    setenv("KEA_LOGGER_DESTINATION", "/dev/null", 0);
55
2.91k
    setenv("KEA_LOCKFILE_DIR", "/tmp", 0);
56
2.91k
    setenv("KEA_PIDFILE_DIR", "/tmp", 0);
57
2.91k
    setenv("KEA_LFC_EXECUTABLE", "/bin/true", 0);
58
2.91k
    try {
59
2.91k
        isc::log::initLogger("fuzzer");
60
2.91k
        isc::process::Daemon::loggerInit("fuzzer", false);
61
2.91k
        isc::process::Daemon::setDefaultLoggerName("fuzzer");
62
2.91k
    } catch (...) {
63
        // Early exit if logging initialisation failed
64
0
        return 0;
65
0
    }
66
67
    // Create temporary configuration file
68
2.91k
    std::string path = fuzz::writeTempConfig(true);
69
2.91k
    if (path.empty()) {
70
        // Early exit if configuration file creation failed
71
0
        fuzz::deleteTempFile(path);
72
0
        return 0;
73
0
    }
74
75
2.91k
    OptionCollection options;
76
2.91k
    std::list<uint16_t> deferred;
77
2.91k
    std::unique_ptr<ControlledDhcpv4Srv> srv;
78
2.91k
    std::vector<uint8_t> buf(data, data + size);
79
80
2.91k
    try {
81
        // Package parsing
82
2.91k
        Pkt4Ptr pkt = Pkt4Ptr(new Pkt4(data, size));
83
2.91k
        pkt->toText(fdp->ConsumeBool());
84
2.91k
        pkt->getType();
85
2.91k
        pkt->getTransid();
86
2.91k
        pkt->unpack();
87
2.91k
        pkt->pack();
88
2.91k
        pkt->getName();
89
2.91k
        pkt->getName(fdp->ConsumeIntegral<uint8_t>());
90
2.91k
        pkt->getLabel();           
91
2.91k
        pkt->getMAC(fdp->ConsumeIntegral<uint16_t>());
92
2.91k
    } catch (...) {}
93
94
    // OptionVendorClass parsing
95
2.91k
    try {
96
2.91k
        OptionBuffer buf(data, data + size);
97
2.91k
        OptionVendorClassPtr vendor_class;
98
2.91k
        vendor_class = OptionVendorClassPtr(new OptionVendorClass(Option::V4,
99
2.91k
            buf.begin(),
100
2.91k
            buf.end()));
101
2.91k
    }catch(...){
102
2.90k
    }
103
104
2.91k
    try {
105
        // Package parsing for 4o6
106
2.91k
        Pkt4Ptr pkt4 = Pkt4Ptr(new Pkt4(data, size));
107
2.91k
        Pkt6Ptr pkt6 = Pkt6Ptr(new Pkt6(data, size));
108
2.91k
        Pkt4o6Ptr pkt = Pkt4o6Ptr(new Pkt4o6(pkt4, pkt6));
109
2.91k
        pkt->toText();
110
2.91k
        pkt->getType();
111
2.91k
        pkt->getTransid();
112
2.91k
        pkt->unpack();
113
2.91k
        pkt->pack();
114
2.91k
        pkt->getName();
115
2.91k
        pkt->getName(fdp->ConsumeIntegral<uint8_t>());
116
2.91k
        pkt->getLabel();   
117
2.91k
        pkt->getMAC(fdp->ConsumeIntegral<uint16_t>());
118
2.91k
    } catch (...) {}
119
120
2.91k
    try {
121
        // Protocol parsing
122
2.91k
        InputBuffer buf(data, size);
123
2.91k
        Pkt4Ptr pkt = Pkt4Ptr(new Pkt4(DHCPREQUEST, 1234));
124
2.91k
        decodeEthernetHeader(buf, pkt);
125
2.91k
        decodeIpUdpHeader(buf, pkt);
126
2.91k
        calcChecksum(data, size, fdp->ConsumeIntegral<uint32_t>());
127
2.91k
    } catch (...) {}
128
129
    // OptionVendor parsing
130
2.91k
    try{
131
2.91k
        OptionBuffer buf(data, data + size);
132
2.91k
        OptionVendorPtr vendor;
133
2.91k
        vendor.reset(new OptionVendor(Option::V4, buf.begin() + 2, buf.end()));
134
2.91k
        OutputBuffer output(0);
135
2.91k
        vendor->pack(output);
136
2.91k
    }
137
2.91k
    catch (...){}
138
139
2.91k
    try {
140
        // Package parsing
141
2.91k
        Pkt4Ptr pkt = Pkt4Ptr(new Pkt4(data, size));
142
143
        // Option parsing
144
2.91k
        LibDHCP::unpackOptions4(buf, DHCP4_OPTION_SPACE, options, deferred, false);
145
11.6k
        for (auto& kv : options) {
146
11.6k
            auto opt = kv.second;
147
11.6k
            if (!opt) {
148
0
                continue;
149
0
            }
150
11.6k
            opt->getType();
151
11.6k
            opt->toText();
152
11.6k
        }
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
2.91k
    } catch (const isc::Exception& e) {
165
        // Slient exceptions
166
1.58k
    }
167
168
  //  srv.reset();
169
170
    // Remove temp configuration file
171
2.91k
    fuzz::deleteTempFile(path);
172
2.91k
    delete fdp;
173
2.91k
    return 0;
174
2.91k
}