Skip to content

Commit 39e0ddd

Browse files
committed
Initialize project for fuzzing
1 parent 24b5e7a commit 39e0ddd

File tree

4 files changed

+158
-0
lines changed

4 files changed

+158
-0
lines changed

CMakeLists.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ if(RAPIDJSON_USE_MEMBERSMAP)
4646
add_definitions(-DRAPIDJSON_USE_MEMBERSMAP=1)
4747
endif()
4848

49+
find_package(cifuzz NO_SYSTEM_ENVIRONMENT_PATH)
50+
enable_fuzz_testing()
51+
4952
find_program(CCACHE_FOUND ccache)
5053
if(CCACHE_FOUND)
5154
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache)
@@ -255,3 +258,5 @@ IF(CMAKE_INSTALL_DIR)
255258
INSTALL(TARGETS RapidJSON EXPORT RapidJSON-targets)
256259
INSTALL(EXPORT RapidJSON-targets DESTINATION ${CMAKE_INSTALL_DIR})
257260
ENDIF()
261+
262+
add_subdirectory(cifuzz-spark)

cifuzz-spark/CMakeLists.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#cifuzz:build-template:begin
2+
#add_fuzz_test({{ .FuzzTestName }} {{ .FileName }})
3+
#target_link_libraries({{ .FuzzTestName }} PRIVATE "$<LINK_LIBRARY:WHOLE_ARCHIVE,RapidJSON>")
4+
#cifuzz:build-template:end
5+
6+
add_fuzz_test(fuzz_test fuzz_test.cpp)
7+
target_link_libraries(fuzz_test PRIVATE "$<LINK_LIBRARY:WHOLE_ARCHIVE,RapidJSON>")

cifuzz-spark/fuzz_test.cpp

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
#include <assert.h>
2+
#include <cstdio>
3+
#include <cstdlib>
4+
#include <cstring>
5+
#include <vector>
6+
#include <cifuzz/cifuzz.h>
7+
#include <fuzzer/FuzzedDataProvider.h>
8+
9+
// RapidJSON includes
10+
#include "rapidjson/document.h"
11+
#include "rapidjson/schema.h"
12+
#include "rapidjson/filereadstream.h"
13+
#include "rapidjson/error/en.h"
14+
#include "rapidjson/prettywriter.h"
15+
#include "rapidjson/stringbuffer.h"
16+
17+
// FUZZ_TEST_SETUP:
18+
// (No one-time setup needed beyond what is shown)
19+
FUZZ_TEST_SETUP() {
20+
// One-time initialization tasks can be performed here.
21+
}
22+
23+
FUZZ_TEST(const uint8_t *data, size_t size) {
24+
// Initialize FuzzedDataProvider (using a single instance)
25+
FuzzedDataProvider fdp(data, size);
26+
27+
// Consume a string for the schema (limit size to 1024)
28+
std::string schemaStr = fdp.ConsumeRandomLengthString(1024);
29+
// Consume remaining data for the JSON instance (limit to 8192)
30+
std::string jsonStr = fdp.ConsumeRandomLengthString(8192);
31+
32+
// ----------------------------- //
33+
// Set up the Schema using tmpfile
34+
// ----------------------------- //
35+
FILE* schemaFile = tmpfile();
36+
if (!schemaFile) return; // if tmpfile fails, exit
37+
38+
// Write schema data to file
39+
if (!schemaStr.empty()) {
40+
fwrite(schemaStr.data(), 1, schemaStr.size(), schemaFile);
41+
}
42+
rewind(schemaFile);
43+
44+
// Prepare a buffer, and parse the schema using FileReadStream
45+
char buffer[4096];
46+
rapidjson::Document d;
47+
rapidjson::FileReadStream schemaStream(schemaFile, buffer, sizeof(buffer));
48+
d.ParseStream(schemaStream);
49+
fclose(schemaFile);
50+
51+
// Construct the SchemaDocument from the parsed Document
52+
rapidjson::SchemaDocument sd(d);
53+
54+
// --------------------------------- //
55+
// Set up JSON instance using tmpfile
56+
// --------------------------------- //
57+
FILE* jsonFile = tmpfile();
58+
if (!jsonFile) return;
59+
60+
if (!jsonStr.empty()) {
61+
fwrite(jsonStr.data(), 1, jsonStr.size(), jsonFile);
62+
}
63+
rewind(jsonFile);
64+
65+
// Create a SchemaValidator and Reader.
66+
rapidjson::SchemaValidator validator(sd);
67+
rapidjson::Reader reader;
68+
rapidjson::FileReadStream jsonStream(jsonFile, buffer, sizeof(buffer));
69+
reader.Parse(jsonStream, validator);
70+
fclose(jsonFile);
71+
72+
// Call additional API functions to further exercise the interface.
73+
volatile bool valid = validator.IsValid();
74+
// When invalid, obtain various API outputs
75+
if (!valid) {
76+
rapidjson::GenericStringBuffer<rapidjson::UTF8<>> sb;
77+
validator.GetInvalidSchemaPointer().StringifyUriFragment(sb);
78+
validator.GetInvalidDocumentPointer().StringifyUriFragment(sb);
79+
rapidjson::PrettyWriter<rapidjson::GenericStringBuffer<rapidjson::UTF8<>>> writer(sb);
80+
validator.GetError().Accept(writer);
81+
}
82+
}

cifuzz.yaml

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
## Configuration for a CI Fuzz project
2+
## Generated on 2025-04-22
3+
4+
## The build system used to build this project. If not set, cifuzz tries to
5+
## detect the build system automatically.
6+
## Valid values: "bazel", "cmake", "other"
7+
build-system: cmake
8+
9+
## Engine used for fuzzing, default is "libfuzzer-clang".
10+
## Valid values: "libfuzzer-clang", "honggfuzz-clang", "honggfuzz-gcc"
11+
#engine: libfuzzer-clang
12+
13+
## If the build system type is "other", this command is used to build the fuzz
14+
## tests.
15+
#build-command: make my_fuzz_test
16+
17+
## If the build system type is "other", this command is used to list the names
18+
## of already existing fuzz tests in your project. This allows running all fuzz
19+
## tests in the project without listing them explicitly, supports fuzz test
20+
## generation and enables fuzz test completion for commands.
21+
## The listed names should be separated by whitespace and can't include
22+
## whitespaces themselves, i.e. 'fuzz_test1 fuzz_test_2 ...'
23+
#list-fuzz-tests-command: echo my_fuzz_test
24+
25+
## Command-line arguments to pass directly to the build system to use when
26+
## building fuzz tests.
27+
#build-system-args:
28+
# - -DBUILD_TESTS=ON
29+
30+
## Directories containing sample inputs used as seeds for running fuzz tests.
31+
## For general information on seed corpora, see:
32+
## https://docs.code-intelligence.com/glossary#seed-corpus
33+
#seed-corpus-dirs:
34+
# - path/to/seed-corpus
35+
36+
## Directories containing inputs for calculating coverage. These are used in
37+
## addition to inputs found in the directory of the fuzz test.
38+
#corpus-dirs:
39+
# - path/to/corpus
40+
41+
## File containing input language keywords or other interesting byte sequences
42+
## used for running fuzz tests.
43+
## For libFuzzer see: https://llvm.org/docs/LibFuzzer.html#dictionaries
44+
#dict: path/to/dictionary.dct
45+
46+
## Command-line arguments to pass to the fuzzing engine when running fuzz tests.
47+
## For libFuzzer see: https://llvm.org/docs/LibFuzzer.html#options
48+
#engine-args:
49+
# - -rss_limit_mb=4096
50+
51+
## Maximum time to run all fuzz tests. Default is 10 minutes. The time will be
52+
## split up evenly between multiple fuzz tests. To keep running indefinitely,
53+
## set value to 0.
54+
#max-fuzzing-duration: 30m
55+
56+
## Set to true to print output of the `cifuzz run` command as JSON.
57+
#print-json: true
58+
59+
## Set to true to disable desktop notifications.
60+
#no-notifications: true
61+
62+
## Set style for command output.
63+
## Valid values: "pretty", "plain"
64+
#style: plain

0 commit comments

Comments
 (0)