Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fuzz: add fuzzer targeting sample deserialization
- Loading branch information
1 parent
8acd62b
commit 42f9323
Showing
6 changed files
with
145 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
cmake_minimum_required(VERSION 3.5) | ||
project(fuzz_sample_deser LANGUAGES C) | ||
|
||
if(NOT TARGET CycloneDDS::ddsc) | ||
# Find the CycloneDDS package. | ||
find_package(CycloneDDS REQUIRED) | ||
endif() | ||
|
||
idlc_generate(TARGET fuzz_sample FILES fuzz_sample.idl WARNINGS no-implicit-extensibility) | ||
add_executable(fuzz_sample_deser fuzz_sample_deser.c fuzz_sample.c) | ||
target_include_directories( | ||
fuzz_sample_deser PRIVATE | ||
"$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>/" | ||
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../../src/core/ddsc/src>" | ||
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../../src/core/cdr/include>" | ||
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../../src/core/ddsi/include>" | ||
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../../src/core/ddsi/src>") | ||
|
||
target_compile_options(fuzz_sample_deser PRIVATE -fsanitize=fuzzer,address -g) | ||
target_link_libraries(fuzz_sample_deser fuzz_sample CycloneDDS::ddsc -fsanitize=fuzzer,address) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
#include <ddsi__serdata_cdr.h> | ||
#include <dds/ddsrt/heap.h> | ||
#include <string.h> | ||
|
||
#include "fuzz_samples.h" | ||
|
||
static void __attribute__((constructor)) print_idl_types_seed() { | ||
printf("IDL types seed: %s\n", idl_types_seed); | ||
} | ||
|
||
static void topic_to_descriptor(struct dds_cdrstream_desc *desc, const dds_topic_descriptor_t *t) { | ||
memset(desc, 0, sizeof(struct dds_cdrstream_desc)); | ||
dds_cdrstream_desc_init(desc, &dds_cdrstream_default_allocator, t->m_size, t->m_align, t->m_flagset, t->m_ops, NULL, 0); | ||
} | ||
|
||
int LLVMFuzzerTestOneInput(void *data, size_t size) | ||
{ | ||
uint32_t actual_size; | ||
|
||
for(size_t i = 0; i < sizeof(fixed_types)/sizeof(fixed_types[0]); i++) { | ||
const struct dds_topic_descriptor *topic = fixed_types[i]; | ||
struct dds_cdrstream_desc desc; | ||
topic_to_descriptor(&desc, topic); | ||
if (dds_stream_normalize(data, (uint32_t) size, false, DDSI_RTPS_CDR_ENC_VERSION_2, &desc, false, &actual_size)) { | ||
void *sample = ddsrt_calloc(1, desc.size); | ||
dds_istream_t is; | ||
dds_istream_init(&is, (uint32_t) size, data, DDSI_RTPS_CDR_ENC_VERSION_2); | ||
dds_stream_read_sample(&is, sample, &dds_cdrstream_default_allocator, &desc); | ||
dds_stream_free_sample(sample, &dds_cdrstream_default_allocator, desc.ops.ops); | ||
ddsrt_free(sample); | ||
} | ||
dds_cdrstream_desc_fini(&desc, &dds_cdrstream_default_allocator); | ||
} | ||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
#!/usr/bin/env python | ||
|
||
import sys | ||
import os | ||
from fuzz_tools.rand_idl.creator import generate_random_types, generate_random_idl | ||
from fuzz_tools.rand_idl.value import generate_random_instance | ||
from fuzz_tools.rand_idl.compile import compile_idl | ||
|
||
def die(code, s): | ||
print(s, file=sys.stderr) | ||
sys.exit(code) | ||
|
||
MODULE_NAME = "Fuzz" | ||
CORPUS="fuzz_sample_deser_seed_corpus" | ||
if __name__ == '__main__': | ||
if len(sys.argv) != 3: | ||
die(0, "Usage: {} <seed> <target_directory>") | ||
seed = int(sys.argv[1], 16) | ||
directory = sys.argv[2] | ||
if not os.path.isdir(directory): | ||
die(-1, f"{directory} is not a directory") | ||
|
||
# Generate random idl | ||
scope = generate_random_types(MODULE_NAME, number=25, seed=seed) | ||
idl_text = generate_random_idl(scope) | ||
with open(os.path.join(directory, "fuzz_sample.idl"), "w") as f: | ||
f.write(idl_text) | ||
|
||
# Hacky way to identify top-level types. | ||
toplvltypes = [e for e in scope.entities if getattr(e, "extensibility", False)] | ||
# Generate fuzz_samples.h, collecting all generated types | ||
with open(os.path.join(directory, "fuzz_samples.h"), "w") as f: | ||
f.write("#include \"fuzz_sample.h\"\n") | ||
f.write("static const char *idl_types_seed = \"{}\";".format(sys.argv[1])) | ||
f.write("static const struct dds_topic_descriptor *fixed_types[] = {\n") | ||
for entity in toplvltypes: | ||
entry = "&{}_{}_desc".format(MODULE_NAME, entity.name) | ||
if entity != scope.entities[-1]: | ||
f.write(f"\t{entry},\n") | ||
else: | ||
f.write(f"\t{entry}\n") | ||
f.write("};\n") | ||
|
||
# Generate initial corpus | ||
imported, tdir = compile_idl(idl_text, MODULE_NAME) | ||
corpus = os.path.join(directory, CORPUS) | ||
if not os.path.isdir(corpus): | ||
os.mkdir(corpus) | ||
for entity in toplvltypes: | ||
t = getattr(imported.__fuzzytypes, entity.name) | ||
sample = generate_random_instance(t, seed=seed) | ||
fname = "seed_{}".format(entity.name) | ||
with open(os.path.join(corpus, fname), "wb") as f: | ||
f.write(sample.serialize()) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
#!/bin/bash -eu | ||
|
||
prepare_fuzz_deser() { | ||
apt-get -y install python3 python3-pip libssl-dev | ||
mkdir -p build_python install | ||
export CYCLONEDDS_HOME="$(pwd)/install" | ||
fuzzer="$(pwd)/fuzz/fuzz_sample_deser" | ||
cd build_python | ||
|
||
# This builds cyclone for the python tool, the fuzzer is built later | ||
cmake \ | ||
-DBUILD_IDLC=ON \ | ||
-DBUILD_TESTING=OFF \ | ||
-DBUILD_SHARED_LIBS=ON \ | ||
-DBUILD_EXAMPLES=NO \ | ||
-DENABLE_SECURITY=NO \ | ||
-DENABLE_SSL=NO \ | ||
-DCMAKE_POSITION_INDEPENDENT_CODE=ON \ | ||
-DCMAKE_INSTALL_PREFIX=../install .. | ||
cmake --build . | ||
cmake --build . --target install | ||
|
||
rm -rf cyclonedds-python | ||
git clone --depth=1 https://github.com/eclipse-cyclonedds/cyclonedds-python.git | ||
pip3 install ./cyclonedds-python | ||
ln -sf "$(pwd)/cyclonedds-python/tests/support_modules/fuzz_tools" "${fuzzer}/fuzz_tools" | ||
|
||
# Use current git HEAD hash as seed | ||
seed=$(git ls-remote https://github.com/eclipse-cyclonedds/cyclonedds HEAD |cut -f1) | ||
PATH=${CYCLONEDDS_HOME}/bin:$PATH python3 "${fuzzer}/generate_idl.py" $seed "${fuzzer}" | ||
} | ||
|
||
export -f prepare_fuzz_deser | ||
env -u CFLAGS -u CXXFLAGS -u LIB_FUZZING_ENGINE bash -euc prepare_fuzz_deser |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters