LCOV - code coverage report
Current view: top level - test/fuzzer - wasm-fuzzer-common.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 61 90 67.8 %
Date: 2017-10-20 Functions: 3 3 100.0 %

          Line data    Source code
       1             : // Copyright 2016 the V8 project authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : 
       5             : #include "test/fuzzer/wasm-fuzzer-common.h"
       6             : 
       7             : #include "include/v8.h"
       8             : #include "src/isolate.h"
       9             : #include "src/objects-inl.h"
      10             : #include "src/wasm/module-compiler.h"
      11             : #include "src/wasm/wasm-api.h"
      12             : #include "src/wasm/wasm-module-builder.h"
      13             : #include "src/wasm/wasm-module.h"
      14             : #include "src/zone/accounting-allocator.h"
      15             : #include "src/zone/zone.h"
      16             : #include "test/common/wasm/wasm-module-runner.h"
      17             : #include "test/fuzzer/fuzzer-support.h"
      18             : 
      19             : namespace v8 {
      20             : namespace internal {
      21             : namespace wasm {
      22             : namespace fuzzer {
      23             : 
      24             : static constexpr uint32_t kWasmCodeFuzzerHashSeed = 83;
      25             : 
      26             : static constexpr const char* kNameString = "name";
      27             : static constexpr size_t kNameStringLength = 4;
      28             : 
      29           7 : int FuzzWasmSection(SectionCode section, const uint8_t* data, size_t size) {
      30           7 :   v8_fuzzer::FuzzerSupport* support = v8_fuzzer::FuzzerSupport::Get();
      31           7 :   v8::Isolate* isolate = support->GetIsolate();
      32             :   i::Isolate* i_isolate = reinterpret_cast<Isolate*>(isolate);
      33             : 
      34             :   // Clear any pending exceptions from a prior run.
      35           7 :   if (i_isolate->has_pending_exception()) {
      36             :     i_isolate->clear_pending_exception();
      37             :   }
      38             : 
      39             :   v8::Isolate::Scope isolate_scope(isolate);
      40          14 :   v8::HandleScope handle_scope(isolate);
      41           7 :   v8::Context::Scope context_scope(support->GetContext());
      42          14 :   v8::TryCatch try_catch(isolate);
      43             : 
      44          14 :   AccountingAllocator allocator;
      45          14 :   Zone zone(&allocator, ZONE_NAME);
      46             : 
      47             :   ZoneBuffer buffer(&zone);
      48             :   buffer.write_u32(kWasmMagic);
      49             :   buffer.write_u32(kWasmVersion);
      50           7 :   if (section == kNameSectionCode) {
      51             :     buffer.write_u8(kUnknownSectionCode);
      52           1 :     buffer.write_size(size + kNameStringLength + 1);
      53             :     buffer.write_u8(kNameStringLength);
      54             :     buffer.write(reinterpret_cast<const uint8_t*>(kNameString),
      55           1 :                  kNameStringLength);
      56           1 :     buffer.write(data, size);
      57             :   } else {
      58           6 :     buffer.write_u8(section);
      59           6 :     buffer.write_size(size);
      60           6 :     buffer.write(data, size);
      61             :   }
      62             : 
      63           7 :   ErrorThrower thrower(i_isolate, "decoder");
      64             : 
      65             :   std::unique_ptr<const WasmModule> module(testing::DecodeWasmModuleForTesting(
      66          14 :       i_isolate, &thrower, buffer.begin(), buffer.end(), kWasmOrigin));
      67             : 
      68           7 :   return 0;
      69             : }
      70             : 
      71           2 : void InterpretAndExecuteModule(i::Isolate* isolate,
      72             :                                Handle<WasmModuleObject> module_object) {
      73             :   ScheduledErrorThrower thrower(isolate, "WebAssembly Instantiation");
      74             :   // Try to instantiate and interpret the module_object.
      75             :   MaybeHandle<WasmInstanceObject> maybe_instance =
      76             :       SyncInstantiate(isolate, &thrower, module_object,
      77             :                       Handle<JSReceiver>::null(),     // imports
      78           2 :                       MaybeHandle<JSArrayBuffer>());  // memory
      79             :   Handle<WasmInstanceObject> instance;
      80           4 :   if (!maybe_instance.ToHandle(&instance)) return;
      81           1 :   if (!testing::InterpretWasmModuleForTesting(isolate, instance, "main", 0,
      82           1 :                                               nullptr)) {
      83             :     return;
      84             :   }
      85             : 
      86             :   // Instantiate and execute the module_object.
      87             :   maybe_instance = SyncInstantiate(isolate, &thrower, module_object,
      88             :                                    Handle<JSReceiver>::null(),     // imports
      89           0 :                                    MaybeHandle<JSArrayBuffer>());  // memory
      90           0 :   if (!maybe_instance.ToHandle(&instance)) return;
      91             : 
      92           0 :   testing::RunWasmModuleForTesting(isolate, instance, 0, nullptr);
      93             : }
      94             : 
      95           3 : int WasmExecutionFuzzer::FuzzWasmModule(
      96             :     const uint8_t* data, size_t size) {
      97             :   // Save the flag so that we can change it and restore it later.
      98           3 :   bool generate_test = FLAG_wasm_code_fuzzer_gen_test;
      99           3 :   if (generate_test) {
     100           0 :     OFStream os(stdout);
     101             : 
     102           0 :     os << "// Copyright 2017 the V8 project authors. All rights reserved."
     103             :        << std::endl;
     104             :     os << "// Use of this source code is governed by a BSD-style license that "
     105           0 :           "can be"
     106             :        << std::endl;
     107           0 :     os << "// found in the LICENSE file." << std::endl;
     108             :     os << std::endl;
     109           0 :     os << "load(\"test/mjsunit/wasm/wasm-constants.js\");" << std::endl;
     110           0 :     os << "load(\"test/mjsunit/wasm/wasm-module-builder.js\");" << std::endl;
     111             :     os << std::endl;
     112           0 :     os << "(function() {" << std::endl;
     113           0 :     os << "  var builder = new WasmModuleBuilder();" << std::endl;
     114           0 :     os << "  builder.addMemory(16, 32, false);" << std::endl;
     115           0 :     os << "  builder.addFunction(\"test\", kSig_i_iii)" << std::endl;
     116           0 :     os << "    .addBodyWithEnd([" << std::endl;
     117             :   }
     118           3 :   v8_fuzzer::FuzzerSupport* support = v8_fuzzer::FuzzerSupport::Get();
     119           3 :   v8::Isolate* isolate = support->GetIsolate();
     120             :   i::Isolate* i_isolate = reinterpret_cast<Isolate*>(isolate);
     121             : 
     122             :   // Clear any pending exceptions from a prior run.
     123           3 :   if (i_isolate->has_pending_exception()) {
     124             :     i_isolate->clear_pending_exception();
     125             :   }
     126             : 
     127             :   v8::Isolate::Scope isolate_scope(isolate);
     128           6 :   v8::HandleScope handle_scope(isolate);
     129           3 :   v8::Context::Scope context_scope(support->GetContext());
     130           6 :   v8::TryCatch try_catch(isolate);
     131             :   HandleScope scope(i_isolate);
     132             : 
     133           6 :   AccountingAllocator allocator;
     134           6 :   Zone zone(&allocator, ZONE_NAME);
     135             : 
     136             :   ZoneBuffer buffer(&zone);
     137           3 :   int32_t num_args = 0;
     138           3 :   std::unique_ptr<WasmValue[]> interpreter_args;
     139           3 :   std::unique_ptr<Handle<Object>[]> compiler_args;
     140           3 :   if (!GenerateModule(i_isolate, &zone, data, size, buffer, num_args,
     141           3 :                       interpreter_args, compiler_args)) {
     142             :     return 0;
     143             :   }
     144             : 
     145           2 :   testing::SetupIsolateForWasmModule(i_isolate);
     146             : 
     147           2 :   ErrorThrower interpreter_thrower(i_isolate, "Interpreter");
     148           2 :   ModuleWireBytes wire_bytes(buffer.begin(), buffer.end());
     149             : 
     150             :   MaybeHandle<WasmModuleObject> compiled_module =
     151           2 :       SyncCompile(i_isolate, &interpreter_thrower, wire_bytes);
     152             :   // Clear the flag so that the WebAssembly code is not printed twice.
     153           2 :   FLAG_wasm_code_fuzzer_gen_test = false;
     154           2 :   bool compiles = !compiled_module.is_null();
     155             : 
     156           2 :   if (generate_test) {
     157           0 :     OFStream os(stdout);
     158           0 :     os << "            ])" << std::endl
     159           0 :        << "            .exportFunc();" << std::endl;
     160           0 :     if (compiles) {
     161           0 :       os << "  var module = builder.instantiate();" << std::endl
     162           0 :          << "  module.exports.test(1, 2, 3);" << std::endl;
     163             :     } else {
     164           0 :       OFStream os(stdout);
     165           0 :       os << "  assertThrows(function() { builder.instantiate(); });"
     166           0 :          << std::endl;
     167             :     }
     168           0 :     os << "})();" << std::endl;
     169             :   }
     170             : 
     171           2 :   bool validates = SyncValidate(i_isolate, wire_bytes);
     172             : 
     173           2 :   if (compiles != validates) {
     174             :     uint32_t hash = StringHasher::HashSequentialString(
     175           0 :         data, static_cast<int>(size), kWasmCodeFuzzerHashSeed);
     176             :     V8_Fatal(__FILE__, __LINE__,
     177             :              "compiles != validates (%d vs %d); WasmCodeFuzzerHash=%x",
     178           0 :              compiles, validates, hash);
     179             :   }
     180             : 
     181           2 :   if (!compiles) return 0;
     182             : 
     183             :   int32_t result_interpreted;
     184           1 :   bool possible_nondeterminism = false;
     185             :   {
     186             :     MaybeHandle<WasmInstanceObject> interpreter_instance = SyncInstantiate(
     187             :         i_isolate, &interpreter_thrower, compiled_module.ToHandleChecked(),
     188           1 :         MaybeHandle<JSReceiver>(), MaybeHandle<JSArrayBuffer>());
     189             : 
     190           1 :     if (interpreter_thrower.error()) {
     191           0 :       return 0;
     192             :     }
     193             :     result_interpreted = testing::InterpretWasmModule(
     194             :         i_isolate, interpreter_instance.ToHandleChecked(), &interpreter_thrower,
     195           1 :         0, interpreter_args.get(), &possible_nondeterminism);
     196             :   }
     197             : 
     198             :   // Do not execute the generated code if the interpreter did not finished after
     199             :   // a bounded number of steps.
     200           1 :   if (interpreter_thrower.error()) {
     201             :     return 0;
     202             :   }
     203             : 
     204             :   int32_t result_compiled;
     205             :   {
     206             :     ErrorThrower compiler_thrower(i_isolate, "Compiler");
     207             :     MaybeHandle<WasmInstanceObject> compiled_instance = SyncInstantiate(
     208             :         i_isolate, &compiler_thrower, compiled_module.ToHandleChecked(),
     209           1 :         MaybeHandle<JSReceiver>(), MaybeHandle<JSArrayBuffer>());
     210             : 
     211             :     DCHECK(!compiler_thrower.error());
     212             :     result_compiled = testing::CallWasmFunctionForTesting(
     213             :         i_isolate, compiled_instance.ToHandleChecked(), &compiler_thrower,
     214           2 :         "main", num_args, compiler_args.get());
     215             :   }
     216             : 
     217             :   // The WebAssembly spec allows the sign bit of NaN to be non-deterministic.
     218             :   // This sign bit may cause result_interpreted to be different than
     219             :   // result_compiled. Therefore we do not check the equality of the results
     220             :   // if the execution may have produced a NaN at some point.
     221           1 :   if (possible_nondeterminism) return 0;
     222             : 
     223           1 :   if (result_interpreted == bit_cast<int32_t>(0xdeadbeef)) {
     224           0 :     CHECK(i_isolate->has_pending_exception());
     225             :     i_isolate->clear_pending_exception();
     226             :   } else {
     227           1 :     CHECK(!i_isolate->has_pending_exception());
     228           1 :     if (result_interpreted != result_compiled) {
     229             :       V8_Fatal(__FILE__, __LINE__, "WasmCodeFuzzerHash=%x",
     230             :                StringHasher::HashSequentialString(data, static_cast<int>(size),
     231           0 :                                                   kWasmCodeFuzzerHashSeed));
     232             :     }
     233             :   }
     234             :   return 0;
     235             : }
     236             : 
     237             : }  // namespace fuzzer
     238             : }  // namespace wasm
     239             : }  // namespace internal
     240             : }  // namespace v8

Generated by: LCOV version 1.10