From ab654266b35e1cf26cb5da9dff90a5375cfd2ebd Mon Sep 17 00:00:00 2001 From: firewave Date: Thu, 15 Feb 2024 16:15:54 +0100 Subject: [PATCH] added fuzzing client [skip ci] --- Makefile | 18 +++++++++++---- fuzz.cpp | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+), 4 deletions(-) create mode 100644 fuzz.cpp diff --git a/Makefile b/Makefile index db1ca257..ba2435d6 100644 --- a/Makefile +++ b/Makefile @@ -4,11 +4,13 @@ CXXFLAGS = -Wall -Wextra -pedantic -Wcast-qual -Wfloat-equal -Wmissing-declarati LDFLAGS = -g %.o: %.cpp simplecpp.h - $(CXX) $(CXXFLAGS) -c $< + $(CXX) $(CXXFLAGS) -c $< $(LIB_FUZZING_ENGINE) +fuzz_no.o: fuzz.cpp + $(CXX) $(CXXFLAGS) -DNO_FUZZ -c -o $@ fuzz.cpp testrunner: test.o simplecpp.o - $(CXX) $(LDFLAGS) simplecpp.o test.o -o testrunner + $(CXX) $(LDFLAGS) -o $@ $^ test: testrunner simplecpp # The -std=c++03 makes sure that simplecpp.cpp is C++03 conformant. We don't require a C++11 compiler @@ -16,11 +18,19 @@ test: testrunner simplecpp ./testrunner python3 run-tests.py +fuzz: fuzz.o simplecpp.o + # TODO: use -stdlib=libc++ -lc++ + # make fuzz CXX=clang++ CXXFLAGS="-O2 -fno-omit-frame-pointer -g -gline-tables-only -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -fsanitize=address,undefined -fsanitize-address-use-after-scope -fno-sanitize=integer -fno-sanitize-recover=undefined" LIB_FUZZING_ENGINE="-fsanitize=fuzzer" + $(CXX) $(LDFLAGS) $(CXXFLAGS) -o $@ $^ $(LIB_FUZZING_ENGINE) + +no-fuzz: fuzz_no.o simplecpp.o + $(CXX) $(LDFLAGS) $(CXXFLAGS) -o $@ $^ + selfcheck: simplecpp ./selfcheck.sh simplecpp: main.o simplecpp.o - $(CXX) $(LDFLAGS) main.o simplecpp.o -o simplecpp + $(CXX) $(LDFLAGS) -o $@ $^ clean: - rm -f testrunner simplecpp *.o + rm -f testrunner fuzz no-fuzz simplecpp *.o diff --git a/fuzz.cpp b/fuzz.cpp new file mode 100644 index 00000000..151c8a92 --- /dev/null +++ b/fuzz.cpp @@ -0,0 +1,67 @@ +/* + * simplecpp - A simple and high-fidelity C/C++ preprocessor library + * Copyright (C) 2016-2024 simplecpp team + */ + +#include "simplecpp.h" + +#include + +#ifdef NO_FUZZ +#include +#include +#include +#include +#endif + +static void doProcess(const uint8_t *data, size_t dataSize) +{ + simplecpp::OutputList outputList; + std::vector files; + simplecpp::TokenList rawtokens(data, dataSize, files, "test.cpp", &outputList); + rawtokens.removeComments(); + + simplecpp::TokenList outputTokens(files); + std::map filedata; + simplecpp::DUI dui; + dui.removeComments = true; + std::list macroUsage; + std::list ifCond; + simplecpp::preprocess(outputTokens, rawtokens, files, filedata, dui, &outputList, ¯oUsage, &ifCond); + + simplecpp::cleanup(filedata); +} + +#ifndef NO_FUZZ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t dataSize); + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t dataSize) +{ + doProcess(data, dataSize); + return 0; +} +#else +int main(int argc, char * argv[]) +{ + if (argc < 2 || argc > 3) + return EXIT_FAILURE; + + std::ifstream f(argv[1]); + if (!f.is_open()) + return EXIT_FAILURE; + + std::ostringstream oss; + oss << f.rdbuf(); + + if (!f.good()) + return EXIT_FAILURE; + + const int cnt = (argc == 3) ? std::stoi(argv[2]) : 1; + + const std::string code = oss.str(); + for (int i = 0; i < cnt; ++i) + doProcess(reinterpret_cast(code.data()), code.size()); + + return EXIT_SUCCESS; +} +#endif