Skip to content

Commit 0b39e3a

Browse files
authored
add fuzzer for padded_string (simdjson#1312)
This also fixes an overflow problem.
1 parent 924ad2d commit 0b39e3a

File tree

6 files changed

+75
-8
lines changed

6 files changed

+75
-8
lines changed

.github/workflows/fuzzers.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@ jobs:
1515
runs-on: ubuntu-latest
1616
env:
1717
# fuzzers that change behaviour with SIMDJSON_FORCE_IMPLEMENTATION
18-
defaultimplfuzzers: atpointer dump dump_raw_tape element minify parser print_json
18+
defaultimplfuzzers: atpointer dump dump_raw_tape element minify parser print_json
1919
# fuzzers that loop over the implementations themselves, or don't need to switch.
20-
implfuzzers: implementations minifyimpl ondemand utf8
20+
implfuzzers: implementations minifyimpl ondemand padded utf8
2121
implementations: haswell westmere fallback
2222
UBSAN_OPTIONS: halt_on_error=1
2323
MAXLEN: -max_len=4000

fuzz/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ if(ENABLE_FUZZING)
5858
implement_fuzzer(fuzz_minify) # minify *with* parsing
5959
implement_fuzzer(fuzz_minifyimpl) # minify *without* parsing, plus compare implementations
6060
implement_fuzzer(fuzz_ondemand)
61+
implement_fuzzer(fuzz_padded)
6162
implement_fuzzer(fuzz_parser)
6263
implement_fuzzer(fuzz_print_json)
6364
implement_fuzzer(fuzz_utf8) # utf8 verification, compares across implementations

fuzz/build_fuzzer_variants.sh

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@ fi
2424
set -u
2525

2626
# common options
27-
COMMON="-GNinja -DCMAKE_CXX_COMPILER=clang++$CLANGSUFFIX -DCMAKE_C_COMPILER=clang$CLANGSUFFIX -DSIMDJSON_BUILD_STATIC=Off -DENABLE_FUZZING=On -DSIMDJSON_COMPETITION=OFF -DSIMDJSON_GOOGLE_BENCHMARKS=OFF -DSIMDJSON_GIT=Off -DSIMDJSON_DISABLE_DEPRECATED_API=On"
27+
CXX_CLAGS_COMMON=-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
28+
COMMON="-GNinja -DCMAKE_CXX_COMPILER=clang++$CLANGSUFFIX -DCMAKE_C_COMPILER=clang$CLANGSUFFIX -DSIMDJSON_BUILD_STATIC=Off -DENABLE_FUZZING=On -DSIMDJSON_COMPETITION=OFF -DSIMDJSON_GOOGLE_BENCHMARKS=OFF -DSIMDJSON_DISABLE_DEPRECATED_API=On"
2829

2930
# A replay build, as plain as it gets. For use with valgrind/gdb.
3031
variant=replay
@@ -63,7 +64,7 @@ variant=sanitizers-O3
6364
cd build-$variant
6465
cmake .. \
6566
$COMMON \
66-
-DCMAKE_CXX_FLAGS="-O3 -fsanitize=fuzzer-no-link,address,undefined -fno-sanitize-recover=undefined" \
67+
-DCMAKE_CXX_FLAGS="-O3 -fsanitize=fuzzer-no-link,address,undefined -fno-sanitize-recover=undefined $CXX_CLAGS_COMMON" \
6768
-DCMAKE_C_FLAGS="-O3 -fsanitize=fuzzer-no-link,address,undefined -fno-sanitize-recover=undefined" \
6869
-DCMAKE_BUILD_TYPE=Debug \
6970
-DSIMDJSON_FUZZ_LINKMAIN=Off \
@@ -81,7 +82,7 @@ variant=sanitizers-O0
8182
cd build-$variant
8283
cmake .. \
8384
$COMMON \
84-
-DCMAKE_CXX_FLAGS="-O0 -fsanitize=fuzzer-no-link,address,undefined -fno-sanitize-recover=undefined" \
85+
-DCMAKE_CXX_FLAGS="-O0 -fsanitize=fuzzer-no-link,address,undefined -fno-sanitize-recover=undefined $CXX_CLAGS_COMMON" \
8586
-DCMAKE_C_FLAGS="-O0 -fsanitize=fuzzer-no-link,address,undefined -fno-sanitize-recover=undefined" \
8687
-DCMAKE_BUILD_TYPE=Debug \
8788
-DSIMDJSON_FUZZ_LINKMAIN=Off \
@@ -101,7 +102,7 @@ variant=fast
101102

102103
cmake .. \
103104
$COMMON \
104-
-DCMAKE_CXX_FLAGS="-fsanitize=fuzzer-no-link" \
105+
-DCMAKE_CXX_FLAGS="-fsanitize=fuzzer-no-link $CXX_CLAGS_COMMON" \
105106
-DCMAKE_C_FLAGS="-fsanitize=fuzzer-no-link" \
106107
-DCMAKE_BUILD_TYPE=Release \
107108
-DSIMDJSON_FUZZ_LINKMAIN=Off \

fuzz/build_like_ossfuzz.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ export OUT=$(pwd)/ossfuzz-out
1414
export CC=clang
1515
export CXX="clang++"
1616
export CFLAGS="-fsanitize=fuzzer-no-link"
17-
export CXXFLAGS="-fsanitize=fuzzer-no-link,address,undefined -O1"
17+
export CXXFLAGS="-fsanitize=fuzzer-no-link,address,undefined -O1 -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION"
1818
export LIB_FUZZING_ENGINE="-fsanitize=fuzzer"
1919

2020
$ossfuzz

fuzz/fuzz_padded.cpp

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
#include "FuzzUtils.h"
2+
#include "simdjson.h"
3+
#include <cstddef>
4+
#include <cstdint>
5+
#include <fstream>
6+
#include <string>
7+
8+
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
9+
FuzzData fd(Data, Size);
10+
11+
const int action = fd.getInt<0, 10>();
12+
13+
const auto s1 = fd.get<size_t>();
14+
const auto s2 = fd.get<size_t>();
15+
switch (action) {
16+
case 0: {
17+
simdjson_unused simdjson::padded_string p(s1);
18+
} break;
19+
case 1: {
20+
// operator== with temp value
21+
simdjson_unused simdjson::padded_string p1(s1);
22+
simdjson_unused simdjson::padded_string p2(s2);
23+
p1 = std::move(p2);
24+
} break;
25+
case 2: {
26+
// swap
27+
simdjson_unused simdjson::padded_string p1(s1);
28+
simdjson_unused simdjson::padded_string p2(s2);
29+
p1.swap(p2);
30+
} break;
31+
case 3: {
32+
simdjson_unused simdjson::padded_string p(s1);
33+
p.data();
34+
} break;
35+
case 4: {
36+
simdjson::padded_string p(s1);
37+
simdjson_unused auto sv = static_cast<std::string_view>(p);
38+
} break;
39+
case 5: {
40+
// load from file.
41+
const std::string filename = "/dev/shm/fuzz_padded.tmp";
42+
{
43+
std::ofstream file(filename);
44+
assert(file);
45+
const long ssize = static_cast<long>(fd.Size);
46+
file.write(fd.chardata(), ssize);
47+
assert(file.tellp() == ssize);
48+
}
49+
simdjson_unused auto data = simdjson::padded_string::load(filename);
50+
} break;
51+
default:;
52+
}
53+
return 0;
54+
}

include/simdjson/padded_string-inl.h

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,18 @@ namespace internal {
1919
// The length parameter is the maximum size in bytes of the string.
2020
// The caller is responsible to free the memory (e.g., delete[] (...)).
2121
inline char *allocate_padded_buffer(size_t length) noexcept {
22-
size_t totalpaddedlength = length + SIMDJSON_PADDING;
22+
const size_t totalpaddedlength = length + SIMDJSON_PADDING;
23+
if(totalpaddedlength<length) {
24+
// overflow
25+
return nullptr;
26+
}
27+
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
28+
// avoid getting out of memory
29+
if (totalpaddedlength>(1UL<<20)) {
30+
return nullptr;
31+
}
32+
#endif
33+
2334
char *padded_buffer = new (std::nothrow) char[totalpaddedlength];
2435
if (padded_buffer == nullptr) {
2536
return nullptr;

0 commit comments

Comments
 (0)