From e3c00c93ae99111bb96658de10de368c5b095ca4 Mon Sep 17 00:00:00 2001 From: Ben Wiederhake Date: Sat, 20 Feb 2021 21:59:23 +0100 Subject: [PATCH] Utilities: Provide fuzzers as a utility in serenity --- Userland/Utilities/CMakeLists.txt | 1 + Userland/Utilities/test-fuzz.cpp | 173 ++++++++++++++++++++++++++++++ 2 files changed, 174 insertions(+) create mode 100644 Userland/Utilities/test-fuzz.cpp diff --git a/Userland/Utilities/CMakeLists.txt b/Userland/Utilities/CMakeLists.txt index 4ac99be6e0c..46bab9ee276 100644 --- a/Userland/Utilities/CMakeLists.txt +++ b/Userland/Utilities/CMakeLists.txt @@ -42,6 +42,7 @@ target_link_libraries(su LibCrypt) target_link_libraries(tar LibTar LibCompress) target_link_libraries(test-crypto LibCrypto LibTLS LibLine) target_link_libraries(test-compress LibCompress) +target_link_libraries(test-fuzz LibCore LibGemini LibGfx LibHTTP LibIPC LibJS LibMarkdown LibShell) target_link_libraries(test-js LibJS LibLine LibCore) target_link_libraries(test-pthread LibThread) target_link_libraries(test-web LibWeb) diff --git a/Userland/Utilities/test-fuzz.cpp b/Userland/Utilities/test-fuzz.cpp new file mode 100644 index 00000000000..a2f61f2a0f7 --- /dev/null +++ b/Userland/Utilities/test-fuzz.cpp @@ -0,0 +1,173 @@ +/* + * Copyright (c) 2021, Ben Wiederhake + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include + +#define ENUMERATE_TARGETS(T) \ + T(BMPLoader) \ + T(ELF) \ + T(Gemini) \ + T(GIFLoader) \ + T(HttpRequest) \ + T(ICOLoader) \ + T(JPGLoader) \ + T(Js) \ + T(Markdown) \ + T(PBMLoader) \ + T(PGMLoader) \ + T(PNGLoader) \ + T(PPMLoader) \ + T(RegexECMA262) \ + T(RegexPosixExtended) \ + T(Shell) \ + T(TTF) \ + T(URL) + +#undef __ENUMERATE_TARGET +#define __ENUMERATE_TARGET(x) extern "C" int Test##x(const uint8_t*, size_t); +ENUMERATE_TARGETS(__ENUMERATE_TARGET) +#undef __ENUMERATE_TARGET + +#define LLVMFuzzerTestOneInput TestBMPLoader +#include +#undef LLVMFuzzerTestOneInput + +#define LLVMFuzzerTestOneInput TestELF +#include +#undef LLVMFuzzerTestOneInput + +#define LLVMFuzzerTestOneInput TestGemini +#include +#undef LLVMFuzzerTestOneInput + +#define LLVMFuzzerTestOneInput TestGIFLoader +#include +#undef LLVMFuzzerTestOneInput + +#define LLVMFuzzerTestOneInput TestHttpRequest +#include +#undef LLVMFuzzerTestOneInput + +#define LLVMFuzzerTestOneInput TestICOLoader +#include +#undef LLVMFuzzerTestOneInput + +#define LLVMFuzzerTestOneInput TestJPGLoader +#include +#undef LLVMFuzzerTestOneInput + +#define LLVMFuzzerTestOneInput TestJs +#include +#undef LLVMFuzzerTestOneInput + +#define LLVMFuzzerTestOneInput TestMarkdown +#include +#undef LLVMFuzzerTestOneInput + +#define LLVMFuzzerTestOneInput TestPBMLoader +#include +#undef LLVMFuzzerTestOneInput + +#define LLVMFuzzerTestOneInput TestPGMLoader +#include +#undef LLVMFuzzerTestOneInput + +#define LLVMFuzzerTestOneInput TestPNGLoader +#include +#undef LLVMFuzzerTestOneInput + +#define LLVMFuzzerTestOneInput TestPPMLoader +#include +#undef LLVMFuzzerTestOneInput + +#define LLVMFuzzerTestOneInput TestRegexECMA262 +#include +#undef LLVMFuzzerTestOneInput + +#define LLVMFuzzerTestOneInput TestRegexPosixExtended +#include +#undef LLVMFuzzerTestOneInput + +#define LLVMFuzzerTestOneInput TestShell +#include +#undef LLVMFuzzerTestOneInput + +#define LLVMFuzzerTestOneInput TestTTF +#include +#undef LLVMFuzzerTestOneInput + +#define LLVMFuzzerTestOneInput TestURL +#include +#undef LLVMFuzzerTestOneInput + +static auto parse_target_name(const String& name) +{ + if (name == "list") { + outln("The following targets are included:"); +#undef __ENUMERATE_TARGET +#define __ENUMERATE_TARGET(x) outln(#x); + ENUMERATE_TARGETS(__ENUMERATE_TARGET) +#undef __ENUMERATE_TARGET + exit(0); + } + +#undef __ENUMERATE_TARGET +#define __ENUMERATE_TARGET(x) \ + if (name == #x) \ + return Test##x; + ENUMERATE_TARGETS(__ENUMERATE_TARGET) +#undef __ENUMERATE_TARGET + + warnln("Unknown fuzzing target \"{}\". Try \"list\" to get a full list.", name); + exit(1); +} + +int main(int argc, char** argv) +{ + const char* type; + const char* filename; + + Core::ArgsParser args_parser; + args_parser.add_positional_argument(type, "Type of fuzzing target to run (use \"list\" to list all existing)", "target-kind"); + args_parser.add_positional_argument(filename, "Input file", "filename"); + args_parser.parse(argc, argv); + + auto fn = parse_target_name(type); + + auto file = Core::File::open(filename, Core::IODevice::OpenMode::ReadOnly); + if (file.is_error()) { + warnln("Cannot read from file: {}", file.error()); + exit(1); + } + + auto input = file.value()->read_all(); + + return fn(input.data(), input.size()); +}