Merge pull request #201 from tyler92/improve-fuzzing

Fuzzing improvements
This commit is contained in:
Tristan Penman 2024-10-22 14:10:17 +11:00 committed by GitHub
commit bd1f707f8c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 81 additions and 53 deletions

View File

@ -1,43 +1,78 @@
#include <stdexcept>
#include <unistd.h>
#include <document.h>
#include <valijson/adapters/rapidjson_adapter.hpp> #include <valijson/adapters/rapidjson_adapter.hpp>
#include <valijson/utils/rapidjson_utils.hpp>
#include <valijson/schema.hpp>
#include <valijson/schema_parser.hpp> #include <valijson/schema_parser.hpp>
#include <valijson/validator.hpp>
using valijson::Schema; using valijson::Schema;
using valijson::SchemaParser; using valijson::SchemaParser;
using valijson::ValidationResults;
using valijson::Validator;
using valijson::adapters::AdapterTraits;
using valijson::adapters::RapidJsonAdapter; using valijson::adapters::RapidJsonAdapter;
using AdapterType = RapidJsonAdapter;
extern "C" int void runOneTest(const AdapterType &test, const Schema &schema,
LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) Validator::TypeCheckingMode mode)
{ {
if(size<3) return 0;
char input_file[256];
sprintf(input_file, "/tmp/libfuzzer.json");
FILE *fp = fopen(input_file, "wb");
if (!fp)
return 0;
fwrite(data, size, 1, fp);
fclose(fp);
rapidjson::Document schemaDocument;
if (!valijson::utils::loadDocument(input_file, schemaDocument)) {
return 1;
}
Schema schema;
SchemaParser parser;
RapidJsonAdapter schemaDocumentAdapter(schemaDocument);
try { try {
parser.populateSchema(schemaDocumentAdapter, schema); if (!test.isObject()) {
} catch (std::exception &e) { return;
unlink(input_file); }
return 1;
const AdapterType::Object testObject = test.getObject();
const auto dataItr = testObject.find("data");
if (dataItr == testObject.end()) {
return;
}
Validator validator(mode);
ValidationResults results;
validator.validate(schema, dataItr->second, &results);
} catch (const std::exception &) {
}
}
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
{
AdapterTraits<AdapterType>::DocumentType document;
document.template Parse<rapidjson::kParseIterativeFlag>(reinterpret_cast<const char *>(data), size);
if (document.HasParseError() || !document.IsArray()) {
return 0;
} }
unlink(input_file); for (const auto &testCase : AdapterType(document).getArray()) {
return 1; if (!testCase.isObject()) {
continue;
}
const AdapterType::Object object = testCase.getObject();
const auto schemaItr = object.find("schema");
const auto testsItr = object.find("tests");
if (schemaItr == object.end() || testsItr == object.end() ||
!testsItr->second.isArray()) {
continue;
}
Schema schema;
SchemaParser parser(size % 2 ? SchemaParser::kDraft4
: SchemaParser::kDraft7);
try {
parser.populateSchema(schemaItr->second, schema);
} catch (const std::exception &) {
continue;
}
const auto mode = testsItr->second.hasStrictTypes()
? Validator::kStrongTypes
: Validator::kWeakTypes;
for (const AdapterType test : testsItr->second.getArray()) {
runOneTest(test, schema, mode);
}
}
return 0;
} }

View File

@ -2,38 +2,31 @@
git submodule update --init --depth 1 thirdparty git submodule update --init --depth 1 thirdparty
# This line causes an abort which breaks fuzzing:
sed -i '27d' include/valijson/utils/rapidjson_utils.hpp
mkdir build mkdir build
cd build cd build
cmake \ cmake \
-Dvalijson_BUILD_TESTS=TRUE \ -Dvalijson_BUILD_TESTS=FALSE \
-Dvalijson_BUILD_EXAMPLES=FALSE \ -Dvalijson_BUILD_EXAMPLES=FALSE \
-Dvalijson_EXCLUDE_BOOST=TRUE \ -Dvalijson_EXCLUDE_BOOST=TRUE \
.. ..
make -j"$(nproc)" make -j"$(nproc)"
cd ../tests/fuzzing cd ../tests/fuzzing
find ../.. -name "*.o" -exec ar rcs fuzz_lib.a {} \;
# CXXFLAGS may contain spaces # CXXFLAGS may contain spaces
# shellcheck disable=SC2086
"$CXX" $CXXFLAGS -DVALIJSON_USE_EXCEPTIONS=1 \
-I/src/valijson/thirdparty/rapidjson/include \
-I/src/valijson/thirdparty/rapidjson/include/rapidjson \
-I/src/valijson/include \
-I/src/valijson/include/valijson \
-I/src/valijson/include/valijson/adapters \
-c fuzzer.cpp -o fuzzer.o
# shellcheck disable=SC2086 # shellcheck disable=SC2086
"$CXX" $CXXFLAGS "$LIB_FUZZING_ENGINE" \ "$CXX" $CXXFLAGS "$LIB_FUZZING_ENGINE" \
-DVALIJSON_USE_EXCEPTIONS=1 \ -DVALIJSON_USE_EXCEPTIONS=1 \
-rdynamic fuzzer.o \ -I/src/valijson/thirdparty/rapidjson/include \
-o "${OUT}/fuzzer" fuzz_lib.a -I/src/valijson/include \
fuzzer.cpp -o "${OUT}/fuzzer"
zip "${OUT}/fuzzer_seed_corpus.zip" \ mkdir seed_corpus
"${SRC}/valijson/doc/schema/draft-03.json"
find "${SRC}/valijson/thirdparty/JSON-Schema-Test-Suite/tests" -name "*.json" | while read file; do
sha1=$(sha1sum "$file" | awk '{print $1}')
cp "$file" seed_corpus/"${sha1}"
done
zip -j -r "${OUT}/fuzzer_seed_corpus.zip" seed_corpus