Skip to content

Commit 9442c9e

Browse files
pauldreiklemire
authored andcommitted
add basic fuzzers (simdjson#348)
* add basic fuzzing using libFuzzer * let cmake respect cflags, otherwise the fuzzer flags go unnoticed also, integrates badly with oss-fuzz * add new fuzzer for minification, simplify the old one * add fuzzer for the dump example * clang format
1 parent 1574050 commit 9442c9e

6 files changed

Lines changed: 134 additions & 2 deletions

File tree

‎CMakeLists.txt‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,12 @@ add_subdirectory(tools)
4848
add_subdirectory(tests)
4949
add_subdirectory(benchmark)
5050

51+
# for fuzzing, read the comments in the fuzz/CMakeLists.txt file
52+
option(ENABLE_FUZZING "enable fuzzing (experimental, requires clang)" OFF)
53+
if(ENABLE_FUZZING)
54+
add_subdirectory(fuzz)
55+
endif()
56+
5157
set(CPACK_PACKAGE_VENDOR "Daniel Lemire")
5258
set(CPACK_PACKAGE_CONTACT "lemire@gmail.com")
5359
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Parsing gigabytes of JSON per second")
@@ -62,3 +68,5 @@ set(CPACK_RPM_PACKAGE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE")
6268
set(CPACK_SOURCE_GENERATOR "TGZ;ZIP")
6369

6470
include(CPack)
71+
72+

‎fuzz/CMakeLists.txt‎

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# First attempt at a fuzzer, using libFuzzer.
2+
#
3+
# compile like this:
4+
# mkdir build-fuzzer
5+
# cd build-fuzzer
6+
# export LDFLAGS="-fsanitize=address,undefined"
7+
# export CXXFLAGS="-fsanitize=fuzzer-no-link,address,undefined"
8+
# export CFLAGS="-fsanitize=fuzzer-no-link,address,undefined"
9+
# export CXX=clang++
10+
# export CC=clang++
11+
# cmake .. -GNinja -DCMAKE_BUILD_TYPE=Debug -DENABLE_FUZZING=On
12+
# ninja
13+
14+
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
15+
add_executable(fuzz_parser fuzz_parser.cpp)
16+
target_link_libraries(fuzz_parser PRIVATE ${SIMDJSON_LIB_NAME} )
17+
target_link_libraries(fuzz_parser PRIVATE "-fsanitize=fuzzer")
18+
19+
add_executable(fuzz_minify fuzz_minify.cpp)
20+
target_link_libraries(fuzz_minify PRIVATE ${SIMDJSON_LIB_NAME} )
21+
target_link_libraries(fuzz_minify PRIVATE "-fsanitize=fuzzer")
22+
23+
add_executable(fuzz_dump fuzz_dump.cpp)
24+
target_link_libraries(fuzz_dump PRIVATE ${SIMDJSON_LIB_NAME} )
25+
target_link_libraries(fuzz_dump PRIVATE "-fsanitize=fuzzer")
26+
endif()
27+

‎fuzz/fuzz_dump.cpp‎

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
#include "simdjson/jsonparser.h"
2+
#include <cstddef>
3+
#include <cstdint>
4+
#include <iostream>
5+
#include <string>
6+
7+
// from https://stackoverflow.com/a/8244052
8+
class NulStreambuf : public std::streambuf {
9+
char dummyBuffer[64];
10+
11+
protected:
12+
virtual int overflow(int c) {
13+
setp(dummyBuffer, dummyBuffer + sizeof(dummyBuffer));
14+
return (c == traits_type::eof()) ? '\0' : c;
15+
}
16+
};
17+
18+
class NulOStream : private NulStreambuf, public std::ostream {
19+
public:
20+
NulOStream() : std::ostream(this) {}
21+
NulStreambuf *rdbuf() { return this; }
22+
};
23+
24+
// from the README on the front page
25+
void compute_dump(simdjson::ParsedJson::Iterator &pjh) {
26+
NulOStream os;
27+
28+
if (pjh.is_object()) {
29+
os << "{";
30+
if (pjh.down()) {
31+
pjh.print(os); // must be a string
32+
os << ":";
33+
pjh.next();
34+
compute_dump(pjh); // let us recurse
35+
while (pjh.next()) {
36+
os << ",";
37+
pjh.print(os);
38+
os << ":";
39+
pjh.next();
40+
compute_dump(pjh); // let us recurse
41+
}
42+
pjh.up();
43+
}
44+
os << "}";
45+
} else if (pjh.is_array()) {
46+
os << "[";
47+
if (pjh.down()) {
48+
compute_dump(pjh); // let us recurse
49+
while (pjh.next()) {
50+
os << ",";
51+
compute_dump(pjh); // let us recurse
52+
}
53+
pjh.up();
54+
}
55+
os << "]";
56+
} else {
57+
pjh.print(os); // just print the lone value
58+
}
59+
}
60+
61+
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
62+
63+
try {
64+
auto pj = simdjson::build_parsed_json(Data, Size);
65+
simdjson::ParsedJson::Iterator pjh(pj);
66+
if (pjh.is_ok()) {
67+
compute_dump(pjh);
68+
}
69+
} catch (...) {
70+
}
71+
return 0;
72+
}

‎fuzz/fuzz_minify.cpp‎

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#include "simdjson/jsonminifier.h"
2+
#include "simdjson/jsonparser.h"
3+
#include <cstddef>
4+
#include <cstdint>
5+
#include <string>
6+
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
7+
8+
auto begin = (const char *)Data;
9+
auto end = begin + Size;
10+
11+
std::string str(begin, end);
12+
13+
simdjson::json_minify(str.data(), str.size(), str.data());
14+
return 0;
15+
}

‎fuzz/fuzz_parser.cpp‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#include "simdjson/jsonparser.h"
2+
#include <cstddef>
3+
#include <cstdint>
4+
#include <string>
5+
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
6+
7+
auto ignored = simdjson::build_parsed_json(Data, Size);
8+
9+
return 0;
10+
}

‎tools/cmake/FindOptions.cmake‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,13 +46,13 @@ set(CMAKE_C_FLAGS_DEBUG "-ggdb")
4646
set(CMAKE_C_FLAGS_RELEASE "-O3")
4747
endif()
4848

49-
set(CMAKE_C_FLAGS "${STD_FLAGS} ${OPT_FLAGS} ${INCLUDE_FLAGS} ${WARNING_FLAGS} ${SIMDJSON_SANITIZE_FLAGS} ")
49+
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${STD_FLAGS} ${OPT_FLAGS} ${INCLUDE_FLAGS} ${WARNING_FLAGS} ${SIMDJSON_SANITIZE_FLAGS} ")
5050

5151
if(NOT MSVC)
5252
set(CMAKE_CXX_FLAGS_DEBUG "-ggdb")
5353
set(CMAKE_CXX_FLAGS_RELEASE "-O3")
5454
endif()
55-
set(CMAKE_CXX_FLAGS "${CXXSTD_FLAGS} ${OPT_FLAGS} ${INCLUDE_FLAGS} ${WARNING_FLAGS} ${SIMDJSON_SANITIZE_FLAGS} ")
55+
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXXSTD_FLAGS} ${OPT_FLAGS} ${INCLUDE_FLAGS} ${WARNING_FLAGS} ${SIMDJSON_SANITIZE_FLAGS} ")
5656

5757
if(MSVC)
5858
add_definitions( "${OPT_FLAGS} /W3 /D_CRT_SECURE_NO_WARNINGS /wd4005 /wd4996 /wd4267 /wd4244 /wd4113 /nologo")

0 commit comments

Comments
 (0)