File size: 3,698 Bytes
3bfbf53
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
// libFuzzer harness for executorch::runtime::Program::load()
// Targets the .pte flatbuffer parsing path (runtime/executor/program.cpp).
// Authorized local testing only - huntr MFV scope: ExecuTorch .pte parser.

#include <cstddef>
#include <cstdint>

#include <executorch/extension/data_loader/buffer_data_loader.h>
#include <executorch/runtime/executor/program.h>
#include <executorch/runtime/platform/runtime.h>

using executorch::extension::BufferDataLoader;
using executorch::runtime::Program;

static bool g_initialized = false;

extern "C" int LLVMFuzzerTestOneInput(const std::uint8_t* data, std::size_t size) {
  if (!g_initialized) {
    executorch::runtime::runtime_init();
    g_initialized = true;
  }

  constexpr std::size_t kMaxInput = 32U * 1024U * 1024U;
  if (data == nullptr || size == 0 || size > kMaxInput) {
    return 0;
  }

  BufferDataLoader loader(data, size);

  // Try both verification levels - Minimal is the one used in perf-sensitive
  // deployments and skips more validation than InternalConsistency.
  auto program_ic = Program::load(&loader, Program::Verification::InternalConsistency);
  if (getenv("ET_FUZZ_DEBUG")) {
    fprintf(stderr, "[dbg] IC program.ok()=%d", program_ic.ok());
    if (!program_ic.ok()) {
      fprintf(stderr, " error=0x%x", static_cast<unsigned int>(program_ic.error()));
    } else {
      fprintf(stderr, " num_methods=%zu", program_ic.get().num_methods());
    }
    fprintf(stderr, "\n");
    BufferDataLoader loader2(data, size);
    auto program_min = Program::load(&loader2, Program::Verification::Minimal);
    fprintf(stderr, "[dbg] Minimal program.ok()=%d", program_min.ok());
    if (!program_min.ok()) {
      fprintf(stderr, " error=0x%x", static_cast<unsigned int>(program_min.error()));
    } else {
      fprintf(stderr, " num_methods=%zu", program_min.get().num_methods());
    }
    fprintf(stderr, "\n");
  }
  if (program_ic.ok()) {
    // Touch metadata to exercise more of the parsing surface.
    auto& p = program_ic.get();
    auto n = p.num_methods();
    for (size_t i = 0; i < n; ++i) {
      auto name = p.get_method_name(i);
      if (name.ok()) {
        auto meta = p.method_meta(name.get());
        if (meta.ok()) {
          auto& m = meta.get();
          (void)m.name();
          (void)m.num_inputs();
          (void)m.num_outputs();
          (void)m.num_attributes();
          (void)m.num_memory_planned_buffers();
          (void)m.num_instructions();
          // uses_backend()/num_backends()/get_backend_name() exercise the
          // ExecutionPlan::delegates() optional field - not guarded against
          // null in uses_backend() per source review.
          (void)m.uses_backend("XNNPACK");
          (void)m.uses_backend("");
          size_t nb = m.num_backends();
          for (size_t bi = 0; bi < nb; ++bi) {
            (void)m.get_backend_name(bi);
          }
          size_t na = m.num_attributes();
          for (size_t ai = 0; ai < na && ai < 64; ++ai) {
            (void)m.attribute_tensor_meta(ai);
          }
          size_t ni = m.num_inputs();
          for (size_t ii = 0; ii < ni && ii < 64; ++ii) {
            (void)m.input_tag(ii);
            (void)m.input_tensor_meta(ii);
          }
          size_t no = m.num_outputs();
          for (size_t oi = 0; oi < no && oi < 64; ++oi) {
            (void)m.output_tag(oi);
            (void)m.output_tensor_meta(oi);
          }
          size_t nmb = m.num_memory_planned_buffers();
          for (size_t mi = 0; mi < nmb && mi < 64; ++mi) {
            (void)m.memory_planned_buffer_size(mi);
            (void)m.memory_planned_buffer_device(mi);
          }
        }
      }
    }
  }

  return 0;
}