diff --git a/BUILD.gn b/BUILD.gn index 4d76100fbe6d20..82c8d855bfd291 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -57,6 +57,8 @@ if (current_toolchain != "${dir_pw_toolchain}/default:default") { "${chip_root}/src/lib/core/tests:fuzz-tlv-reader", "${chip_root}/src/lib/dnssd/minimal_mdns/tests:fuzz-minmdns-packet-parsing", "${chip_root}/src/lib/format/tests:fuzz-payload-decoder", + "${chip_root}/src/setup_payload/tests:fuzz-setup-payload-base38", + "${chip_root}/src/setup_payload/tests:fuzz-setup-payload-base38-decode", ] } } diff --git a/src/setup_payload/tests/BUILD.gn b/src/setup_payload/tests/BUILD.gn index c3013c94f5acb5..75cdb8a71b0ad3 100644 --- a/src/setup_payload/tests/BUILD.gn +++ b/src/setup_payload/tests/BUILD.gn @@ -17,6 +17,7 @@ import("//build_overrides/chip.gni") import("//build_overrides/pigweed.gni") import("${chip_root}/build/chip/chip_test_suite.gni") +import("${chip_root}/build/chip/fuzz_test.gni") chip_test_suite("tests") { output_name = "libSetupPayloadTests" @@ -38,3 +39,20 @@ chip_test_suite("tests") { "${chip_root}/src/setup_payload", ] } + +if (enable_fuzz_test_targets) { + chip_fuzz_target("fuzz-setup-payload-base38") { + sources = [ "FuzzBase38.cpp" ] + public_deps = [ + "${chip_root}/src/platform/logging:stdio", + "${chip_root}/src/setup_payload", + ] + } + chip_fuzz_target("fuzz-setup-payload-base38-decode") { + sources = [ "FuzzBase38Decode.cpp" ] + public_deps = [ + "${chip_root}/src/platform/logging:stdio", + "${chip_root}/src/setup_payload", + ] + } +} diff --git a/src/setup_payload/tests/FuzzBase38.cpp b/src/setup_payload/tests/FuzzBase38.cpp new file mode 100644 index 00000000000000..478b2a0fc1d9dd --- /dev/null +++ b/src/setup_payload/tests/FuzzBase38.cpp @@ -0,0 +1,63 @@ +#include +#include +#include +#include +#include + +#include +#include + +using namespace chip; + +/** + * @file + * This file describes a base38 roundtrip Fuzzer. + * It starts by encoding the fuzzing value passed + * in Base38. The value encoded will then be decoded. + * The fuzzer verify that the decoded value is the same + * as the one in input. + */ + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t * data, size_t len) +{ + size_t outputSizeNeeded = base38EncodedLength(len); + const size_t kMaxOutputSize = 512; + + if (outputSizeNeeded > kMaxOutputSize) + { + return 0; + } + + ByteSpan span(data, len); + char encodedBuf[kMaxOutputSize]; + MutableCharSpan encodedSpan(encodedBuf); + CHIP_ERROR encodingError = base38Encode(span, encodedSpan); + + if (encodingError != CHIP_NO_ERROR) + { + __builtin_trap(); + } + + std::string base38EncodedString(encodedSpan.data(), encodedSpan.size()); + + std::vector decodedData; + CHIP_ERROR decodingError = base38Decode(base38EncodedString, decodedData); + + if (decodingError == CHIP_NO_ERROR) + { + if (decodedData.size() != len) + { + __builtin_trap(); + } + + if (memcmp(data, decodedData.data(), len) != 0) + { + __builtin_trap(); + } + } + else + { + __builtin_trap(); + } + return 0; +} diff --git a/src/setup_payload/tests/FuzzBase38Decode.cpp b/src/setup_payload/tests/FuzzBase38Decode.cpp new file mode 100644 index 00000000000000..317473370230c7 --- /dev/null +++ b/src/setup_payload/tests/FuzzBase38Decode.cpp @@ -0,0 +1,24 @@ +#include +#include +#include + +#include + +using namespace chip; + +/** + * @file + * This file describes a Fuzzer for decoding base38 encoded strings. + */ + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t * data, size_t len) +{ + std::string base38EncodedString(reinterpret_cast(data), len); + std::vector decodedData; + + // Ignoring return value, because in general the data is garbage and won't decode properly. + // We're just testing that the decoder does not crash on the fuzzer-generated inputs. + chip::base38Decode(base38EncodedString, decodedData); + + return 0; +}