tsk-arasu commited on
Commit
efdb2b1
·
verified ·
1 Parent(s): 20e1dcc

Upload poc/harness_execute_fuzzer.cpp with huggingface_hub

Browse files
Files changed (1) hide show
  1. poc/harness_execute_fuzzer.cpp +174 -0
poc/harness_execute_fuzzer.cpp ADDED
@@ -0,0 +1,174 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // libFuzzer harness for Program::load_method() + Method::execute().
2
+ // Registers a fake kernel (for every op name that might appear) that ALWAYS
3
+ // calls context.fail(), to deterministically exercise the KernelCall failure
4
+ // logging path in Method::execute_instruction() - specifically testing
5
+ // whether op->overload()->c_str() is dereferenced unconditionally when
6
+ // overload is null (optional per schema).
7
+ //
8
+ // Also registers a fake backend (matching common backend id strings) whose
9
+ // init()/execute() are minimal, to exercise BackendDelegate::Init() and
10
+ // GetProcessedData() paths without requiring a real backend implementation.
11
+ #include <cstddef>
12
+ #include <cstdint>
13
+ #include <vector>
14
+
15
+ #include <executorch/extension/data_loader/buffer_data_loader.h>
16
+ #include <executorch/runtime/backend/interface.h>
17
+ #include <executorch/runtime/executor/method.h>
18
+ #include <executorch/runtime/executor/program.h>
19
+ #include <executorch/runtime/core/memory_allocator.h>
20
+ #include <executorch/runtime/core/hierarchical_allocator.h>
21
+ #include <executorch/runtime/executor/memory_manager.h>
22
+ #include <executorch/runtime/kernel/operator_registry.h>
23
+ #include <executorch/runtime/kernel/kernel_runtime_context.h>
24
+ #include <executorch/runtime/platform/runtime.h>
25
+
26
+ using executorch::extension::BufferDataLoader;
27
+ using executorch::runtime::Program;
28
+ using executorch::runtime::Method;
29
+ using executorch::runtime::MemoryAllocator;
30
+ using executorch::runtime::HierarchicalAllocator;
31
+ using executorch::runtime::MemoryManager;
32
+ using executorch::runtime::Span;
33
+ using executorch::runtime::EValue;
34
+ using executorch::runtime::Error;
35
+ using executorch::runtime::Result;
36
+ using executorch::runtime::KernelRuntimeContext;
37
+ using executorch::runtime::Kernel;
38
+ using executorch::runtime::register_kernels;
39
+ using executorch::runtime::BackendInterface;
40
+ using executorch::runtime::Backend;
41
+ using executorch::runtime::register_backend;
42
+ using executorch::runtime::DelegateHandle;
43
+ using executorch::runtime::FreeableBuffer;
44
+ using executorch::runtime::ArrayRef;
45
+ using executorch::runtime::CompileSpec;
46
+ using executorch::runtime::BackendInitContext;
47
+ using executorch::runtime::BackendExecutionContext;
48
+
49
+ // A kernel that always fails - forces Method::execute_instruction()'s
50
+ // KernelCall failure-logging path (which dereferences op->overload()) on
51
+ // EVERY KernelCall instruction, regardless of which operator is named.
52
+ void always_fail_kernel(KernelRuntimeContext& context, Span<EValue*> /*args*/) {
53
+ context.fail(Error::Internal);
54
+ }
55
+
56
+ // A minimal backend that succeeds trivially, to exercise
57
+ // BackendDelegate::Init()/GetProcessedData() without needing a real backend.
58
+ class FuzzTestBackend final : public BackendInterface {
59
+ public:
60
+ bool is_available() const override {
61
+ return true;
62
+ }
63
+ Result<DelegateHandle*> init(
64
+ BackendInitContext& /*context*/,
65
+ FreeableBuffer* /*processed*/,
66
+ ArrayRef<CompileSpec> /*compile_specs*/) const override {
67
+ return static_cast<DelegateHandle*>(nullptr);
68
+ }
69
+ Error execute(
70
+ BackendExecutionContext& /*context*/,
71
+ DelegateHandle* /*handle*/,
72
+ Span<EValue*> /*args*/) const override {
73
+ return Error::Ok;
74
+ }
75
+ };
76
+
77
+ static bool g_initialized = false;
78
+ static FuzzTestBackend* g_backend = nullptr;
79
+
80
+ extern "C" int LLVMFuzzerTestOneInput(const std::uint8_t* data, std::size_t size) {
81
+ if (!g_initialized) {
82
+ executorch::runtime::runtime_init();
83
+
84
+ // Register a wildcard-ish set of fallback kernels for common op names
85
+ // seen in the seed corpus, all pointing to always_fail_kernel. We can't
86
+ // truly wildcard-match in this registry, so register kernels for the
87
+ // most common ops that appear in the existing .pte seed corpus.
88
+ static const Kernel kernels[] = {
89
+ Kernel("aten::add.out", always_fail_kernel),
90
+ Kernel("aten::add.Tensor_out", always_fail_kernel),
91
+ Kernel("aten::mul.out", always_fail_kernel),
92
+ Kernel("aten::mul.Tensor_out", always_fail_kernel),
93
+ Kernel("aten::sub.out", always_fail_kernel),
94
+ Kernel("aten::relu.out", always_fail_kernel),
95
+ Kernel("aten::linear.out", always_fail_kernel),
96
+ Kernel("aten::cat.out", always_fail_kernel),
97
+ Kernel("aten::view_copy.out", always_fail_kernel),
98
+ Kernel("aten::index.Tensor_out", always_fail_kernel),
99
+ Kernel("aten::_softmax.out", always_fail_kernel),
100
+ Kernel("aten::convolution.out", always_fail_kernel),
101
+ Kernel("aten::permute_copy.out", always_fail_kernel),
102
+ Kernel("aten::_to_copy.out", always_fail_kernel),
103
+ // No-overload variants: matches Operator entries whose `overload`
104
+ // field is null/absent, which is the specific condition needed to
105
+ // test whether Method::execute_instruction()'s KernelCall failure
106
+ // path dereferences op->overload() unconditionally.
107
+ Kernel("aten::add", always_fail_kernel),
108
+ Kernel("aten::mul", always_fail_kernel),
109
+ Kernel("aten::sub", always_fail_kernel),
110
+ Kernel("aten::relu", always_fail_kernel),
111
+ Kernel("aten::linear", always_fail_kernel),
112
+ Kernel("aten::cat", always_fail_kernel),
113
+ Kernel("test_op", always_fail_kernel),
114
+ Kernel("test_op_no_overload", always_fail_kernel),
115
+ };
116
+ register_kernels({kernels, sizeof(kernels) / sizeof(kernels[0])});
117
+
118
+ static FuzzTestBackend backend_instance;
119
+ g_backend = &backend_instance;
120
+ static const char* backend_names[] = {
121
+ "XnnpackBackend", "CoreMLBackend", "QnnBackend",
122
+ "VulkanBackend", "MPSBackend", "TCE0", "TCE1"};
123
+ for (const char* name : backend_names) {
124
+ register_backend(Backend{name, g_backend});
125
+ }
126
+
127
+ g_initialized = true;
128
+ }
129
+
130
+ constexpr std::size_t kMaxInput = 8U * 1024U * 1024U;
131
+ if (data == nullptr || size == 0 || size > kMaxInput) {
132
+ return 0;
133
+ }
134
+
135
+ BufferDataLoader loader(data, size);
136
+ auto program = Program::load(&loader, Program::Verification::InternalConsistency);
137
+ if (!program.ok()) {
138
+ return 0;
139
+ }
140
+
141
+ static std::vector<uint8_t> method_pool(512 * 1024);
142
+ static std::vector<uint8_t> planned_pool(256 * 1024);
143
+ MemoryAllocator method_allocator(method_pool.size(), method_pool.data());
144
+ static Span<uint8_t> planned_span(planned_pool.data(), planned_pool.size());
145
+ HierarchicalAllocator planned_memory({&planned_span, 1});
146
+ MemoryManager mm(&method_allocator, &planned_memory, nullptr);
147
+
148
+ auto& p = program.get();
149
+ auto n = p.num_methods();
150
+ for (size_t i = 0; i < n; ++i) {
151
+ auto name = p.get_method_name(i);
152
+ if (!name.ok()) continue;
153
+ auto method = p.load_method(name.get(), &mm);
154
+ if (!method.ok()) {
155
+ #ifdef ET_FUZZ_DEBUG
156
+ fprintf(stderr, "[dbg] load_method failed: 0x%x\n",
157
+ static_cast<unsigned int>(method.error()));
158
+ #endif
159
+ continue;
160
+ }
161
+ // Attempt to set trivial inputs where possible, then execute. We don't
162
+ // try hard to satisfy every possible input shape - we're hunting for
163
+ // crashes during initialization and the KernelCall failure path, not
164
+ // testing correct numerical execution.
165
+ auto& m = method.get();
166
+ auto exec_err = m.execute();
167
+ #ifdef ET_FUZZ_DEBUG
168
+ fprintf(stderr, "[dbg] execute() returned: 0x%x\n",
169
+ static_cast<unsigned int>(exec_err));
170
+ #endif
171
+ (void)exec_err;
172
+ }
173
+ return 0;
174
+ }