mirror of
https://github.com/saymrwulf/onnxruntime.git
synced 2026-05-14 20:48:00 +00:00
[Fuzzer] Add two new ORT libfuzzer (Linux clang support for now) (#22055)
### Description This PR adds two new libfuzzer in fuzzer project. 1. Binary libfuzzer 2. libprotobuf-fuzzer To compile run below cmd on linux: ``` LLVM_PROFILE_FILE="%p.profraw" CFLAGS="-g -fsanitize=address,fuzzer-no-link -shared-libasan -fprofile-instr-generate -fcoverage-mapping" CXXFLAGS="-g -shared-libasan -fsanitize=address,fuzzer-no-link -fprofile-instr-generate -fcoverage-mapping" CC=clang CXX=clang++ ./build.sh --update --build --config Debug --compile_no_warning_as_error --build_shared_lib --skip_submodule_sync --use_full_protobuf --parallel --fuzz_testing --build_dir build/ ``` Run fuzzer: ``` LD_PRELOAD=$(clang -print-file-name=libclang_rt.asan-x86_64.so) build/Debug/onnxruntime_libfuzzer_fuzz testinput -rss_limit_mb=8196 -max_total_time=472800 -fork=2 -jobs=4 -workers=4 -ignore_crashes=1 -max_len=2097152 2>&1 | grep -v "\[libprotobuf ERROR" ``` ### Motivation and Context The existing custom fuzzer is not coverage guided and it's slow and it will work on one model mutation at a time. The new fuzzers are coverage guided, and we can use more models' files as a corpus to increase the coverage.
This commit is contained in:
parent
d539c27de8
commit
5c361106e6
3 changed files with 233 additions and 42 deletions
|
|
@ -21,6 +21,7 @@ if (onnxruntime_FUZZ_ENABLED)
|
||||||
onnxruntime_add_include_to_target(protobuf-mutator-libfuzzer ${PROTOBUF_LIB})
|
onnxruntime_add_include_to_target(protobuf-mutator-libfuzzer ${PROTOBUF_LIB})
|
||||||
target_include_directories(protobuf-mutator PRIVATE ${INCLUDE_DIRECTORIES} ${PROTOBUF_MUT_INCLUDE_DIRS})
|
target_include_directories(protobuf-mutator PRIVATE ${INCLUDE_DIRECTORIES} ${PROTOBUF_MUT_INCLUDE_DIRS})
|
||||||
target_include_directories(protobuf-mutator-libfuzzer PRIVATE ${INCLUDE_DIRECTORIES} ${PROTOBUF_MUT_INCLUDE_DIRS})
|
target_include_directories(protobuf-mutator-libfuzzer PRIVATE ${INCLUDE_DIRECTORIES} ${PROTOBUF_MUT_INCLUDE_DIRS})
|
||||||
|
|
||||||
if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
|
if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
|
||||||
# MSVC-specific compiler options
|
# MSVC-specific compiler options
|
||||||
target_compile_options(protobuf-mutator PRIVATE "/wd4244" "/wd4245" "/wd4267" "/wd4100" "/wd4456")
|
target_compile_options(protobuf-mutator PRIVATE "/wd4244" "/wd4245" "/wd4267" "/wd4100" "/wd4456")
|
||||||
|
|
@ -72,14 +73,68 @@ if (onnxruntime_FUZZ_ENABLED)
|
||||||
# add all these include directory to the Fuzzing engine
|
# add all these include directory to the Fuzzing engine
|
||||||
target_include_directories(onnxruntime_security_fuzz PRIVATE ${INCLUDE_FILES})
|
target_include_directories(onnxruntime_security_fuzz PRIVATE ${INCLUDE_FILES})
|
||||||
|
|
||||||
# add link libraries the project
|
# add link libraries to the project
|
||||||
target_link_libraries(onnxruntime_security_fuzz onnx_proto onnxruntime protobuf-mutator ${PROTOBUF_LIB})
|
target_link_libraries(onnxruntime_security_fuzz onnx_proto onnxruntime protobuf-mutator ${PROTOBUF_LIB})
|
||||||
|
|
||||||
# add the dependencies
|
# add the dependencies
|
||||||
add_dependencies(onnxruntime_security_fuzz onnx_proto onnxruntime protobuf-mutator ${PROTOBUF_LIB})
|
add_dependencies(onnxruntime_security_fuzz onnx_proto onnxruntime protobuf-mutator ${PROTOBUF_LIB})
|
||||||
|
|
||||||
# copy the dlls to the execution directory
|
# copy the shared libraries (DLLs on Windows, SOs on Linux) to the execution directory
|
||||||
add_custom_command(TARGET onnxruntime_security_fuzz POST_BUILD
|
add_custom_command(TARGET onnxruntime_security_fuzz POST_BUILD
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_FILE:onnxruntime> $<TARGET_FILE_DIR:onnxruntime_security_fuzz>
|
COMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_FILE:onnxruntime> $<TARGET_FILE_DIR:onnxruntime_security_fuzz>
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_FILE:${PROTOBUF_LIB}> $<TARGET_FILE_DIR:onnxruntime_security_fuzz>)
|
COMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_FILE:${PROTOBUF_LIB}> $<TARGET_FILE_DIR:onnxruntime_security_fuzz>)
|
||||||
|
|
||||||
|
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
||||||
|
# Add a second fuzzer that uses libFuzzer in fuzzer/libfuzzer
|
||||||
|
message(STATUS "Building libProtoBufFuzzer-based fuzzer")
|
||||||
|
|
||||||
|
# Set source files for the libFuzzer
|
||||||
|
set(LIBFUZZER_SRC "${SEC_FUZZ_ROOT}/src/OnnxPrediction.cpp"
|
||||||
|
"${SEC_FUZZ_ROOT}/src/testlog.cpp"
|
||||||
|
"${SEC_FUZZ_ROOT}/ort_libfuzzer/OrtProtoLibfuzzer.cpp")
|
||||||
|
|
||||||
|
# Compile the libFuzzer-based fuzzer
|
||||||
|
onnxruntime_add_executable(onnxruntime_proto_libfuzzer ${LIBFUZZER_SRC})
|
||||||
|
# Security fuzzing engine header file reference
|
||||||
|
onnxruntime_add_include_to_target(onnxruntime_proto_libfuzzer onnx onnxruntime)
|
||||||
|
# Set include directories for libFuzzer
|
||||||
|
target_include_directories(onnxruntime_proto_libfuzzer PRIVATE ${INCLUDE_FILES})
|
||||||
|
|
||||||
|
# Add link libraries for libFuzzer
|
||||||
|
target_link_libraries(onnxruntime_proto_libfuzzer onnx_proto onnxruntime protobuf-mutator protobuf-mutator-libfuzzer -fsanitize=fuzzer,address ${PROTOBUF_LIB})
|
||||||
|
|
||||||
|
# Add the dependencies for libFuzzer
|
||||||
|
add_dependencies(onnxruntime_proto_libfuzzer onnx_proto onnxruntime protobuf-mutator protobuf-mutator-libfuzzer ${PROTOBUF_LIB})
|
||||||
|
|
||||||
|
# Copy shared libraries for libFuzzer
|
||||||
|
add_custom_command(TARGET onnxruntime_proto_libfuzzer POST_BUILD
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_FILE:onnxruntime> $<TARGET_FILE_DIR:onnxruntime_proto_libfuzzer>
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_FILE:${PROTOBUF_LIB}> $<TARGET_FILE_DIR:onnxruntime_proto_libfuzzer>)
|
||||||
|
# Add a second fuzzer that uses libFuzzer in fuzzer/libfuzzer
|
||||||
|
message(STATUS "Building libBufFuzzer-based fuzzer")
|
||||||
|
|
||||||
|
# Set source files for the libFuzzer
|
||||||
|
set(LIBFUZZER_SRC "${SEC_FUZZ_ROOT}/src/OnnxPrediction.cpp"
|
||||||
|
"${SEC_FUZZ_ROOT}/src/testlog.cpp"
|
||||||
|
"${SEC_FUZZ_ROOT}/ort_libfuzzer/OrtLibfuzzer.cpp")
|
||||||
|
|
||||||
|
# Compile the libFuzzer-based fuzzer
|
||||||
|
onnxruntime_add_executable(onnxruntime_libfuzzer_fuzz ${LIBFUZZER_SRC})
|
||||||
|
# Security fuzzing engine header file reference
|
||||||
|
onnxruntime_add_include_to_target(onnxruntime_libfuzzer_fuzz onnx onnxruntime)
|
||||||
|
# Set include directories for libFuzzer
|
||||||
|
target_compile_definitions(onnxruntime_libfuzzer_fuzz PRIVATE GOOGLE_PROTOBUF_NO_LOGGING=1)
|
||||||
|
target_include_directories(onnxruntime_libfuzzer_fuzz PRIVATE ${INCLUDE_FILES})
|
||||||
|
|
||||||
|
# Add link libraries for libFuzzer
|
||||||
|
target_link_libraries(onnxruntime_libfuzzer_fuzz onnx_proto onnxruntime protobuf-mutator protobuf-mutator-libfuzzer -fsanitize=fuzzer,address ${PROTOBUF_LIB})
|
||||||
|
|
||||||
|
# Add the dependencies for libFuzzer
|
||||||
|
add_dependencies(onnxruntime_libfuzzer_fuzz onnx_proto onnxruntime protobuf-mutator protobuf-mutator-libfuzzer ${PROTOBUF_LIB})
|
||||||
|
|
||||||
|
# Copy shared libraries for libFuzzer
|
||||||
|
add_custom_command(TARGET onnxruntime_libfuzzer_fuzz POST_BUILD
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_FILE:onnxruntime> $<TARGET_FILE_DIR:onnxruntime_libfuzzer_fuzz>
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_FILE:${PROTOBUF_LIB}> $<TARGET_FILE_DIR:onnxruntime_libfuzzer_fuzz>)
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
|
||||||
42
onnxruntime/test/fuzzing/ort_libfuzzer/OrtLibfuzzer.cpp
Normal file
42
onnxruntime/test/fuzzing/ort_libfuzzer/OrtLibfuzzer.cpp
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
// Licensed under the MIT License.
|
||||||
|
|
||||||
|
#include "OnnxPrediction.h"
|
||||||
|
#include "onnxruntime_session_options_config_keys.h"
|
||||||
|
#include "src/libfuzzer/libfuzzer_macro.h"
|
||||||
|
#include "fuzzer/FuzzedDataProvider.h"
|
||||||
|
|
||||||
|
Ort::Env env;
|
||||||
|
|
||||||
|
void predict(onnx::ModelProto& msg, unsigned int seed, Ort::Env& env) {
|
||||||
|
// Create object for prediction
|
||||||
|
//
|
||||||
|
OnnxPrediction predict(msg, env);
|
||||||
|
|
||||||
|
// Give predict a function to generate the data
|
||||||
|
// to run prediction on.
|
||||||
|
//
|
||||||
|
predict.SetupInput(GenerateDataForInputTypeTensor, seed);
|
||||||
|
|
||||||
|
// Run the prediction on the data
|
||||||
|
//
|
||||||
|
predict.RunInference();
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||||
|
FuzzedDataProvider data_provider(data, size);
|
||||||
|
onnx::ModelProto msg;
|
||||||
|
try {
|
||||||
|
if (!msg.ParseFromArray(data, static_cast<int>(size))) {
|
||||||
|
return 0; // Ignore invalid inputs
|
||||||
|
}
|
||||||
|
predict(msg, data_provider.ConsumeIntegral<int>(), env);
|
||||||
|
} catch (const std::exception& e) {
|
||||||
|
// Optionally log or suppress the exception
|
||||||
|
// std::cerr << "Caught exception: " << e.what() << std::endl;
|
||||||
|
} catch (...) {
|
||||||
|
// Handle any other exceptions
|
||||||
|
// std::cerr << "Caught unknown exception." << std::endl;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
94
onnxruntime/test/fuzzing/ort_libfuzzer/OrtProtoLibfuzzer.cpp
Normal file
94
onnxruntime/test/fuzzing/ort_libfuzzer/OrtProtoLibfuzzer.cpp
Normal file
|
|
@ -0,0 +1,94 @@
|
||||||
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
// Licensed under the MIT License.
|
||||||
|
|
||||||
|
#include "src/mutator.h"
|
||||||
|
#include "OnnxPrediction.h"
|
||||||
|
#include "onnxruntime_session_options_config_keys.h"
|
||||||
|
#include "src/libfuzzer/libfuzzer_macro.h"
|
||||||
|
#include "onnx/onnx_pb.h"
|
||||||
|
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
Ort::Env env;
|
||||||
|
|
||||||
|
std::string wstring_to_string(const std::wstring& wstr) {
|
||||||
|
std::wstring_convert<std::codecvt_utf8<wchar_t>> converter;
|
||||||
|
return converter.to_bytes(wstr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void predict(onnx::ModelProto& msg, unsigned int seed, Ort::Env& env) {
|
||||||
|
// Create object for prediction
|
||||||
|
//
|
||||||
|
OnnxPrediction predict(msg, env);
|
||||||
|
|
||||||
|
// Give predict a function to generate the data
|
||||||
|
// to run prediction on.
|
||||||
|
//
|
||||||
|
predict.SetupInput(GenerateDataForInputTypeTensor, seed);
|
||||||
|
|
||||||
|
// Run the prediction on the data
|
||||||
|
//
|
||||||
|
predict.RunInference();
|
||||||
|
|
||||||
|
// View the output
|
||||||
|
//
|
||||||
|
predict.PrintOutputValues();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Proto>
|
||||||
|
using PostProcessor =
|
||||||
|
protobuf_mutator::libfuzzer::PostProcessorRegistration<Proto>;
|
||||||
|
|
||||||
|
// Helper function to generate random strings
|
||||||
|
std::string generate_random_string(size_t length, std::mt19937& rng) {
|
||||||
|
const std::string characters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||||
|
std::uniform_int_distribution<> dist(0, characters.size() - 1);
|
||||||
|
std::string result;
|
||||||
|
for (size_t i = 0; i < length; ++i) {
|
||||||
|
result += characters[dist(rng)];
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper function to generate random float
|
||||||
|
float generate_random_float(std::mt19937& rng) {
|
||||||
|
std::uniform_real_distribution<float> dist(0.0f, 1.0f);
|
||||||
|
return dist(rng);
|
||||||
|
}
|
||||||
|
|
||||||
|
// PostProcessor for ONNX ModelProto with random values
|
||||||
|
static PostProcessor<onnx::ModelProto> reg1 = {
|
||||||
|
[](onnx::ModelProto* model_proto, unsigned int seed) {
|
||||||
|
std::mt19937 rng(seed);
|
||||||
|
|
||||||
|
// Set model's IR version
|
||||||
|
model_proto->set_ir_version(7);
|
||||||
|
|
||||||
|
model_proto->set_producer_name("onnx");
|
||||||
|
model_proto->set_producer_version("7.0");
|
||||||
|
model_proto->set_domain("example.com");
|
||||||
|
|
||||||
|
// Add a dummy opset import
|
||||||
|
auto* opset_import = model_proto->add_opset_import();
|
||||||
|
opset_import->set_version(10);
|
||||||
|
|
||||||
|
// Access the graph from the model
|
||||||
|
auto* graph = model_proto->mutable_graph();
|
||||||
|
|
||||||
|
// Set a random name for the graph
|
||||||
|
graph->set_name(generate_random_string(10, rng));
|
||||||
|
}};
|
||||||
|
|
||||||
|
DEFINE_PROTO_FUZZER(const onnx::ModelProto& msg) {
|
||||||
|
try {
|
||||||
|
auto seed = static_cast<unsigned int>(std::chrono::system_clock::now().time_since_epoch().count());
|
||||||
|
onnx::ModelProto msg_proto = msg;
|
||||||
|
predict(msg_proto, seed, env);
|
||||||
|
} catch (const std::exception& e) {
|
||||||
|
// Optionally log or suppress the exception
|
||||||
|
// std::cerr << "Caught exception: " << e.what() << std::endl;
|
||||||
|
} catch (...) {
|
||||||
|
// Handle any other exceptions
|
||||||
|
// std::cerr << "Caught unknown exception." << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue