| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| #include <cstddef> |
| #include <cstdint> |
| #include <vector> |
|
|
| #include <executorch/extension/data_loader/buffer_data_loader.h> |
| #include <executorch/runtime/backend/interface.h> |
| #include <executorch/runtime/executor/method.h> |
| #include <executorch/runtime/executor/program.h> |
| #include <executorch/runtime/core/memory_allocator.h> |
| #include <executorch/runtime/core/hierarchical_allocator.h> |
| #include <executorch/runtime/executor/memory_manager.h> |
| #include <executorch/runtime/kernel/operator_registry.h> |
| #include <executorch/runtime/kernel/kernel_runtime_context.h> |
| #include <executorch/runtime/platform/runtime.h> |
|
|
| using executorch::extension::BufferDataLoader; |
| using executorch::runtime::Program; |
| using executorch::runtime::Method; |
| using executorch::runtime::MemoryAllocator; |
| using executorch::runtime::HierarchicalAllocator; |
| using executorch::runtime::MemoryManager; |
| using executorch::runtime::Span; |
| using executorch::runtime::EValue; |
| using executorch::runtime::Error; |
| using executorch::runtime::Result; |
| using executorch::runtime::KernelRuntimeContext; |
| using executorch::runtime::Kernel; |
| using executorch::runtime::register_kernels; |
| using executorch::runtime::BackendInterface; |
| using executorch::runtime::Backend; |
| using executorch::runtime::register_backend; |
| using executorch::runtime::DelegateHandle; |
| using executorch::runtime::FreeableBuffer; |
| using executorch::runtime::ArrayRef; |
| using executorch::runtime::CompileSpec; |
| using executorch::runtime::BackendInitContext; |
| using executorch::runtime::BackendExecutionContext; |
|
|
| |
| |
| |
| void always_fail_kernel(KernelRuntimeContext& context, Span<EValue*> ) { |
| context.fail(Error::Internal); |
| } |
|
|
| |
| |
| class FuzzTestBackend final : public BackendInterface { |
| public: |
| bool is_available() const override { |
| return true; |
| } |
| Result<DelegateHandle*> init( |
| BackendInitContext& , |
| FreeableBuffer* , |
| ArrayRef<CompileSpec> ) const override { |
| return static_cast<DelegateHandle*>(nullptr); |
| } |
| Error execute( |
| BackendExecutionContext& , |
| DelegateHandle* , |
| Span<EValue*> ) const override { |
| return Error::Ok; |
| } |
| }; |
|
|
| static bool g_initialized = false; |
| static FuzzTestBackend* g_backend = nullptr; |
|
|
| extern "C" int LLVMFuzzerTestOneInput(const std::uint8_t* data, std::size_t size) { |
| if (!g_initialized) { |
| executorch::runtime::runtime_init(); |
|
|
| |
| |
| |
| |
| static const Kernel kernels[] = { |
| Kernel("aten::add.out", always_fail_kernel), |
| Kernel("aten::add.Tensor_out", always_fail_kernel), |
| Kernel("aten::mul.out", always_fail_kernel), |
| Kernel("aten::mul.Tensor_out", always_fail_kernel), |
| Kernel("aten::sub.out", always_fail_kernel), |
| Kernel("aten::relu.out", always_fail_kernel), |
| Kernel("aten::linear.out", always_fail_kernel), |
| Kernel("aten::cat.out", always_fail_kernel), |
| Kernel("aten::view_copy.out", always_fail_kernel), |
| Kernel("aten::index.Tensor_out", always_fail_kernel), |
| Kernel("aten::_softmax.out", always_fail_kernel), |
| Kernel("aten::convolution.out", always_fail_kernel), |
| Kernel("aten::permute_copy.out", always_fail_kernel), |
| Kernel("aten::_to_copy.out", always_fail_kernel), |
| |
| |
| |
| |
| Kernel("aten::add", always_fail_kernel), |
| Kernel("aten::mul", always_fail_kernel), |
| Kernel("aten::sub", always_fail_kernel), |
| Kernel("aten::relu", always_fail_kernel), |
| Kernel("aten::linear", always_fail_kernel), |
| Kernel("aten::cat", always_fail_kernel), |
| Kernel("test_op", always_fail_kernel), |
| Kernel("test_op_no_overload", always_fail_kernel), |
| }; |
| register_kernels({kernels, sizeof(kernels) / sizeof(kernels[0])}); |
|
|
| static FuzzTestBackend backend_instance; |
| g_backend = &backend_instance; |
| static const char* backend_names[] = { |
| "XnnpackBackend", "CoreMLBackend", "QnnBackend", |
| "VulkanBackend", "MPSBackend", "TCE0", "TCE1"}; |
| for (const char* name : backend_names) { |
| register_backend(Backend{name, g_backend}); |
| } |
|
|
| g_initialized = true; |
| } |
|
|
| constexpr std::size_t kMaxInput = 8U * 1024U * 1024U; |
| if (data == nullptr || size == 0 || size > kMaxInput) { |
| return 0; |
| } |
|
|
| BufferDataLoader loader(data, size); |
| auto program = Program::load(&loader, Program::Verification::InternalConsistency); |
| if (!program.ok()) { |
| return 0; |
| } |
|
|
| static std::vector<uint8_t> method_pool(512 * 1024); |
| static std::vector<uint8_t> planned_pool(256 * 1024); |
| MemoryAllocator method_allocator(method_pool.size(), method_pool.data()); |
| static Span<uint8_t> planned_span(planned_pool.data(), planned_pool.size()); |
| HierarchicalAllocator planned_memory({&planned_span, 1}); |
| MemoryManager mm(&method_allocator, &planned_memory, nullptr); |
|
|
| auto& p = program.get(); |
| auto n = p.num_methods(); |
| for (size_t i = 0; i < n; ++i) { |
| auto name = p.get_method_name(i); |
| if (!name.ok()) continue; |
| auto method = p.load_method(name.get(), &mm); |
| if (!method.ok()) { |
| #ifdef ET_FUZZ_DEBUG |
| fprintf(stderr, "[dbg] load_method failed: 0x%x\n", |
| static_cast<unsigned int>(method.error())); |
| #endif |
| continue; |
| } |
| |
| |
| |
| |
| auto& m = method.get(); |
| auto exec_err = m.execute(); |
| #ifdef ET_FUZZ_DEBUG |
| fprintf(stderr, "[dbg] execute() returned: 0x%x\n", |
| static_cast<unsigned int>(exec_err)); |
| #endif |
| (void)exec_err; |
| } |
| return 0; |
| } |
|
|