Skip to content

Commit

Permalink
Add several fuzz targets built when linux/mac are built with clang (#…
Browse files Browse the repository at this point in the history
…20285)

* Add a fuzzing target for the tlv reader

* Restyle

* Also enable asan for this fuzzing library

* Add clang tests to targets, add build default to main build file

* Restyle

* Fuzzert for some chip credentials calls

* A few more fuzzing calls on various things taking a bytespan

* Restyle

* Add a fuzz target for minmdns packet parsing

* update build target after new test clang was added as a build target

* Reorganize fuzz target rules into a separate file, so that build logic is shared

* Restyle
  • Loading branch information
andy31415 authored Jul 5, 2022
1 parent 61041e7 commit 19132a3
Show file tree
Hide file tree
Showing 10 changed files with 240 additions and 0 deletions.
17 changes: 17 additions & 0 deletions BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,12 @@ import("$dir_pw_build/python.gni")
# This build file should not be used in superproject builds.
assert(chip_root == "//")

import("${chip_root}/build/chip/fuzz_test.gni")
import("${chip_root}/build/chip/tests.gni")
import("${chip_root}/build/chip/tools.gni")

import("${build_root}/config/compiler/compiler.gni")

import("//src/crypto/crypto.gni")

if (current_toolchain != "${dir_pw_toolchain}/default:default") {
Expand All @@ -40,6 +43,16 @@ if (current_toolchain != "${dir_pw_toolchain}/default:default") {
enable_pylib = false
}

if (enable_fuzz_test_targets) {
group("fuzz_tests") {
deps = [
"${chip_root}/src/credentials/tests:fuzz-chip-cert",
"${chip_root}/src/lib/core/tests:fuzz-tlv-reader",
"${chip_root}/src/lib/dnssd/minimal_mdns/tests:fuzz-minmdns-packet-parsing",
]
}
}

# Python packages for supporting specific targets.
pw_python_group("python_packages") {
python_deps = [
Expand Down Expand Up @@ -88,6 +101,10 @@ if (current_toolchain != "${dir_pw_toolchain}/default:default") {
"${nlunit_test_root}:nlunit-test",
]

if (enable_fuzz_test_targets) {
deps += [ "//:fuzz_tests" ]
}

if (chip_device_platform != "none") {
deps += [ "${chip_root}/src/app/server" ]
}
Expand Down
64 changes: 64 additions & 0 deletions build/chip/fuzz_test.gni
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# Copyright (c) 2020 Project CHIP Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import("//build_overrides/build.gni")
import("//build_overrides/chip.gni")
import("${build_root}/config/compiler/compiler.gni")

declare_args() {
enable_fuzz_test_targets =
is_clang && (current_os == "linux" || current_os == "mac")
}

# Define a fuzz target for chip.
#
# Fuzz generally only apply on the following environments:
# - linux and mac host builds when using clang
#
# Sample usage
#
# chip_fuzz_target("fuzz-target-name") {
# sources = [
# "FuzzTarget.cpp", # Fuzz target
# ]
#
# public_deps = [
# "${chip_root}/src/lib/foo", # add dependencies here
# "${nlunit_test_root}:nlunit-test",
# ]
# }
#
#
template("chip_fuzz_target") {
if (enable_fuzz_test_targets) {
executable(target_name) {
forward_variables_from(invoker, "*")

if (defined(public_configs)) {
public_configs += [
"//build/config/compiler:libfuzzer_fuzzing",
"//build/config/compiler:sanitize_address",
]
} else {
public_configs = [
"//build/config/compiler:libfuzzer_fuzzing",
"//build/config/compiler:sanitize_address",
]
}
if (!defined(oubput_dir)) {
output_dir = "${root_out_dir}/tests"
}
}
}
}
1 change: 1 addition & 0 deletions scripts/build/build/targets.py
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,7 @@ def HostTargets():
test_target = Target(HostBoard.NATIVE.PlatformName(), HostBuilder)
for board in [HostBoard.NATIVE, HostBoard.FAKE]:
yield test_target.Extend(board.BoardName() + '-tests', board=board, app=HostApp.TESTS)
yield test_target.Extend(board.BoardName() + '-tests-clang', board=board, app=HostApp.TESTS, use_clang=True)


def Esp32Targets():
Expand Down
12 changes: 12 additions & 0 deletions scripts/build/testdata/build_linux_on_x64.txt
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,9 @@ PKG_CONFIG_PATH="SYSROOT_AARCH64/lib/aarch64-linux-gnu/pkgconfig" \
# Generating linux-fake-tests
gn gen --check --fail-on-unused-args --export-compile-commands --root={root} '--args=chip_build_tests=true custom_toolchain="//build/toolchain/fake:fake_x64_gcc" chip_link_tests=true chip_device_platform="fake" chip_fake_platform=true' {out}/linux-fake-tests

# Generating linux-fake-tests-clang
gn gen --check --fail-on-unused-args --export-compile-commands --root={root} '--args=is_clang=true chip_build_tests=true custom_toolchain="//build/toolchain/fake:fake_x64_gcc" chip_link_tests=true chip_device_platform="fake" chip_fake_platform=true' {out}/linux-fake-tests-clang

# Generating linux-x64-address-resolve-tool
gn gen --check --fail-on-unused-args --export-compile-commands --root={root} {out}/linux-x64-address-resolve-tool

Expand Down Expand Up @@ -231,6 +234,9 @@ gn gen --check --fail-on-unused-args --export-compile-commands --root={root}/exa
# Generating linux-x64-tests
gn gen --check --fail-on-unused-args --export-compile-commands --root={root} --args=chip_build_tests=true {out}/linux-x64-tests

# Generating linux-x64-tests-clang
gn gen --check --fail-on-unused-args --export-compile-commands --root={root} '--args=is_clang=true chip_build_tests=true' {out}/linux-x64-tests-clang

# Generating linux-x64-thermostat
gn gen --check --fail-on-unused-args --export-compile-commands --root={root}/examples/thermostat/linux {out}/linux-x64-thermostat

Expand Down Expand Up @@ -336,6 +342,9 @@ ninja -C {out}/linux-arm64-tv-casting-app-ipv6only
# Building linux-fake-tests
ninja -C {out}/linux-fake-tests check

# Building linux-fake-tests-clang
ninja -C {out}/linux-fake-tests-clang check

# Building linux-x64-address-resolve-tool
ninja -C {out}/linux-x64-address-resolve-tool src/lib/address_resolve:address-resolve-tool

Expand Down Expand Up @@ -423,6 +432,9 @@ ninja -C {out}/linux-x64-shell-ipv6only
# Building linux-x64-tests
ninja -C {out}/linux-x64-tests check

# Building linux-x64-tests-clang
ninja -C {out}/linux-x64-tests-clang check

# Building linux-x64-thermostat
ninja -C {out}/linux-x64-thermostat

Expand Down
8 changes: 8 additions & 0 deletions src/credentials/tests/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import("//build_overrides/chip.gni")
import("//build_overrides/nlunit_test.gni")

import("${chip_root}/build/chip/chip_test_suite.gni")
import("${chip_root}/build/chip/fuzz_test.gni")

static_library("cert_test_vectors") {
output_name = "libCertTestVectors"
Expand Down Expand Up @@ -61,3 +62,10 @@ chip_test_suite("tests") {
"${nlunit_test_root}:nlunit-test",
]
}

if (enable_fuzz_test_targets) {
chip_fuzz_target("fuzz-chip-cert") {
sources = [ "FuzzChipCert.cpp" ]
public_deps = [ "${chip_root}/src/credentials" ]
}
}
36 changes: 36 additions & 0 deletions src/credentials/tests/FuzzChipCert.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#include <cstddef>
#include <cstdint>

#include "credentials/CHIPCert.h"

using namespace chip;
using namespace chip::Credentials;

extern "C" int LLVMFuzzerTestOneInput(const uint8_t * data, size_t len)
{

NodeId nodeId;
FabricId fabricId;

ByteSpan span(data, len);

(void) ExtractFabricIdFromCert(span, &fabricId);
(void) ExtractNodeIdFabricIdFromOpCert(span, &nodeId, &fabricId);

{
ChipDN dn;
(void) ExtractSubjectDNFromX509Cert(span, dn);
}

{
Credentials::P256PublicKeySpan key;
(void) ExtractPublicKeyFromChipCert(span, key);
}

{
ChipCertificateData certData;
(void) DecodeChipCert(span, certData);
}

return 0;
}
8 changes: 8 additions & 0 deletions src/lib/core/tests/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import("//build_overrides/chip.gni")
import("//build_overrides/nlunit_test.gni")

import("${chip_root}/build/chip/chip_test_suite.gni")
import("${chip_root}/build/chip/fuzz_test.gni")

chip_test_suite("tests") {
output_name = "libCoreTests"
Expand All @@ -39,3 +40,10 @@ chip_test_suite("tests") {
"${nlunit_test_root}:nlunit-test",
]
}

if (enable_fuzz_test_targets) {
chip_fuzz_target("fuzz-tlv-reader") {
sources = [ "FuzzTlvReader.cpp" ]
public_deps = [ "${chip_root}/src/lib/core" ]
}
}
21 changes: 21 additions & 0 deletions src/lib/core/tests/FuzzTlvReader.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#include <cstddef>
#include <cstdint>

#include "lib/core/CHIPTLV.h"
#include "lib/core/CHIPTLVUtilities.hpp"

using chip::TLV::TLVReader;

static CHIP_ERROR FuzzIterator(const TLVReader & aReader, size_t aDepth, void * aContext)
{
return CHIP_NO_ERROR;
}

extern "C" int LLVMFuzzerTestOneInput(const uint8_t * data, size_t len)
{
TLVReader reader;
reader.Init(data, len);
chip::TLV::Utilities::Iterate(reader, FuzzIterator, nullptr);

return 0;
}
8 changes: 8 additions & 0 deletions src/lib/dnssd/minimal_mdns/tests/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import("//build_overrides/chip.gni")
import("//build_overrides/nlunit_test.gni")

import("${chip_root}/build/chip/chip_test_suite.gni")
import("${chip_root}/build/chip/fuzz_test.gni")

chip_test_suite("tests") {
output_name = "libMinimalMdnstests"
Expand All @@ -42,3 +43,10 @@ chip_test_suite("tests") {
"${nlunit_test_root}:nlunit-test",
]
}

if (enable_fuzz_test_targets) {
chip_fuzz_target("fuzz-minmdns-packet-parsing") {
sources = [ "FuzzPacketParsing.cpp" ]
public_deps = [ "${chip_root}/src/lib/dnssd/minimal_mdns" ]
}
}
65 changes: 65 additions & 0 deletions src/lib/dnssd/minimal_mdns/tests/FuzzPacketParsing.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
#include <cstddef>
#include <cstdint>

#include <lib/dnssd/minimal_mdns/Parser.h>
#include <lib/dnssd/minimal_mdns/RecordData.h>

namespace {

using namespace chip;
using namespace mdns::Minimal;

class FuzzDelegate : public ParserDelegate
{
public:
FuzzDelegate(const mdns::Minimal::BytesRange & packet) : mPacketRange(packet) {}
virtual ~FuzzDelegate() {}

void OnHeader(ConstHeaderRef & header) override {}
void OnQuery(const QueryData & data) override {}
void OnResource(ResourceType type, const ResourceData & data) override
{
switch (data.GetType())
{
case QType::SRV: {
mdns::Minimal::SrvRecord srv;
(void) srv.Parse(data.GetData(), mPacketRange);
break;
}
case QType::A: {
chip::Inet::IPAddress addr;
(void) mdns::Minimal::ParseARecord(data.GetData(), &addr);
break;
}
case QType::AAAA: {
chip::Inet::IPAddress addr;
(void) mdns::Minimal::ParseAAAARecord(data.GetData(), &addr);
break;
}
case QType::PTR: {
mdns::Minimal::SerializedQNameIterator name;
(void) mdns::Minimal::ParsePtrRecord(data.GetData(), mPacketRange, &name);
break;
}
default:
// nothing to do
break;
}
}

private:
mdns::Minimal::BytesRange mPacketRange;
};

} // namespace

extern "C" int LLVMFuzzerTestOneInput(const uint8_t * data, size_t len)
{

BytesRange packet(data, data + len);
FuzzDelegate delegate(packet);

mdns::Minimal::ParsePacket(packet, &delegate);

return 0;
}

0 comments on commit 19132a3

Please sign in to comment.