From 1e7db7f0a8c59244471ac2e09a9356c08cab8f5a Mon Sep 17 00:00:00 2001 From: Yuta Saito Date: Wed, 23 Oct 2024 14:03:16 +0900 Subject: [PATCH] Fuzzing: Update FuzzTranslator to instantiate modules explicitly --- FuzzTesting/Package.swift | 4 ++ .../FuzzTranslator/FuzzTranslator.swift | 4 +- .../WasmKitFuzzing/WasmKitFuzzing.swift | 41 +++++++++++++++++++ Package.swift | 7 +++- Sources/WasmKit/Module.swift | 13 +----- .../FuzzTranslatorRegressionTests.swift | 29 ++----------- 6 files changed, 59 insertions(+), 39 deletions(-) create mode 100644 FuzzTesting/Sources/WasmKitFuzzing/WasmKitFuzzing.swift diff --git a/FuzzTesting/Package.swift b/FuzzTesting/Package.swift index dadf2222..ce94b654 100644 --- a/FuzzTesting/Package.swift +++ b/FuzzTesting/Package.swift @@ -31,6 +31,7 @@ let package = Package( ], targets: [ .target(name: "FuzzTranslator", dependencies: [ + "WasmKitFuzzing", .product(name: "WasmKit", package: "WasmKit") ]), .target(name: "FuzzExecute", dependencies: [ @@ -42,5 +43,8 @@ let package = Package( "WasmCAPI", ]), .target(name: "WasmCAPI"), + .target(name: "WasmKitFuzzing", dependencies: [ + .product(name: "WasmKit", package: "WasmKit"), + ]) ] ) diff --git a/FuzzTesting/Sources/FuzzTranslator/FuzzTranslator.swift b/FuzzTesting/Sources/FuzzTranslator/FuzzTranslator.swift index 80ffb15b..0423eee6 100644 --- a/FuzzTesting/Sources/FuzzTranslator/FuzzTranslator.swift +++ b/FuzzTesting/Sources/FuzzTranslator/FuzzTranslator.swift @@ -1,11 +1,11 @@ import WasmKit +import WasmKitFuzzing @_cdecl("LLVMFuzzerTestOneInput") public func FuzzCheck(_ start: UnsafePointer, _ count: Int) -> CInt { let bytes = Array(UnsafeBufferPointer(start: start, count: count)) do { - var module = try WasmKit.parseWasm(bytes: bytes) - try module.materializeAll() + try fuzzInstantiation(bytes: bytes) } catch { // Ignore errors } diff --git a/FuzzTesting/Sources/WasmKitFuzzing/WasmKitFuzzing.swift b/FuzzTesting/Sources/WasmKitFuzzing/WasmKitFuzzing.swift new file mode 100644 index 00000000..f3362da7 --- /dev/null +++ b/FuzzTesting/Sources/WasmKitFuzzing/WasmKitFuzzing.swift @@ -0,0 +1,41 @@ +// This module defines utilities for fuzzing WasmKit. + +import WasmKit + +/// Check if a Wasm module can be instantiated without crashing. +/// +/// - Parameter bytes: The bytes of the Wasm module. +public func fuzzInstantiation(bytes: [UInt8]) throws { + let module = try WasmKit.parseWasm(bytes: bytes) + let engine = Engine(configuration: EngineConfiguration(compilationMode: .eager)) + let store = Store(engine: engine) + + // Prepare dummy imports + var imports = Imports() + for importEntry in module.imports { + let value: ExternalValueConvertible + switch importEntry.descriptor { + case .function(let typeIndex): + guard typeIndex < module.types.count else { + // Skip if import type index is out of bounds + return + } + let type = module.types[Int(typeIndex)] + value = Function(store: store, type: type) { _, _ in + // Provide "start function" with empty results + if type.results.isEmpty { return [] } + fatalError("Unexpected function call") + } + case .global(let globalType): + value = try Global(store: store, type: globalType, value: .i32(0)) + case .memory(let memoryType): + value = try Memory(store: store, type: memoryType) + case .table(let tableType): + value = try Table(store: store, type: tableType) + } + imports.define(module: importEntry.module, name: importEntry.name, value.externalValue) + } + + // Instantiate the module + _ = try module.instantiate(store: store, imports: imports) +} diff --git a/Package.swift b/Package.swift index 983a4150..b7cdf734 100644 --- a/Package.swift +++ b/Package.swift @@ -48,9 +48,14 @@ let package = Package( exclude: ["CMakeLists.txt"] ), .target(name: "_CWasmKit"), + .target( + name: "WasmKitFuzzing", + dependencies: ["WasmKit"], + path: "FuzzTesting/Sources/WasmKitFuzzing" + ), .testTarget( name: "WasmKitTests", - dependencies: ["WasmKit", "WAT"], + dependencies: ["WasmKit", "WAT", "WasmKitFuzzing"], exclude: ["ExtraSuite"] ), diff --git a/Sources/WasmKit/Module.swift b/Sources/WasmKit/Module.swift index 5a454f5e..55603fc1 100644 --- a/Sources/WasmKit/Module.swift +++ b/Sources/WasmKit/Module.swift @@ -227,13 +227,8 @@ public struct Module { } /// Materialize lazily-computed elements in this module - public mutating func materializeAll() throws { - let allocator = ISeqAllocator() - let funcTypeInterner = Interner() - for function in functions { - _ = try function.compile(module: self, funcTypeInterner: funcTypeInterner, allocator: allocator) - } - } + @available(*, deprecated, message: "Module materialization is no longer supported. Instantiate the module explicitly instead.") + public mutating func materializeAll() throws {} } extension Module { @@ -275,8 +270,4 @@ typealias LabelIndex = UInt32 struct GuestFunction { let type: FunctionType let code: Code - - func compile(module: Module, funcTypeInterner: Interner, allocator: ISeqAllocator) throws -> InstructionSequence { - throw TranslationError("Compile without instantiation is no longer supported") - } } diff --git a/Tests/WasmKitTests/FuzzTranslatorRegressionTests.swift b/Tests/WasmKitTests/FuzzTranslatorRegressionTests.swift index 9f76ea0f..6224ef0f 100644 --- a/Tests/WasmKitTests/FuzzTranslatorRegressionTests.swift +++ b/Tests/WasmKitTests/FuzzTranslatorRegressionTests.swift @@ -1,8 +1,9 @@ import WasmKit +import WasmKitFuzzing import XCTest final class FuzzTranslatorRegressionTests: XCTestCase { - func testRunAll() async throws { + func testRunAll() throws { let sourceRoot = URL(fileURLWithPath: #filePath) .deletingLastPathComponent().deletingLastPathComponent().deletingLastPathComponent() let failCasesDir = @@ -12,33 +13,11 @@ final class FuzzTranslatorRegressionTests: XCTestCase { for file in try FileManager.default.contentsOfDirectory(atPath: failCasesDir.path) { let path = failCasesDir.appendingPathComponent(file).path print("Fuzz regression test: \(path.dropFirst(sourceRoot.path.count + 1))") - let data = try Data(contentsOf: URL(fileURLWithPath: path)) do { - let module = try WasmKit.parseWasm(bytes: Array(data)) - let engine = Engine(configuration: EngineConfiguration(compilationMode: .eager)) - let store = Store(engine: engine) - var imports = Imports() - for importEntry in module.imports { - let value: ExternalValueConvertible - switch importEntry.descriptor { - case .function(let typeIndex): - let type = module.types[Int(typeIndex)] - value = Function(store: store, type: type) { _, _ in - fatalError("unreachable") - } - case .global(let globalType): - value = try Global(store: store, type: globalType, value: .i32(0)) - case .memory(let memoryType): - value = try Memory(store: store, type: memoryType) - case .table(let tableType): - value = try Table(store: store, type: tableType) - } - imports.define(module: importEntry.module, name: importEntry.name, value.externalValue) - } - _ = try module.instantiate(store: store, imports: imports) + try WasmKitFuzzing.fuzzInstantiation(bytes: Array(data)) } catch { - // Explicit errors are ok + // Skip exceptions without crash } } }