forked from microsoft/onnxruntime
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Fuzzer] Add two new ORT libfuzzer (Linux clang support for now) (mic…
…rosoft#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.
- Loading branch information
Showing
3 changed files
with
236 additions
and
45 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,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 changes: 94 additions & 0 deletions
94
onnxruntime/test/fuzzing/ort_libfuzzer/OrtProtoLibfuzzer.cpp
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,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; | ||
} | ||
} |