|
13 | 13 |
|
14 | 14 | using namespace std;
|
15 | 15 |
|
| 16 | +static bool |
| 17 | +is_supported_val_kind(wasm_valkind_t kind) |
| 18 | +{ |
| 19 | + return kind == WASM_I32 || kind == WASM_I64 || kind == WASM_F32 |
| 20 | + || kind == WASM_F64 || kind == WASM_EXTERNREF |
| 21 | + || kind == WASM_FUNCREF; |
| 22 | +} |
| 23 | + |
| 24 | +static wasm_val_t |
| 25 | +pre_defined_val(wasm_valkind_t kind) |
| 26 | +{ |
| 27 | + if (kind == WASM_I32) { |
| 28 | + return wasm_val_t{ .kind = WASM_I32, .of = { .i32 = 2025 } }; |
| 29 | + } |
| 30 | + else if (kind == WASM_I64) { |
| 31 | + return wasm_val_t{ .kind = WASM_I64, .of = { .i64 = 168 } }; |
| 32 | + } |
| 33 | + else if (kind == WASM_F32) { |
| 34 | + return wasm_val_t{ .kind = WASM_F32, .of = { .f32 = 3.14159f } }; |
| 35 | + } |
| 36 | + else if (kind == WASM_F64) { |
| 37 | + return wasm_val_t{ .kind = WASM_F64, .of = { .f64 = 2.71828 } }; |
| 38 | + } |
| 39 | + else if (kind == WASM_EXTERNREF) { |
| 40 | + return wasm_val_t{ .kind = WASM_EXTERNREF, |
| 41 | + .of = { .foreign = 0xabcddead } }; |
| 42 | + } |
| 43 | + // because aft is_supported_val_kind() check, so we can safely return as |
| 44 | + // WASM_FUNCREF |
| 45 | + else { |
| 46 | + return wasm_val_t{ .kind = WASM_FUNCREF, .of = { .ref = nullptr } }; |
| 47 | + } |
| 48 | +} |
| 49 | +void |
| 50 | +print_execution_args(const wasm_export_t &export_type, |
| 51 | + const std::vector<wasm_val_t> &args, unsigned param_count) |
| 52 | +{ |
| 53 | + std::cout << "[EXECUTION] " << export_type.name << "("; |
| 54 | + for (unsigned p_i = 0; p_i < param_count; p_i++) { |
| 55 | + if (p_i != 0) { |
| 56 | + std::cout << ", "; |
| 57 | + } |
| 58 | + |
| 59 | + switch (args[p_i].kind) { |
| 60 | + case WASM_I32: |
| 61 | + std::cout << "i32:" << args[p_i].of.i32; |
| 62 | + break; |
| 63 | + case WASM_I64: |
| 64 | + std::cout << "i64:" << args[p_i].of.i64; |
| 65 | + break; |
| 66 | + case WASM_F32: |
| 67 | + std::cout << "f32:" << args[p_i].of.f32; |
| 68 | + break; |
| 69 | + case WASM_F64: |
| 70 | + std::cout << "f64:" << args[p_i].of.f64; |
| 71 | + break; |
| 72 | + case WASM_EXTERNREF: |
| 73 | + std::cout << "externref:" << args[p_i].of.foreign; |
| 74 | + break; |
| 75 | + default: |
| 76 | + // because aft is_supported_val_kind() check, so we can safely |
| 77 | + // return as WASM_FUNCREF |
| 78 | + std::cout << "funcref:" << args[p_i].of.ref; |
| 79 | + break; |
| 80 | + } |
| 81 | + } |
| 82 | + std::cout << ")" << std::endl; |
| 83 | +} |
| 84 | + |
| 85 | +static bool |
| 86 | +execute_export_functions(wasm_module_t module, wasm_module_inst_t inst) |
| 87 | +{ |
| 88 | + int32_t export_count = wasm_runtime_get_export_count(module); |
| 89 | + |
| 90 | + for (int e_i = 0; e_i < export_count; e_i++) { |
| 91 | + wasm_export_t export_type = { 0 }; |
| 92 | + wasm_runtime_get_export_type(module, e_i, &export_type); |
| 93 | + |
| 94 | + if (export_type.kind != WASM_IMPORT_EXPORT_KIND_FUNC) { |
| 95 | + continue; |
| 96 | + } |
| 97 | + |
| 98 | + wasm_function_inst_t func = |
| 99 | + wasm_runtime_lookup_function(inst, export_type.name); |
| 100 | + if (!func) { |
| 101 | + std::cout << "Failed to lookup function: " << export_type.name |
| 102 | + << std::endl; |
| 103 | + continue; |
| 104 | + } |
| 105 | + |
| 106 | + wasm_func_type_t func_type = export_type.u.func_type; |
| 107 | + uint32_t param_count = wasm_func_type_get_param_count(func_type); |
| 108 | + |
| 109 | + /* build arguments */ |
| 110 | + std::vector<wasm_val_t> args; |
| 111 | + for (unsigned p_i = 0; p_i < param_count; p_i++) { |
| 112 | + wasm_valkind_t param_type = |
| 113 | + wasm_func_type_get_param_valkind(func_type, p_i); |
| 114 | + |
| 115 | + if (!is_supported_val_kind(param_type)) { |
| 116 | + std::cout |
| 117 | + << "Bypass execution because of unsupported value kind: " |
| 118 | + << param_type << std::endl; |
| 119 | + return true; |
| 120 | + } |
| 121 | + |
| 122 | + wasm_val_t arg = pre_defined_val(param_type); |
| 123 | + args.push_back(arg); |
| 124 | + } |
| 125 | + |
| 126 | + /* build results storage */ |
| 127 | + uint32_t result_count = wasm_func_type_get_result_count(func_type); |
| 128 | + std::vector<wasm_val_t> results = std::vector<wasm_val_t>(result_count); |
| 129 | + |
| 130 | + print_execution_args(export_type, args, param_count); |
| 131 | + |
| 132 | + /* execute the function */ |
| 133 | + wasm_exec_env_t exec_env = wasm_runtime_get_exec_env_singleton(inst); |
| 134 | + if (!exec_env) { |
| 135 | + std::cout << "Failed to get exec env" << std::endl; |
| 136 | + return false; |
| 137 | + } |
| 138 | + |
| 139 | + bool ret = wasm_runtime_call_wasm_a(exec_env, func, result_count, |
| 140 | + results.data(), param_count, args.data()); |
| 141 | + if (!ret) { |
| 142 | + const char *exception = wasm_runtime_get_exception(inst); |
| 143 | + if (!exception) { |
| 144 | + std::cout << "[EXECUTION] " << export_type.name |
| 145 | + << "() failed. No exception info." << std::endl; |
| 146 | + } |
| 147 | + else { |
| 148 | + std::cout << "[EXECUTION] " << export_type.name << "() failed. " |
| 149 | + << exception << std::endl; |
| 150 | + } |
| 151 | + } |
| 152 | + |
| 153 | + wasm_runtime_clear_exception(inst); |
| 154 | + } |
| 155 | + |
| 156 | + return true; |
| 157 | +} |
| 158 | + |
16 | 159 | extern "C" int
|
17 | 160 | LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size)
|
18 | 161 | {
|
@@ -43,7 +186,7 @@ LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size)
|
43 | 186 | return 0;
|
44 | 187 | }
|
45 | 188 |
|
46 |
| - std::cout << "PASS" << std::endl; |
| 189 | + execute_export_functions(module, inst); |
47 | 190 |
|
48 | 191 | wasm_runtime_deinstantiate(inst);
|
49 | 192 | wasm_runtime_unload(module);
|
|
0 commit comments