Skip to content

Commit

Permalink
fuzz: add fuzzer targeting sample deserialization
Browse files Browse the repository at this point in the history
  • Loading branch information
robertfemmer authored and eboasson committed Mar 12, 2024
1 parent 8acd62b commit 42f9323
Show file tree
Hide file tree
Showing 6 changed files with 145 additions and 0 deletions.
1 change: 1 addition & 0 deletions fuzz/CMakeLists.txt
Expand Up @@ -17,4 +17,5 @@ include("${CMAKE_SOURCE_DIR}/cmake/Modules/Generate.cmake")
add_subdirectory(fuzz_config_init)
add_subdirectory(fuzz_handle_rtps_message)
add_subdirectory(fuzz_type_object)
add_subdirectory(fuzz_sample_deser)
# add_subdirectory(fuzz_idlc)
20 changes: 20 additions & 0 deletions fuzz/fuzz_sample_deser/CMakeLists.txt
@@ -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)
35 changes: 35 additions & 0 deletions fuzz/fuzz_sample_deser/fuzz_sample_deser.c
@@ -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;
}
54 changes: 54 additions & 0 deletions fuzz/fuzz_sample_deser/generate_idl.py
@@ -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())
34 changes: 34 additions & 0 deletions fuzz/fuzz_sample_deser/prepare.sh
@@ -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
1 change: 1 addition & 0 deletions fuzz/oss-fuzz-build.sh
Expand Up @@ -12,6 +12,7 @@
# SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
#

source fuzz/fuzz_sample_deser/prepare.sh
(
mkdir build
cd build
Expand Down

0 comments on commit 42f9323

Please sign in to comment.