#!/bin/bash -eu
+
# Copyright (C) 2025 Ada Logics Ltd.
#
# This Source Code Form is subject to the terms of the Mozilla Public
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
################################################################################
+# This file is required by OSS-Fuzz.
+
# Compile log4cplus
-cd $SRC/log4cplus
+cd "${SRC}/log4cplus"
./configure --prefix=/usr --enable-static --disable-shared --with-pic
make -j"$(nproc)"
make install
# Configure flags
-cd $SRC/kea
+cd "${SRC}/kea"
export CXXFLAGS="${CXXFLAGS:-} -gdwarf-4"
export LDFLAGS="${LDFLAGS:-} -gdwarf-4"
CPP_ARGS="${CPP_ARGS} -fsanitize=fuzzer-no-link"
fi
+# shellcheck disable=SC2086
+# SC2086: Double quote to prevent globbing and word splitting.
+# Reason: we specifically want ${SANITIZER_CHOICE} to split because there may be multiple words in it.
meson setup build --prefix="$OUT" $SANITIZER_CHOICE -D cpp_std=c++17 \
-D fuzz=enabled -D tests=enabled -D crypto=openssl -D default_library=static \
-D default_both_libraries=static -D cpp_args="$CPP_ARGS" -D cpp_link_args="$LD_ARGS" \
meson compile --verbose -C build
# Package static library
-find $SRC/kea/build/src/lib -type f -name '*.o' -print0 | xargs -0 llvm-ar rcsD libkea.a
+find "${SRC}/kea/build/src/lib" -type f -name '*.o' -print0 | xargs -0 llvm-ar rcsD libkea.a
llvm-ranlib libkea.a
# Find necessary static libraries
BUILD_BASEDIR="$SRC/kea/build/src"
KEA_STATIC_LIBS="/usr/lib/liblog4cplus.a libkea.a "
-KEA_STATIC_LIBS+=$(find $BUILD_BASEDIR/bin \( -path '/src/kea/build/src/bin/dhcp4/*' -o -path '/src/kea/build/src/bin/dhcp6/*' \) -prune -o -type f -name '*.a' -print)
+KEA_STATIC_LIBS+=$(find "${BUILD_BASEDIR}/bin" \( -path '/src/kea/build/src/bin/dhcp4/*' -o -path '/src/kea/build/src/bin/dhcp6/*' \) -prune -o -type f -name '*.a' -print)
KEA_STATIC_LIBS_TEST="$KEA_STATIC_LIBS $SRC/kea/build/subprojects/googletest-1.15.2/googletest/libgtest-all.a"
-INCLUDES="-I. -I$SRC -I$SRC/kea-fuzzer -Isrc -Ibuild -Isrc/lib -Isrc/bin -Isrc/hooks -Isrc/hooks/d2 -Isrc/hooks/d2/gss_tsig "
+INCLUDES="-I. -I$SRC -I$SRC/kea/src/fuzz -Isrc -Ibuild -Isrc/lib -Isrc/bin -Isrc/hooks -Isrc/hooks/d2 -Isrc/hooks/d2/gss_tsig "
INCLUDES+="-Isrc/hooks/dhcp/pgsql -Isrc/hooks/dhcp/mysql -Isrc/hooks/dhcp/user_chk -I/usr/include/postgresql -I/usr/include/mariadb"
KEA_INCLUDES="$INCLUDES -I/src/kea/subprojects/googletest-1.15.2/googletest/include -Ifuzz"
LIBS="-lpthread -ldl -lm -lc++ -lc++abi -lssl -lcrypto -lkrb5 -lgssapi_krb5"
extra_lib="$SRC/kea/build/src/hooks/d2/gss_tsig/libddns_gss_tsig.a"
;;
esac
-
+
# fuzz_dns, fuzz_encode, and fuzz_cryptolink don't need helper_func.cc
if [ "$fuzzer" = "fuzz_dns" ] || [ "$fuzzer" = "fuzz_encode" ] || [ "$fuzzer" = "fuzz_cryptolink" ]; then
- $CXX $CXXFLAGS "$SRC/kea-fuzzer/${fuzzer}.cc" \
+ # shellcheck disable=SC2086
+ # SC2086: Double quote to prevent globbing and word splitting.
+ # Reason: we specifically want several variables to split because there may be multiple words in it.
+ $CXX $CXXFLAGS "$SRC/kea/src/fuzz/${fuzzer}.cc" \
-Wl,--start-group $KEA_STATIC_LIBS $extra_lib -Wl,--end-group \
$INCLUDES $LIBS $LIB_FUZZING_ENGINE -o "$OUT/${fuzzer}"
else
- $CXX $CXXFLAGS "$SRC/kea-fuzzer/helper_func.cc" \
- "$SRC/kea-fuzzer/${fuzzer}.cc" \
+ # shellcheck disable=SC2086
+ # SC2086: Double quote to prevent globbing and word splitting.
+ # Reason: we specifically want several variables to split because there may be multiple words in it.
+ $CXX $CXXFLAGS "$SRC/kea/src/fuzz/helper_func.cc" \
+ "$SRC/kea/src/fuzz/${fuzzer}.cc" \
-Wl,--start-group $KEA_STATIC_LIBS $extra_lib -Wl,--end-group \
$INCLUDES $LIBS $LIB_FUZZING_ENGINE -o "$OUT/${fuzzer}"
fi
- if [ -f "$SRC/kea-fuzzer/${fuzzer}.dict" ]; then
- cp $SRC/kea-fuzzer/${fuzzer}.dict $OUT
+ if [ -f "$SRC/kea/src/fuzz/${fuzzer}.dict" ]; then
+ cp "${SRC}/kea/src/fuzz/${fuzzer}.dict" "${OUT}"
fi
done
do
extra_lib=""
case "$fuzzer" in fuzz_pgsql)
- extra_lib="$SRC/kea-fuzzer/pgmock.cc "
+ extra_lib="$SRC/kea/src/fuzz/pgmock.cc "
extra_lib+="$SRC/kea/build/src/hooks/dhcp/pgsql/libdhcp_pgsql.a"
;;
esac
case "$fuzzer" in fuzz_mysql)
- extra_lib="$SRC/kea-fuzzer/mysqlmock.cc "
+ extra_lib="$SRC/kea/src/fuzz/mysqlmock.cc "
extra_lib+="$SRC/kea/build/src/hooks/dhcp/mysql/libdhcp_mysql.a"
;;
esac
case "$fuzzer" in fuzz_dhcp_pkt_process)
extra_lib="$SRC/kea/build/src/hooks/dhcp/lease_cmds/libdhcp_lease_cmds.a"
- cp $SRC/kea-fuzzer/fuzz_dhcp_pkt.dict $OUT/${fuzzer}${DHCPVER}.dict
+ cp "${SRC}/kea/src/fuzz/fuzz_dhcp_pkt.dict" "${OUT}/${fuzzer}${DHCPVER}.dict"
;;
esac
case "$fuzzer" in fuzz_hook_run_script)
extra_lib="$SRC/kea/build/src/hooks/dhcp/run_script/libdhcp_run_script.a"
- cp $SRC/kea-fuzzer/fuzz_dhcp_pkt.dict $OUT/${fuzzer}${DHCPVER}.dict
+ cp "${SRC}/kea/src/fuzz/fuzz_dhcp_pkt.dict" "${OUT}/${fuzzer}${DHCPVER}.dict"
;;
esac
case "$fuzzer" in fuzz_hook_radius)
extra_lib="$SRC/kea/build/src/hooks/dhcp/radius/libdhcp_radius.a"
- cp $SRC/kea-fuzzer/fuzz_dhcp_pkt.dict $OUT/${fuzzer}${DHCPVER}.dict
+ cp "${SRC}/kea/src/fuzz/fuzz_dhcp_pkt.dict" "${OUT}/${fuzzer}${DHCPVER}.dict"
;;
esac
case "$fuzzer" in fuzz_hook_ddns_tuning)
extra_lib="$SRC/kea/build/src/hooks/dhcp/ddns_tuning/libdhcp_ddns_tuning.a"
- cp $SRC/kea-fuzzer/fuzz_dhcp_pkt.dict $OUT/${fuzzer}${DHCPVER}.dict
+ cp "${SRC}/kea/src/fuzz/fuzz_dhcp_pkt.dict" "${OUT}/${fuzzer}${DHCPVER}.dict"
;;
esac
case "$fuzzer" in fuzz_hook_lease_query)
extra_lib="$SRC/kea/build/src/hooks/dhcp/lease_query/libdhcp_lease_query.a"
- cp $SRC/kea-fuzzer/fuzz_dhcp_pkt.dict $OUT/${fuzzer}${DHCPVER}.dict
+ cp "${SRC}/kea/src/fuzz/fuzz_dhcp_pkt.dict" "${OUT}/${fuzzer}${DHCPVER}.dict"
;;
esac
case "$fuzzer" in fuzz_hook_flex_id)
extra_lib="$SRC/kea/build/src/hooks/dhcp/flex_id/libdhcp_flex_id.a"
- cp $SRC/kea-fuzzer/fuzz_dhcp_pkt.dict $OUT/${fuzzer}${DHCPVER}.dict
+ cp "${SRC}/kea/src/fuzz/fuzz_dhcp_pkt.dict" "${OUT}/${fuzzer}${DHCPVER}.dict"
;;
esac
case "$fuzzer" in fuzz_hook_user_chk)
extra_lib="$SRC/kea/build/src/hooks/dhcp/user_chk/libdhcp_user_chk.a"
- cp $SRC/kea-fuzzer/fuzz_dhcp_pkt.dict $OUT/${fuzzer}${DHCPVER}.dict
+ cp "${SRC}/kea/src/fuzz/fuzz_dhcp_pkt.dict" "${OUT}/${fuzzer}${DHCPVER}.dict"
;;
esac
- $CXX $CXXFLAGS -Wl,--start-group "$SRC/kea-fuzzer/helper_func.cc" \
- "$SRC/kea-fuzzer/${fuzzer}${DHCPVER}.cc" $extra_lib \
+ # shellcheck disable=SC2086
+ # SC2086: Double quote to prevent globbing and word splitting.
+ # Reason: we specifically want several variables to split because there may be multiple words in it.
+ $CXX $CXXFLAGS -Wl,--start-group "$SRC/kea/src/fuzz/helper_func.cc" \
+ "$SRC/kea/src/fuzz/${fuzzer}${DHCPVER}.cc" $extra_lib \
$KEA_STATIC_LIBS $BUILD_BASEDIR/bin/dhcp$DHCPVER/libdhcp$DHCPVER.a \
-Wl,--end-group $INCLUDES $LIBS \
$LIB_FUZZING_ENGINE -o "$OUT/${fuzzer}${DHCPVER}"
- if [ -f "$SRC/kea-fuzzer/${fuzzer}.dict" ]; then
- cp $SRC/kea-fuzzer/${fuzzer}.dict $OUT/${fuzzer}${DHCPVER}.dict
+ if [ -f "$SRC/kea/src/fuzz/${fuzzer}.dict" ]; then
+ cp "${SRC}/kea/src/fuzz/${fuzzer}.dict" "${OUT}/${fuzzer}${DHCPVER}.dict"
fi
done
continue
fi
- $CXX $CXXFLAGS -Wl,--start-group "$SRC/kea/fuzz/${fuzzer}${DHCPVER}.cc" \
- $SRC/kea/fuzz/fuzz.cc $KEA_STATIC_LIBS_TEST \
+ # shellcheck disable=SC2086
+ # SC2086: Double quote to prevent globbing and word splitting.
+ # Reason: we specifically want several variables to split because there may be multiple words in it.
+ $CXX $CXXFLAGS -Wl,--start-group "$SRC/kea/src/fuzz/${fuzzer}${DHCPVER}.cc" \
+ $SRC/kea/src/fuzz/fuzz.cc $KEA_STATIC_LIBS_TEST \
$BUILD_BASEDIR/bin/dhcp$DHCPVER/libdhcp$DHCPVER.a \
$KEA_INCLUDES $LIBS $LIB_FUZZING_ENGINE -Wl,--end-group \
-o "$OUT/${fuzzer}${DHCPVER}"
fuzz_dhcp_pkt4 fuzz_dhcp_pkt6 fuzz_cc fuzz_d2 fuzz_agent \
fuzz_config_kea_dhcp4 fuzz_config_kea_dhcp6
do
- echo -e "[libfuzzer]\nmax_len=25600" > $OUT/$fuzzer.options
+ printf '[libfuzzer]\nmax_len=25600\n' > "${OUT}/${fuzzer}.options"
done
# Prepare the seeds
-zip -j $OUT/fuzz_dhcpsrv_seed_corpus.zip $SRC/kea-fuzzer/corp/*.json
-zip -j $OUT/fuzz_dhcp_parser4_seed_corpus.zip $SRC/kea-fuzzer/corp/*.json
-zip -j $OUT/fuzz_dhcp_parser6_seed_corpus.zip $SRC/kea-fuzzer/corp/*.json
-zip -j $OUT/fuzz_agent_seed_corpus.zip $SRC/kea/src/bin/agent/tests/testdata/*.json
-zip -j $OUT/fuzz_d2_seed_corpus.zip $SRC/kea/src/bin/d2/tests/testdata/*.json
+zip -j "${OUT}/fuzz_dhcpsrv_seed_corpus.zip" "${SRC}/kea/src/fuzz/corp"/*.json
+zip -j "${OUT}/fuzz_dhcp_parser4_seed_corpus.zip" "${SRC}/kea/src/fuzz/corp"/*.json
+zip -j "${OUT}/fuzz_dhcp_parser6_seed_corpus.zip" "${SRC}/kea/src/fuzz/corp"/*.json
+zip -j "${OUT}/fuzz_agent_seed_corpus.zip" "${SRC}/kea/src/bin/agent/tests/testdata"/*.json
+zip -j "${OUT}/fuzz_d2_seed_corpus.zip" "${SRC}/kea/src/bin/d2/tests/testdata"/*.json
--- /dev/null
+../../../doc/examples/kea4
\ No newline at end of file
--- /dev/null
+../../../doc/examples/kea6
\ No newline at end of file
lease_id,ip_address,subnet_id,state,valid_since,valid_until,mac_address,client_id,hostname
1,192.168.1.100,1,0,2023-10-27 10:00:00,2023-10-27 11:00:00,00:11:22:33:44:55,None,device1
-2,192.168.1.101,1,0,2023-10-27 10:05:00,2023-10-27 11:05:00,AA:BB:CC:DD:EE:FF,None,device2
\ No newline at end of file
+2,192.168.1.101,1,0,2023-10-27 10:05:00,2023-10-27 11:05:00,AA:BB:CC:DD:EE:FF,None,device2
--- /dev/null
+# Copy corp to build directory so that tests can find it.
+current_source_dir = meson.current_source_dir()
+command = run_command(GRABBER, current_source_dir, '*', check: true)
+foreach j : command.stdout().strip().split('\n')
+ configure_file(input: j, output: j, copy: true)
+endforeach
137,Renske,Ladwig,RLADWIG,650.121.1234,14-JUL-03,ST_CLERK,3600, - ,123,50
138,Stephen,Stiles,SSTILES,650.121.2034,26-OCT-05,ST_CLERK,3200, - ,123,50
139,John,Seo,JSEO,650.121.2019,12-FEB-06,ST_CLERK,2700, - ,123,50
-140,Joshua,Patel,JPATEL,650.121.1834,06-APR-06,ST_CLERK,2500, - ,123,50
\ No newline at end of file
+140,Joshua,Patel,JPATEL,650.121.1834,06-APR-06,ST_CLERK,2500, - ,123,50
{"web-app": {
- "servlet": [
+ "servlet": [
{
"servlet-name": "cofaxCDS",
"servlet-class": "org.cofax.cds.CDSServlet",
{
"servlet-name": "cofaxAdmin",
"servlet-class": "org.cofax.cds.AdminServlet"},
-
+
{
"servlet-name": "fileServlet",
"servlet-class": "org.cofax.cds.FileServlet"},
"cofaxAdmin": "/admin/*",
"fileServlet": "/static/*",
"cofaxTools": "/tools/*"},
-
+
"taglib": {
"taglib-uri": "cofax.tld",
"taglib-location": "/WEB-INF/tlds/cofax.tld"}}}
"dislikes": ["cookies"]
}
}
-]
\ No newline at end of file
+]
--- /dev/null
+// Copyright (C) 2026 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+// This file should contain only empty LLVMFuzzer.* functions for harnesses contributed externally that did not define
+// them to begin with.
+
+#include <config.h>
+#include <fuzz.h>
+
+int
+LLVMFuzzerInitialize() {
+ return 0;
+}
+
+int
+LLVMFuzzerTearDown() {
+ return 0;
+}
}
FuzzedDataProvider fdp(data, size);
-
+
// Choose which crypto operation to test
uint8_t path = fdp.ConsumeIntegralInRange<uint8_t>(0, 9);
-
+
// Pick a hash algorithm
HashAlgorithm hash_alg = fdp.PickValueInArray({
HashAlgorithm::MD5,
HashAlgorithm::SHA384,
HashAlgorithm::SHA512
});
-
+
try {
switch (path) {
case 0: {
}
break;
}
-
+
case 1: {
// Test Hash with multiple updates
Hash* hash = CryptoLink::getCryptoLink().createHash(hash_alg);
}
break;
}
-
+
case 2: {
// Test Hash with OutputBuffer
Hash* hash = CryptoLink::getCryptoLink().createHash(hash_alg);
}
break;
}
-
+
case 3: {
// Test Hash with void* result
Hash* hash = CryptoLink::getCryptoLink().createHash(hash_alg);
}
break;
}
-
+
case 4: {
// Test HMAC creation and signing
size_t secret_len = fdp.ConsumeIntegralInRange<size_t>(1, 256);
if (secret.empty()) {
secret.push_back(0); // Ensure non-empty secret
}
-
+
HMAC* hmac = CryptoLink::getCryptoLink().createHMAC(
secret.data(), secret.size(), hash_alg
);
}
break;
}
-
+
case 5: {
// Test HMAC with multiple updates
size_t secret_len = fdp.ConsumeIntegralInRange<size_t>(1, 256);
if (secret.empty()) {
secret.push_back(0);
}
-
+
HMAC* hmac = CryptoLink::getCryptoLink().createHMAC(
secret.data(), secret.size(), hash_alg
);
}
break;
}
-
+
case 6: {
// Test HMAC with OutputBuffer
size_t secret_len = fdp.ConsumeIntegralInRange<size_t>(1, 256);
if (secret.empty()) {
secret.push_back(0);
}
-
+
HMAC* hmac = CryptoLink::getCryptoLink().createHMAC(
secret.data(), secret.size(), hash_alg
);
}
break;
}
-
+
case 7: {
// Test HMAC verification
size_t secret_len = fdp.ConsumeIntegralInRange<size_t>(1, 256);
if (secret.empty()) {
secret.push_back(0);
}
-
+
HMAC* hmac = CryptoLink::getCryptoLink().createHMAC(
secret.data(), secret.size(), hash_alg
);
if (!input_data.empty()) {
hmac->update(input_data.data(), input_data.size());
}
-
+
// Generate signature
std::vector<uint8_t> signature = hmac->sign(hmac->getOutputLength());
-
+
// Verify with same data (should succeed)
HMAC* verify_hmac = CryptoLink::getCryptoLink().createHMAC(
secret.data(), secret.size(), hash_alg
}
break;
}
-
+
case 8: {
// Test HMAC with long secret (should be hashed)
size_t secret_len = fdp.ConsumeIntegralInRange<size_t>(256, 1024);
if (secret.size() < 64) {
secret.resize(64, 0x42); // Pad to ensure long secret
}
-
+
HMAC* hmac = CryptoLink::getCryptoLink().createHMAC(
secret.data(), secret.size(), hash_alg
);
}
break;
}
-
+
case 9: {
// Test RNG generation
size_t rng_len = fdp.ConsumeIntegralInRange<size_t>(0, 1024);
std::vector<uint8_t> random_data = isc::cryptolink::random(rng_len);
-
+
// Test Qid generation
uint16_t qid = isc::cryptolink::generateQid();
(void)qid; // Use the variable
} catch (const std::exception&) {
// Catch any standard library exceptions
}
-
+
return 0;
}
// Subnets6ListConfigParser
try {
ElementPtr elem = fuzz::parseJSON(full_payload);
- SrvConfigPtr srv = SrvConfigPtr(new SrvConfig());
+ SrvConfigPtr srvconf = SrvConfigPtr(new SrvConfig());
Subnets6ListConfigParser parser(fdp.ConsumeBool());
- parser.parse(srv, elem, fdp.ConsumeBool());
+ parser.parse(srvconf, elem, fdp.ConsumeBool());
} catch (const isc::Exception&) {
// Known exceptions
}
// CompatibilityParser
try {
ElementPtr elem = fuzz::parseJSON(full_payload);
- SrvConfig srv = SrvConfig();
+ SrvConfig srvconf = SrvConfig();
CompatibilityParser parser = CompatibilityParser();
- parser.parse(elem, srv);
+ parser.parse(elem, srvconf);
} catch (const isc::Exception&) {
// Known exceptions
}
// Subnets6ListConfigParser
try {
ElementPtr elem = fuzz::parseJSON(full_payload);
- SrvConfigPtr srv = SrvConfigPtr(new SrvConfig());
+ SrvConfigPtr srvconf = SrvConfigPtr(new SrvConfig());
Subnets6ListConfigParser parser(fdp.ConsumeBool());
- parser.parse(srv, elem, fdp.ConsumeBool());
+ parser.parse(srvconf, elem, fdp.ConsumeBool());
} catch (const isc::Exception&) {
// Known exceptions
}
// CompatibilityParser
try {
ElementPtr elem = fuzz::parseJSON(full_payload);
- SrvConfig srv = SrvConfig();
+ SrvConfig srvconf = SrvConfig();
CompatibilityParser parser = CompatibilityParser();
- parser.parse(elem, srv);
+ parser.parse(elem, srvconf);
} catch (const isc::Exception&) {
// Known exceptions
}
return 0;
}
-
pkt->pack();
pkt->getName();
pkt->getName(fdp->ConsumeIntegral<uint8_t>());
- pkt->getLabel();
+ pkt->getLabel();
pkt->getMAC(fdp->ConsumeIntegral<uint16_t>());
} catch (...) {}
// OptionVendorClass parsing
try {
- OptionBuffer buf(data, data + size);
+ OptionBuffer optbuf(data, data + size);
OptionVendorClassPtr vendor_class;
vendor_class = OptionVendorClassPtr(new OptionVendorClass(Option::V4,
- buf.begin(),
- buf.end()));
+ optbuf.begin(),
+ optbuf.end()));
}catch(...){
}
pkt->pack();
pkt->getName();
pkt->getName(fdp->ConsumeIntegral<uint8_t>());
- pkt->getLabel();
+ pkt->getLabel();
pkt->getMAC(fdp->ConsumeIntegral<uint16_t>());
} catch (...) {}
try {
// Protocol parsing
- InputBuffer buf(data, size);
+ InputBuffer inbuf(data, size);
Pkt4Ptr pkt = Pkt4Ptr(new Pkt4(DHCPREQUEST, 1234));
- decodeEthernetHeader(buf, pkt);
- decodeIpUdpHeader(buf, pkt);
+ decodeEthernetHeader(inbuf, pkt);
+ decodeIpUdpHeader(inbuf, pkt);
calcChecksum(data, size, fdp->ConsumeIntegral<uint32_t>());
} catch (...) {}
// OptionVendor parsing
try{
- OptionBuffer buf(data, data + size);
+ OptionBuffer outbuf(data, data + size);
OptionVendorPtr vendor;
- vendor.reset(new OptionVendor(Option::V4, buf.begin() + 2, buf.end()));
+ vendor.reset(new OptionVendor(Option::V4, outbuf.begin() + 2, outbuf.end()));
OutputBuffer output(0);
vendor->pack(output);
}
// OptionVendor parsing
try {
- OptionBuffer buf(data, data + size);
+ OptionBuffer optbuf(data, data + size);
OptionVendorClassPtr vendor_class;
vendor_class = OptionVendorClassPtr(new OptionVendorClass(Option::V6,
- buf.begin(),
- buf.end()));
+ optbuf.begin(),
+ optbuf.end()));
}catch(...){}
try {
hrp.parse(SubnetID(10), elem, fdp.ConsumeBool());
} catch (const isc::Exception&) {
// Slient exceptions
- }
-
+ }
+
return 0;
}
}
FuzzedDataProvider fdp(data, size);
-
+
// Get a choice for which fuzzing path to take
uint8_t choice = fdp.ConsumeIntegral<uint8_t>();
-
+
// Reserve some data for different operations
std::vector<uint8_t> wire_data = fdp.ConsumeBytes<uint8_t>(fdp.remaining_bytes() / 2);
std::string string_data = fdp.ConsumeRemainingBytesAsString();
-
+
// Fuzz DNS Name parsing from string
if (choice % 8 == 0 && !string_data.empty()) {
try {
std::string text = name.toText();
OutputBuffer buffer(0);
name.toWire(buffer);
-
+
// Try splitting at different positions
if (name.getLabelCount() > 0) {
Name stripped = name.split(0);
Name reversed = name.reverse();
}
-
+
// Try comparison operations
Name root = Name::ROOT_NAME();
name.compare(root);
-
+
} catch (const std::exception&) {
// Ignore exceptions from operations
}
// Ignore exceptions from parsing
}
}
-
+
// Fuzz DNS Name parsing from wire format
if (choice % 8 == 1 && !wire_data.empty()) {
try {
InputBuffer buffer(&wire_data[0], wire_data.size());
Name name(buffer);
-
+
// Try operations on the parsed name
try {
name.toText();
// Ignore exceptions from parsing
}
}
-
+
// Fuzz DNS Message parsing from wire
if (choice % 8 == 2 && !wire_data.empty()) {
try {
InputBuffer buffer(&wire_data[0], wire_data.size());
Message message(Message::PARSE);
message.fromWire(buffer);
-
+
// Try various Message operations
try {
message.getHeaderFlag(Message::HEADERFLAG_AA);
message.getRcode();
message.getQid();
message.getRRCount(Message::SECTION_ANSWER);
-
+
// Try iterating through sections
for (int sec = Message::SECTION_QUESTION;
sec <= Message::SECTION_ADDITIONAL;
// Ignore iteration exceptions
}
}
-
+
// Try rendering back to wire
MessageRenderer renderer;
try {
} catch (const std::exception&) {
// Ignore rendering exceptions
}
-
+
} catch (const std::exception&) {
// Ignore operation exceptions
}
// Ignore parsing exceptions
}
}
-
+
// Fuzz Question parsing
if (choice % 8 == 3 && !wire_data.empty()) {
try {
InputBuffer buffer(&wire_data[0], wire_data.size());
Question question(buffer);
-
+
try {
question.toText();
question.getName();
question.getType();
question.getClass();
-
+
OutputBuffer out_buffer(0);
question.toWire(out_buffer);
} catch (const std::exception&) {
// Ignore parsing exceptions
}
}
-
+
// Fuzz RRset operations
if (choice % 8 == 4 && !string_data.empty() && !wire_data.empty()) {
try {
Name name(string_data);
- RRsetPtr rrset = RRsetPtr(new RRset(name, RRClass::IN(),
+ RRsetPtr rrset = RRsetPtr(new RRset(name, RRClass::IN(),
RRType::A(), RRTTL(3600)));
-
+
// Try parsing RDATA from wire
try {
InputBuffer buffer(&wire_data[0], wire_data.size());
if (wire_data.size() >= 4) {
- rdata::ConstRdataPtr rdata =
- rdata::createRdata(RRType::A(), RRClass::IN(),
+ rdata::ConstRdataPtr rdata =
+ rdata::createRdata(RRType::A(), RRClass::IN(),
buffer, wire_data.size());
rrset->addRdata(rdata);
}
} catch (const std::exception&) {
// Ignore RDATA parsing exceptions
}
-
+
// Try RRset operations
try {
rrset->toText();
rrset->getRdataCount();
-
+
OutputBuffer out_buffer(0);
rrset->toWire(out_buffer);
} catch (const std::exception&) {
// Ignore exceptions
}
}
-
+
// Fuzz TSIG operations
if (choice % 8 == 5 && !string_data.empty() && wire_data.size() >= 16) {
try {
// Try creating a TSIG key
TSIGKey key(string_data + ":secret");
-
+
// Try creating TSIG RDATA and then a TSIG record
try {
InputBuffer buffer(&wire_data[0], wire_data.size());
// Try to parse TSIG RDATA
- rdata::ConstRdataPtr rdata =
- rdata::createRdata(RRType::TSIG(), RRClass::ANY(),
+ rdata::ConstRdataPtr rdata =
+ rdata::createRdata(RRType::TSIG(), RRClass::ANY(),
buffer, wire_data.size());
- const rdata::any::TSIG& tsig_rdata =
+ const rdata::any::TSIG& tsig_rdata =
dynamic_cast<const rdata::any::TSIG&>(*rdata);
-
+
// Create a TSIGRecord
Name key_name(string_data);
TSIGRecord tsig(key_name, tsig_rdata);
tsig.toText();
-
+
OutputBuffer out_buffer(0);
tsig.toWire(out_buffer);
} catch (const std::exception&) {
// Ignore TSIG parsing exceptions
}
-
+
// Try TSIG context operations (sign operation is public)
try {
TSIGContext ctx(key);
// Ignore key creation exceptions
}
}
-
+
// Fuzz MasterLexer with string input
if (choice % 8 == 6 && !string_data.empty()) {
try {
std::istringstream iss(string_data);
MasterLexer lexer;
lexer.pushSource(iss);
-
+
// Try tokenizing (loop until we hit EOF token)
for (int i = 0; i < 100; ++i) {
try {
const MasterToken& token = lexer.getNextToken();
-
+
// Stop if we hit EOF
if (token.getType() == MasterToken::END_OF_FILE) {
break;
}
-
+
// Access token properties based on type
if (token.getType() == MasterToken::STRING ||
token.getType() == MasterToken::QSTRING) {
// Ignore lexer exceptions
}
}
-
+
// Fuzz Message rendering operations
if (choice % 8 == 7 && !string_data.empty()) {
try {
message.setQid(fdp.ConsumeIntegral<uint16_t>());
message.setOpcode(Opcode::QUERY());
message.setRcode(Rcode::NOERROR());
-
+
// Try setting various flags
- message.setHeaderFlag(Message::HEADERFLAG_AA,
+ message.setHeaderFlag(Message::HEADERFLAG_AA,
fdp.ConsumeBool());
- message.setHeaderFlag(Message::HEADERFLAG_RD,
+ message.setHeaderFlag(Message::HEADERFLAG_RD,
fdp.ConsumeBool());
- message.setHeaderFlag(Message::HEADERFLAG_RA,
+ message.setHeaderFlag(Message::HEADERFLAG_RA,
fdp.ConsumeBool());
-
+
// Try adding a question
try {
Name qname(string_data);
- QuestionPtr question(new Question(qname, RRClass::IN(),
+ QuestionPtr question(new Question(qname, RRClass::IN(),
RRType::A()));
message.addQuestion(question);
} catch (const std::exception&) {
// Ignore question addition exceptions
}
-
+
// Try rendering
try {
MessageRenderer renderer;
// Ignore message creation exceptions
}
}
-
+
return 0;
}
}
FuzzedDataProvider fdp(data, size);
-
+
// Choose which encoding/decoding path to test
uint8_t path = fdp.ConsumeIntegralInRange<uint8_t>(0, 11);
-
+
std::vector<uint8_t> binary_data;
std::string encoded_str;
std::vector<uint8_t> decoded_output;
-
+
switch (path) {
case 0: {
// Test Base64 encoding from binary data
}
break;
}
-
+
case 1: {
// Test Base64 decoding from string
try {
}
break;
}
-
+
case 2: {
// Test Base32Hex encoding from binary data
try {
}
break;
}
-
+
case 3: {
// Test Base32Hex decoding from string
try {
}
break;
}
-
+
case 4: {
// Test Base16 (hex) encoding from binary data
try {
}
break;
}
-
+
case 5: {
// Test Base16 (hex) decoding from string
try {
}
break;
}
-
+
case 6: {
// Test Base64 with various padding scenarios
try {
}
break;
}
-
+
case 7: {
// Test Base32Hex with various padding scenarios
try {
}
break;
}
-
+
case 8: {
// Test mixed case Base64 (should be case-sensitive)
try {
}
break;
}
-
+
case 9: {
// Test mixed case Base32Hex (case-insensitive)
try {
}
break;
}
-
+
case 10: {
// Test Base16 with mixed case (case-insensitive)
try {
}
break;
}
-
+
case 11: {
// Test encoding/decoding with whitespace injection
try {
char ws = fdp.PickValueInArray({' ', '\t', '\n', '\r'});
test_str.insert(pos, 1, ws);
}
-
+
// Try decoding with all encoders
try { decodeBase64(test_str, decoded_output); } catch (...) {}
try { decodeBase32Hex(test_str, decoded_output); } catch (...) {}
break;
}
}
-
+
return 0;
}
std::string tsig_rdata_txt = fdp.ConsumeRandomLengthString(1024);
std::string owner_txt = fdp.ConsumeRandomLengthString(128);
const uint16_t qid = fdp.ConsumeIntegral<uint16_t>();
- const bool do_chunked = fdp.ConsumeBool();
// Target correct key sign and verify
try {
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
////////////////////////////////////////////////////////////////////////////////
+
+#include <config.h>
+
#include <cstddef>
#include <cstdint>
#include <string>
// Target CSVRow
try {
CSVRow row(payload, delim[0]);
- for (int i = 0; i < row.getValuesCount(); i++) {
+ for (size_t i = 0; i < row.getValuesCount(); i++) {
row.readAt(i);
row.readAtEscaped(i);
}
return 0;
}
-
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
////////////////////////////////////////////////////////////////////////////////
+
+#include <config.h>
+
#include "helper_func.h"
#include <cstdlib>
+++ /dev/null
-../../../../doc/examples/kea4
\ No newline at end of file
+++ /dev/null
-../../../../doc/examples/kea6
\ No newline at end of file
+++ /dev/null
-0a
\ No newline at end of file
+++ /dev/null
-{
- "command": "config-get"
-}
+++ /dev/null
-{
- "command": "config-get",
- "service": [ "dhcp4" ]
-}
+++ /dev/null
-0a
\ No newline at end of file
+++ /dev/null
-{
- "a": 1
-}
+++ /dev/null
-{
- "command": "config-get"
-}
+++ /dev/null
-{
- "command": "config-get",
- "service": [ "dhcp6" ]
-}
+++ /dev/null
-0a
\ No newline at end of file
+++ /dev/null
-{
- "a": 1
-}
+++ /dev/null
-0a
\ No newline at end of file
+++ /dev/null
-0a
\ No newline at end of file
+++ /dev/null
-{
- "command": "config-get"
-}
+++ /dev/null
-{
- "command": "config-get",
- "service": [ "dhcp4" ]
-}
+++ /dev/null
-0a
\ No newline at end of file
+++ /dev/null
-{
- "a": 1
-}
+++ /dev/null
-{
- "command": "config-get"
-}
+++ /dev/null
-{
- "command": "config-get",
- "service": [ "dhcp6" ]
-}
+++ /dev/null
-0a
\ No newline at end of file
+++ /dev/null
-{
- "a": 1
-}
+++ /dev/null
-#!/bin/sh
-
-set -eu
-
-# Destdir is set everytime the installation happens through meson or ninja even when --destdir is not passed.
-# Set target path to prefix in case someone wants to run this script directly.
-target_path='@PREFIX@'
-if test -n "${MESON_INSTALL_DESTDIR_PREFIX+x}"; then
- target_path="${MESON_INSTALL_DESTDIR_PREFIX}"
-fi
-
-mkdir -p "${target_path}/share/kea/fuzz"
-cp -r '@current_build_dir@/input'/* "${target_path}/share/kea/fuzz"
current_build_dir = meson.current_build_dir()
current_source_dir = meson.current_source_dir()
-foreach i : [
- 'fuzz_config_kea_dhcp4',
- 'fuzz_config_kea_dhcp6',
- 'fuzz_http_endpoint_kea_dhcp4',
- 'fuzz_http_endpoint_kea_dhcp6',
- 'fuzz_packets_kea_dhcp4',
- 'fuzz_packets_kea_dhcp6',
- 'fuzz_unix_socket_kea_dhcp4',
- 'fuzz_unix_socket_kea_dhcp6',
- 'fuzz_config_kea_dhcp4/doc-examples',
- 'fuzz_config_kea_dhcp6/doc-examples',
-]
- command = run_command(GRABBER, f'input/@i@', '*', check: true)
- foreach j : command.stdout().strip().split('\n')
- # configure_file doesn't work with path segments in the output, so let
- # us simulate it with commands.
- run_command(
- ['mkdir', '-p', f'@TOP_BUILD_DIR@/fuzz/input/@i@'],
- check: true,
- )
- run_command(
- ['cp', f'input/@i@/@j@', f'@TOP_BUILD_DIR@/fuzz/input/@i@/@j@'],
- check: true,
- )
- endforeach
-
-endforeach
-
-fuzz_sources = ['fuzz.cc', 'fuzz.h', 'main.cc']
+fuzz_sources = ['fuzz.cc', 'fuzz.h']
cpp_flags = [
f'-DKEA_LFC_INSTALLATION="@KEA_LFC_INSTALLED@"',
f'-DKEA_LFC_SOURCES="@KEA_LFC_BUILT@"',
]
-includes = [include_directories('.')] + INCLUDES
+# The include paths are a bit invasive, but if we wanted to only have "../hooks" we would need to
+# tweak the include paths in the hooks themselves either to be referenced from "src" or
+# "src/hooks" or to have quotes instead of angled brackets and that is more work.
+includes = [
+ include_directories('.'),
+ include_directories('../hooks'),
+ include_directories('../hooks/d2/gss_tsig'),
+ include_directories('../hooks/dhcp/mysql'),
+ include_directories('../hooks/dhcp/pgsql'),
+ include_directories('../hooks/dhcp/user_chk'),
+] + INCLUDES
fuzz_lib = static_library(
'fuzz_lib',
link_with: LIBS_BUILT_SO_FAR,
)
-FUZZER_EXECUTABLES = []
+FUZZING_HARNESSES = []
foreach i : [
'fuzz_config_kea_dhcp4',
'fuzz_packets_kea_dhcp4',
'fuzz_unix_socket_kea_dhcp4',
]
- FUZZER_EXECUTABLES += executable(
+ FUZZING_HARNESSES += static_library(
i,
f'@i@.cc',
fuzz_sources,
dependencies: [CRYPTO_DEP, GTEST_DEP],
include_directories: includes,
link_with: [dhcp4_lib, kea_testutils_lib, fuzz_lib] + LIBS_BUILT_SO_FAR,
- install: true,
- install_dir: SBINDIR,
- install_rpath: INSTALL_RPATH,
build_rpath: BUILD_RPATH,
)
endforeach
+
foreach i : [
'fuzz_config_kea_dhcp6',
'fuzz_http_endpoint_kea_dhcp6',
'fuzz_packets_kea_dhcp6',
'fuzz_unix_socket_kea_dhcp6',
]
- FUZZER_EXECUTABLES += executable(
+ FUZZING_HARNESSES += static_library(
i,
f'@i@.cc',
fuzz_sources,
dependencies: [CRYPTO_DEP, GTEST_DEP],
include_directories: includes,
link_with: [dhcp6_lib, kea_testutils_lib, fuzz_lib] + LIBS_BUILT_SO_FAR,
- install: true,
- install_dir: SBINDIR,
- install_rpath: INSTALL_RPATH,
build_rpath: BUILD_RPATH,
)
endforeach
+# From external contribution.
+foreach i : [
+ 'fuzz_agent',
+ 'fuzz_cc',
+ 'fuzz_crypto',
+ 'fuzz_cryptolink',
+ 'fuzz_d2',
+ 'fuzz_dhcp_parser4',
+ 'fuzz_dhcp_parser6',
+ 'fuzz_dhcp_pkt4',
+ 'fuzz_dhcp_pkt6',
+ 'fuzz_dhcp_pkt_process4',
+ 'fuzz_dhcp_pkt_process6',
+ 'fuzz_dhcpsrv',
+ 'fuzz_dhcpsrv_csv_lease',
+ 'fuzz_dns',
+ 'fuzz_encode',
+ 'fuzz_eval4',
+ 'fuzz_eval6',
+ 'fuzz_hook_ddns_tuning4',
+ 'fuzz_hook_ddns_tuning6',
+ 'fuzz_hook_flex_id4',
+ 'fuzz_hook_flex_id6',
+ 'fuzz_hook_lease_query4',
+ 'fuzz_hook_lease_query6',
+ 'fuzz_hook_radius4',
+ 'fuzz_hook_radius6',
+ 'fuzz_hook_run_script4',
+ 'fuzz_hook_run_script6',
+ 'fuzz_hook_tsig',
+ 'fuzz_hook_user_chk4',
+ 'fuzz_hook_user_chk6',
+ 'fuzz_http',
+ 'fuzz_ioaddress',
+ 'fuzz_mysql4',
+ 'fuzz_mysql6',
+ 'fuzz_pgsql4',
+ 'fuzz_pgsql6',
+ 'fuzz_util',
+]
+ FUZZING_HARNESSES += static_library(
+ i,
+ f'@i@.cc',
+ 'empty_llvm_functions.cc',
+ 'helper_func.cc',
+ 'mysqlmock.cc',
+ 'pgmock.cc',
+ fuzz_sources,
+ cpp_args: cpp_flags,
+ dependencies: [MYSQL_DEP, POSTGRESQL_DEP, CRYPTO_DEP, GTEST_DEP],
+ include_directories: includes,
+ link_with: [
+ agent_lib,
+ d2_lib,
+ ddns_gss_tsig_lib,
+ dhcp_lease_query_lib,
+ dhcp_flex_id_lib,
+ dhcp_ddns_tuning_lib,
+ dhcp_lease_cmds_lib,
+ dhcp_mysql_lib,
+ dhcp_pgsql_lib,
+ dhcp_radius_lib,
+ dhcp_run_script_lib,
+ dhcp_user_chk_lib,
+ dhcp4_lib,
+ dhcp6_lib,
+ kea_testutils_lib,
+ fuzz_lib,
+ ] + LIBS_BUILT_SO_FAR,
+ build_rpath: BUILD_RPATH,
+ )
+endforeach
+
+subdir('corp')
subdir('tests')
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
////////////////////////////////////////////////////////////////////////////////
+
+#include <config.h>
+
#include <fuzzer/FuzzedDataProvider.h>
-#include <mariadb/mysql.h>
+#include <mysql.h>
#include <stdint.h>
#include <string.h>
return h.find(n) != std::string::npos;
}
-static MYSQL_STMT* make_stmt() {
- auto s = new StmtState();
- s->mysql = reinterpret_cast<MYSQL*>(0x1);
- g_live_stmts.push_back(s);
- return reinterpret_cast<MYSQL_STMT*>(s);
-}
-
static StmtState* SS(MYSQL_STMT* st) {
if (!st) {
return nullptr;
}
extern "C" {
- int mysql_server_init(int argc, char **argv, char **groups) {
+ int mysql_server_init(int /* argc */, char ** /* argv */, char ** /* groups */) {
return 0;
}
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
////////////////////////////////////////////////////////////////////////////////
+
+#include <config.h>
+
#include <fuzzer/FuzzedDataProvider.h>
#include <cstdlib>
return const_cast<char*>("");
}
- PGresult* PQexec(PGconn* , const char* query) {
+ PGresult* PQexec(PGconn* , const char* /* query */) {
if (g_fdp->ConsumeBool()) {
return make_version_result();
}
return make_fuzz_result();
}
- PGresult* PQexecParams(PGconn*, const char* cmd, int, const void*,
+ PGresult* PQexecParams(PGconn*, const char* /* cmd */, int, const void*,
const char* const*, const int*, const int*, int) {
if (g_fdp->ConsumeBool()) {
return make_version_result();
return make_command_ok_result();
}
- PGresult* PQexecPrepared(PGconn*, const char* name, int, const char* const*,
+ PGresult* PQexecPrepared(PGconn*, const char* /* name */, int, const char* const*,
const int*, const int*, int) {
if (g_fdp->ConsumeBool()) {
return make_version_result();
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+// This file should contain all the symbols which are added by OSS-Fuzz like the main function and the LLVMFuzzer.*
+// functions.
+
#include <config.h>
#include <exceptions/exceptions.h>
// Determine some paths.
Path const this_binary(argv[0]);
- string ancestor_path(this_binary.parentPath());
+ string const ancestor_path(this_binary.parentPath());
string const filename(this_binary.filename());
stringstream ss;
- ss << ancestor_path << "/input/" << filename;
+ ss << ancestor_path << "/../corp";
Path const p(ss.str());
// Print start header.
string directory(p.str());
if (exists(directory)) {
// Recursively take all regular files as input.
+ // This means each fuzzing harness runs against each input even if the input is meant for a different fuzzing
+ // harness. A bit chaotic, but let us call it limited fuzzing.
list<string> files;
struct dirent *dp;
-foreach f : FUZZER_EXECUTABLES
+foreach f : FUZZING_HARNESSES
+ n = f.name()
+ t = executable(
+ f'test_@n@',
+ 'main.cc',
+ include_directories: [include_directories('..')] + INCLUDES,
+ link_with: [f],
+ build_rpath: BUILD_RPATH,
+ )
test(
- f.name(),
- f,
+ t.name(),
+ t,
is_parallel: false,
priority: -1,
)