add fuzzer for padded_string (#1312)
This also fixes an overflow problem.
This commit is contained in:
parent
924ad2d592
commit
0b39e3a6cf
|
@ -15,9 +15,9 @@ jobs:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
env:
|
env:
|
||||||
# fuzzers that change behaviour with SIMDJSON_FORCE_IMPLEMENTATION
|
# fuzzers that change behaviour with SIMDJSON_FORCE_IMPLEMENTATION
|
||||||
defaultimplfuzzers: atpointer dump dump_raw_tape element minify parser print_json
|
defaultimplfuzzers: atpointer dump dump_raw_tape element minify parser print_json
|
||||||
# fuzzers that loop over the implementations themselves, or don't need to switch.
|
# fuzzers that loop over the implementations themselves, or don't need to switch.
|
||||||
implfuzzers: implementations minifyimpl ondemand utf8
|
implfuzzers: implementations minifyimpl ondemand padded utf8
|
||||||
implementations: haswell westmere fallback
|
implementations: haswell westmere fallback
|
||||||
UBSAN_OPTIONS: halt_on_error=1
|
UBSAN_OPTIONS: halt_on_error=1
|
||||||
MAXLEN: -max_len=4000
|
MAXLEN: -max_len=4000
|
||||||
|
|
|
@ -58,6 +58,7 @@ if(ENABLE_FUZZING)
|
||||||
implement_fuzzer(fuzz_minify) # minify *with* parsing
|
implement_fuzzer(fuzz_minify) # minify *with* parsing
|
||||||
implement_fuzzer(fuzz_minifyimpl) # minify *without* parsing, plus compare implementations
|
implement_fuzzer(fuzz_minifyimpl) # minify *without* parsing, plus compare implementations
|
||||||
implement_fuzzer(fuzz_ondemand)
|
implement_fuzzer(fuzz_ondemand)
|
||||||
|
implement_fuzzer(fuzz_padded)
|
||||||
implement_fuzzer(fuzz_parser)
|
implement_fuzzer(fuzz_parser)
|
||||||
implement_fuzzer(fuzz_print_json)
|
implement_fuzzer(fuzz_print_json)
|
||||||
implement_fuzzer(fuzz_utf8) # utf8 verification, compares across implementations
|
implement_fuzzer(fuzz_utf8) # utf8 verification, compares across implementations
|
||||||
|
|
|
@ -24,7 +24,8 @@ fi
|
||||||
set -u
|
set -u
|
||||||
|
|
||||||
# common options
|
# common options
|
||||||
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"
|
CXX_CLAGS_COMMON=-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
|
||||||
|
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"
|
||||||
|
|
||||||
# A replay build, as plain as it gets. For use with valgrind/gdb.
|
# A replay build, as plain as it gets. For use with valgrind/gdb.
|
||||||
variant=replay
|
variant=replay
|
||||||
|
@ -63,7 +64,7 @@ variant=sanitizers-O3
|
||||||
cd build-$variant
|
cd build-$variant
|
||||||
cmake .. \
|
cmake .. \
|
||||||
$COMMON \
|
$COMMON \
|
||||||
-DCMAKE_CXX_FLAGS="-O3 -fsanitize=fuzzer-no-link,address,undefined -fno-sanitize-recover=undefined" \
|
-DCMAKE_CXX_FLAGS="-O3 -fsanitize=fuzzer-no-link,address,undefined -fno-sanitize-recover=undefined $CXX_CLAGS_COMMON" \
|
||||||
-DCMAKE_C_FLAGS="-O3 -fsanitize=fuzzer-no-link,address,undefined -fno-sanitize-recover=undefined" \
|
-DCMAKE_C_FLAGS="-O3 -fsanitize=fuzzer-no-link,address,undefined -fno-sanitize-recover=undefined" \
|
||||||
-DCMAKE_BUILD_TYPE=Debug \
|
-DCMAKE_BUILD_TYPE=Debug \
|
||||||
-DSIMDJSON_FUZZ_LINKMAIN=Off \
|
-DSIMDJSON_FUZZ_LINKMAIN=Off \
|
||||||
|
@ -81,7 +82,7 @@ variant=sanitizers-O0
|
||||||
cd build-$variant
|
cd build-$variant
|
||||||
cmake .. \
|
cmake .. \
|
||||||
$COMMON \
|
$COMMON \
|
||||||
-DCMAKE_CXX_FLAGS="-O0 -fsanitize=fuzzer-no-link,address,undefined -fno-sanitize-recover=undefined" \
|
-DCMAKE_CXX_FLAGS="-O0 -fsanitize=fuzzer-no-link,address,undefined -fno-sanitize-recover=undefined $CXX_CLAGS_COMMON" \
|
||||||
-DCMAKE_C_FLAGS="-O0 -fsanitize=fuzzer-no-link,address,undefined -fno-sanitize-recover=undefined" \
|
-DCMAKE_C_FLAGS="-O0 -fsanitize=fuzzer-no-link,address,undefined -fno-sanitize-recover=undefined" \
|
||||||
-DCMAKE_BUILD_TYPE=Debug \
|
-DCMAKE_BUILD_TYPE=Debug \
|
||||||
-DSIMDJSON_FUZZ_LINKMAIN=Off \
|
-DSIMDJSON_FUZZ_LINKMAIN=Off \
|
||||||
|
@ -101,7 +102,7 @@ variant=fast
|
||||||
|
|
||||||
cmake .. \
|
cmake .. \
|
||||||
$COMMON \
|
$COMMON \
|
||||||
-DCMAKE_CXX_FLAGS="-fsanitize=fuzzer-no-link" \
|
-DCMAKE_CXX_FLAGS="-fsanitize=fuzzer-no-link $CXX_CLAGS_COMMON" \
|
||||||
-DCMAKE_C_FLAGS="-fsanitize=fuzzer-no-link" \
|
-DCMAKE_C_FLAGS="-fsanitize=fuzzer-no-link" \
|
||||||
-DCMAKE_BUILD_TYPE=Release \
|
-DCMAKE_BUILD_TYPE=Release \
|
||||||
-DSIMDJSON_FUZZ_LINKMAIN=Off \
|
-DSIMDJSON_FUZZ_LINKMAIN=Off \
|
||||||
|
|
|
@ -14,7 +14,7 @@ export OUT=$(pwd)/ossfuzz-out
|
||||||
export CC=clang
|
export CC=clang
|
||||||
export CXX="clang++"
|
export CXX="clang++"
|
||||||
export CFLAGS="-fsanitize=fuzzer-no-link"
|
export CFLAGS="-fsanitize=fuzzer-no-link"
|
||||||
export CXXFLAGS="-fsanitize=fuzzer-no-link,address,undefined -O1"
|
export CXXFLAGS="-fsanitize=fuzzer-no-link,address,undefined -O1 -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION"
|
||||||
export LIB_FUZZING_ENGINE="-fsanitize=fuzzer"
|
export LIB_FUZZING_ENGINE="-fsanitize=fuzzer"
|
||||||
|
|
||||||
$ossfuzz
|
$ossfuzz
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
#include "FuzzUtils.h"
|
||||||
|
#include "simdjson.h"
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <fstream>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
|
||||||
|
FuzzData fd(Data, Size);
|
||||||
|
|
||||||
|
const int action = fd.getInt<0, 10>();
|
||||||
|
|
||||||
|
const auto s1 = fd.get<size_t>();
|
||||||
|
const auto s2 = fd.get<size_t>();
|
||||||
|
switch (action) {
|
||||||
|
case 0: {
|
||||||
|
simdjson_unused simdjson::padded_string p(s1);
|
||||||
|
} break;
|
||||||
|
case 1: {
|
||||||
|
// operator== with temp value
|
||||||
|
simdjson_unused simdjson::padded_string p1(s1);
|
||||||
|
simdjson_unused simdjson::padded_string p2(s2);
|
||||||
|
p1 = std::move(p2);
|
||||||
|
} break;
|
||||||
|
case 2: {
|
||||||
|
// swap
|
||||||
|
simdjson_unused simdjson::padded_string p1(s1);
|
||||||
|
simdjson_unused simdjson::padded_string p2(s2);
|
||||||
|
p1.swap(p2);
|
||||||
|
} break;
|
||||||
|
case 3: {
|
||||||
|
simdjson_unused simdjson::padded_string p(s1);
|
||||||
|
p.data();
|
||||||
|
} break;
|
||||||
|
case 4: {
|
||||||
|
simdjson::padded_string p(s1);
|
||||||
|
simdjson_unused auto sv = static_cast<std::string_view>(p);
|
||||||
|
} break;
|
||||||
|
case 5: {
|
||||||
|
// load from file.
|
||||||
|
const std::string filename = "/dev/shm/fuzz_padded.tmp";
|
||||||
|
{
|
||||||
|
std::ofstream file(filename);
|
||||||
|
assert(file);
|
||||||
|
const long ssize = static_cast<long>(fd.Size);
|
||||||
|
file.write(fd.chardata(), ssize);
|
||||||
|
assert(file.tellp() == ssize);
|
||||||
|
}
|
||||||
|
simdjson_unused auto data = simdjson::padded_string::load(filename);
|
||||||
|
} break;
|
||||||
|
default:;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -19,7 +19,18 @@ namespace internal {
|
||||||
// The length parameter is the maximum size in bytes of the string.
|
// The length parameter is the maximum size in bytes of the string.
|
||||||
// The caller is responsible to free the memory (e.g., delete[] (...)).
|
// The caller is responsible to free the memory (e.g., delete[] (...)).
|
||||||
inline char *allocate_padded_buffer(size_t length) noexcept {
|
inline char *allocate_padded_buffer(size_t length) noexcept {
|
||||||
size_t totalpaddedlength = length + SIMDJSON_PADDING;
|
const size_t totalpaddedlength = length + SIMDJSON_PADDING;
|
||||||
|
if(totalpaddedlength<length) {
|
||||||
|
// overflow
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
|
||||||
|
// avoid getting out of memory
|
||||||
|
if (totalpaddedlength>(1UL<<20)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
char *padded_buffer = new (std::nothrow) char[totalpaddedlength];
|
char *padded_buffer = new (std::nothrow) char[totalpaddedlength];
|
||||||
if (padded_buffer == nullptr) {
|
if (padded_buffer == nullptr) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
Loading…
Reference in New Issue