diff --git a/Sources/Fuzzilli/Base/ProgramBuilder.swift b/Sources/Fuzzilli/Base/ProgramBuilder.swift index ae9c7bf1..0df465c1 100644 --- a/Sources/Fuzzilli/Base/ProgramBuilder.swift +++ b/Sources/Fuzzilli/Base/ProgramBuilder.swift @@ -3346,9 +3346,9 @@ public class ProgramBuilder { } @discardableResult - public func wasmI64x2LoadSplat(memory: Variable, dynamicOffset: Variable, staticOffset: Int64) -> Variable { + func wasmSimdLoad(kind: WasmSimdLoad.Kind, memory: Variable, dynamicOffset: Variable, staticOffset: Int64) -> Variable { let isMemory64 = b.type(of: memory).wasmMemoryType!.isMemory64 - return b.emit(WasmI64x2LoadSplat(staticOffset: staticOffset, isMemory64: isMemory64), withInputs: [memory, dynamicOffset]).output + return b.emit(WasmSimdLoad(kind: kind, staticOffset: staticOffset, isMemory64: isMemory64), withInputs: [memory, dynamicOffset]).output } } diff --git a/Sources/Fuzzilli/CodeGen/CodeGeneratorWeights.swift b/Sources/Fuzzilli/CodeGen/CodeGeneratorWeights.swift index d140ab02..54dc9efc 100644 --- a/Sources/Fuzzilli/CodeGen/CodeGeneratorWeights.swift +++ b/Sources/Fuzzilli/CodeGen/CodeGeneratorWeights.swift @@ -292,7 +292,7 @@ public let codeGeneratorWeights = [ "WasmSimd128CompareGenerator": 5, "WasmI64x2SplatGenerator": 5, "WasmI64x2ExtractLaneGenerator": 5, - "WasmI64x2LoadSplatGenerator": 5, + "WasmSimdLoadGenerator": 5, "WasmSelectGenerator": 10, ] diff --git a/Sources/Fuzzilli/CodeGen/WasmCodeGenerators.swift b/Sources/Fuzzilli/CodeGen/WasmCodeGenerators.swift index d680061f..8654e548 100644 --- a/Sources/Fuzzilli/CodeGen/WasmCodeGenerators.swift +++ b/Sources/Fuzzilli/CodeGen/WasmCodeGenerators.swift @@ -850,13 +850,13 @@ public let WasmCodeGenerators: [CodeGenerator] = [ function.wasmI64x2ExtractLane(input, 0) }, - CodeGenerator("WasmI64x2LoadSplatGenerator", inContext: .wasmFunction, inputs: .required(.object(ofGroup: "WasmMemory"))) { b, memory in + CodeGenerator("WasmSimdLoadGenerator", inContext: .wasmFunction, inputs: .required(.object(ofGroup: "WasmMemory"))) { b, memory in if (b.hasZeroPages(memory: memory)) { return } let function = b.currentWasmModule.currentWasmFunction let (dynamicOffset, staticOffset) = b.generateMemoryIndexes(forMemory: memory) - - function.wasmI64x2LoadSplat(memory: memory, dynamicOffset: dynamicOffset, staticOffset: staticOffset) + let kind = chooseUniform(from: WasmSimdLoad.Kind.allCases) + function.wasmSimdLoad(kind: kind, memory: memory, dynamicOffset: dynamicOffset, staticOffset: staticOffset) }, // TODO: Add three generators for JSPI diff --git a/Sources/Fuzzilli/FuzzIL/Instruction.swift b/Sources/Fuzzilli/FuzzIL/Instruction.swift index 31636b9b..c3a150a2 100644 --- a/Sources/Fuzzilli/FuzzIL/Instruction.swift +++ b/Sources/Fuzzilli/FuzzIL/Instruction.swift @@ -431,6 +431,33 @@ extension Instruction: ProtobufConvertible { } } + func convertWasmSimdLoadKind(_ loadKind: WasmSimdLoad.Kind) -> Fuzzilli_Protobuf_WasmSimdLoadKind { + switch loadKind { + case .LoadS128: + return .loads128 + case .Load8x8S: + return .load8X8S + case .Load8x8U: + return .load8X8U + case .Load16x4S: + return .load16X4S + case .Load16x4U: + return .load16X4U + case .Load32x2S: + return .load32X2S + case .Load32x2U: + return .load32X2U + case .Load8Splat: + return .load8Splat + case .Load16Splat: + return .load16Splat + case .Load32Splat: + return .load32Splat + case .Load64Splat: + return .load64Splat + } + } + func convertWasmGlobal(wasmGlobal: WasmGlobal) -> Fuzzilli_Protobuf_WasmGlobal.OneOf_WasmGlobal { switch wasmGlobal { case .wasmi32(let val): @@ -1303,8 +1330,9 @@ extension Instruction: ProtobufConvertible { $0.wasmI64X2Splat = Fuzzilli_Protobuf_WasmI64x2Splat() case .wasmI64x2ExtractLane(_): $0.wasmI64X2ExtractLane = Fuzzilli_Protobuf_WasmI64x2ExtractLane() - case .wasmI64x2LoadSplat(let op): - $0.wasmI64X2LoadSplat = Fuzzilli_Protobuf_WasmI64x2LoadSplat.with { + case .wasmSimdLoad(let op): + $0.wasmSimdLoad = Fuzzilli_Protobuf_WasmSimdLoad.with { + $0.kind = convertWasmSimdLoadKind(op.kind) $0.staticOffset = op.staticOffset $0.isMemory64 = op.isMemory64 } @@ -1421,6 +1449,35 @@ extension Instruction: ProtobufConvertible { } } + func convertProtoWasmSimdLoadKind(_ loadKind: Fuzzilli_Protobuf_WasmSimdLoadKind) -> WasmSimdLoad.Kind { + switch loadKind { + case .loads128: + return .LoadS128 + case .load8X8S: + return .Load8x8S + case .load8X8U: + return .Load8x8U + case .load16X4S: + return .Load16x4S + case .load16X4U: + return .Load16x4U + case .load32X2S: + return .Load32x2S + case .load32X2U: + return .Load32x2U + case .load8Splat: + return .Load8Splat + case .load16Splat: + return .Load16Splat + case .load32Splat: + return .Load32Splat + case .load64Splat: + return .Load64Splat + case .UNRECOGNIZED(let i): + fatalError("Invalid WasmSimdLoadKind \(i)") + } + } + func convertWasmGlobal(_ proto: Fuzzilli_Protobuf_WasmGlobal) -> WasmGlobal { switch proto.wasmGlobal { case .nullref(_): @@ -2093,8 +2150,8 @@ extension Instruction: ProtobufConvertible { op = WasmI64x2Splat() case .wasmI64X2ExtractLane(_): op = WasmI64x2ExtractLane(lane: 0) - case .wasmI64X2LoadSplat(let p): - op = WasmI64x2LoadSplat(staticOffset: p.staticOffset, isMemory64: p.isMemory64) + case .wasmSimdLoad(let p): + op = WasmSimdLoad(kind: convertProtoWasmSimdLoadKind(p.kind), staticOffset: p.staticOffset, isMemory64: p.isMemory64) } guard op.numInputs + op.numOutputs + op.numInnerOutputs == inouts.count else { diff --git a/Sources/Fuzzilli/FuzzIL/Opcodes.swift b/Sources/Fuzzilli/FuzzIL/Opcodes.swift index 25a03210..8af19f43 100644 --- a/Sources/Fuzzilli/FuzzIL/Opcodes.swift +++ b/Sources/Fuzzilli/FuzzIL/Opcodes.swift @@ -308,7 +308,7 @@ enum Opcode { case wasmSimd128FloatBinOp(WasmSimd128FloatBinOp) case wasmI64x2Splat(WasmI64x2Splat) case wasmI64x2ExtractLane(WasmI64x2ExtractLane) - case wasmI64x2LoadSplat(WasmI64x2LoadSplat) + case wasmSimdLoad(WasmSimdLoad) case wasmUnreachable(WasmUnreachable) case wasmSelect(WasmSelect) diff --git a/Sources/Fuzzilli/FuzzIL/WasmOperations.swift b/Sources/Fuzzilli/FuzzIL/WasmOperations.swift index 07230321..59e14a59 100644 --- a/Sources/Fuzzilli/FuzzIL/WasmOperations.swift +++ b/Sources/Fuzzilli/FuzzIL/WasmOperations.swift @@ -1523,13 +1523,30 @@ final class WasmI64x2ExtractLane: WasmOperation { } } -final class WasmI64x2LoadSplat: WasmOperation { - override var opcode: Opcode { .wasmI64x2LoadSplat(self) } - +final class WasmSimdLoad: WasmOperation { + enum Kind: UInt8, CaseIterable { + // TODO(mliedtke): Test all the other variants! + case LoadS128 = 0x00 + case Load8x8S = 0x01 + case Load8x8U = 0x02 + case Load16x4S = 0x03 + case Load16x4U = 0x04 + case Load32x2S = 0x05 + case Load32x2U = 0x06 + case Load8Splat = 0x07 + case Load16Splat = 0x08 + case Load32Splat = 0x09 + case Load64Splat = 0x0A + } + + override var opcode: Opcode { .wasmSimdLoad(self) } + + let kind: Kind let staticOffset: Int64 let isMemory64: Bool - init(staticOffset: Int64, isMemory64: Bool) { + init(kind: Kind, staticOffset: Int64, isMemory64: Bool) { + self.kind = kind self.staticOffset = staticOffset self.isMemory64 = isMemory64 let dynamicOffsetType = isMemory64 ? ILType.wasmi64 : ILType.wasmi32 diff --git a/Sources/Fuzzilli/Lifting/FuzzILLifter.swift b/Sources/Fuzzilli/Lifting/FuzzILLifter.swift index 9bcc9d46..e525d2e2 100644 --- a/Sources/Fuzzilli/Lifting/FuzzILLifter.swift +++ b/Sources/Fuzzilli/Lifting/FuzzILLifter.swift @@ -1099,8 +1099,8 @@ public class FuzzILLifter: Lifter { case .wasmI64x2ExtractLane(let op): w.emit("\(output()) <- WasmI64x2ExtractLane \(input(0)) \(op.lane)") - case .wasmI64x2LoadSplat(_): - w.emit("\(output()) <- WasmI64x2LoadSplat \(input(0))") + case .wasmSimdLoad(let op): + w.emit("\(output()) <- WasmSimdLoad \(op.kind) \(input(0)) + \(op.staticOffset)") default: fatalError("No FuzzIL lifting for this operation!") diff --git a/Sources/Fuzzilli/Lifting/JavaScriptLifter.swift b/Sources/Fuzzilli/Lifting/JavaScriptLifter.swift index 5391228f..773f8a97 100644 --- a/Sources/Fuzzilli/Lifting/JavaScriptLifter.swift +++ b/Sources/Fuzzilli/Lifting/JavaScriptLifter.swift @@ -1607,7 +1607,7 @@ public class JavaScriptLifter: Lifter { .wasmSimd128Compare(_), .wasmI64x2Splat(_), .wasmI64x2ExtractLane(_), - .wasmI64x2LoadSplat(_): + .wasmSimdLoad(_): fatalError("unreachable") } diff --git a/Sources/Fuzzilli/Lifting/WasmLifter.swift b/Sources/Fuzzilli/Lifting/WasmLifter.swift index 8388020c..d409445f 100644 --- a/Sources/Fuzzilli/Lifting/WasmLifter.swift +++ b/Sources/Fuzzilli/Lifting/WasmLifter.swift @@ -1071,7 +1071,7 @@ public class WasmLifter { try memoryOpImportAnalysis(instr: instr, isMemory64: op.isMemory64) case .wasmMemoryStore(let op): try memoryOpImportAnalysis(instr: instr, isMemory64: op.isMemory64) - case .wasmI64x2LoadSplat(let op): + case .wasmSimdLoad(let op): try memoryOpImportAnalysis(instr: instr, isMemory64: op.isMemory64) case .wasmTableGet(_), .wasmTableSet(_): @@ -1556,9 +1556,9 @@ public class WasmLifter { return Data([0xFD]) + Leb128.unsignedEncode(0x12) case .wasmI64x2ExtractLane(let op): return Data([0xFD]) + Leb128.unsignedEncode(0x1D) + Leb128.unsignedEncode(op.lane) - case .wasmI64x2LoadSplat(let op): + case .wasmSimdLoad(let op): // The memory immediate is {staticOffset, align} where align is 0 by default. Use signed encoding for potential bad (i.e. negative) offsets. - return Data([0xFD]) + Leb128.unsignedEncode(0x0A) + Leb128.unsignedEncode(0) + Leb128.signedEncode(Int(op.staticOffset)) + return Data([0xFD, op.kind.rawValue]) + Leb128.unsignedEncode(0) + Leb128.signedEncode(Int(op.staticOffset)) default: fatalError("unreachable") diff --git a/Sources/Fuzzilli/Mutators/OperationMutator.swift b/Sources/Fuzzilli/Mutators/OperationMutator.swift index e27c8cf5..740d3596 100644 --- a/Sources/Fuzzilli/Mutators/OperationMutator.swift +++ b/Sources/Fuzzilli/Mutators/OperationMutator.swift @@ -377,7 +377,7 @@ public class OperationMutator: BaseInstructionMutator { case .wasmI64x2ExtractLane(let op): // TODO: ? newOp = op - case .wasmI64x2LoadSplat(let op): + case .wasmSimdLoad(let op): // TODO: ? newOp = op case .createWasmJSTag(let op): diff --git a/Sources/Fuzzilli/Protobuf/operations.pb.swift b/Sources/Fuzzilli/Protobuf/operations.pb.swift index 4f72c442..0efd2ada 100644 --- a/Sources/Fuzzilli/Protobuf/operations.pb.swift +++ b/Sources/Fuzzilli/Protobuf/operations.pb.swift @@ -751,6 +751,76 @@ public enum Fuzzilli_Protobuf_WasmMemoryStoreType: SwiftProtobuf.Enum, Swift.Cas } +public enum Fuzzilli_Protobuf_WasmSimdLoadKind: SwiftProtobuf.Enum, Swift.CaseIterable { + public typealias RawValue = Int + case loads128 // = 0 + case load8X8S // = 1 + case load8X8U // = 2 + case load16X4S // = 3 + case load16X4U // = 4 + case load32X2S // = 5 + case load32X2U // = 6 + case load8Splat // = 7 + case load16Splat // = 8 + case load32Splat // = 9 + case load64Splat // = 10 + case UNRECOGNIZED(Int) + + public init() { + self = .loads128 + } + + public init?(rawValue: Int) { + switch rawValue { + case 0: self = .loads128 + case 1: self = .load8X8S + case 2: self = .load8X8U + case 3: self = .load16X4S + case 4: self = .load16X4U + case 5: self = .load32X2S + case 6: self = .load32X2U + case 7: self = .load8Splat + case 8: self = .load16Splat + case 9: self = .load32Splat + case 10: self = .load64Splat + default: self = .UNRECOGNIZED(rawValue) + } + } + + public var rawValue: Int { + switch self { + case .loads128: return 0 + case .load8X8S: return 1 + case .load8X8U: return 2 + case .load16X4S: return 3 + case .load16X4U: return 4 + case .load32X2S: return 5 + case .load32X2U: return 6 + case .load8Splat: return 7 + case .load16Splat: return 8 + case .load32Splat: return 9 + case .load64Splat: return 10 + case .UNRECOGNIZED(let i): return i + } + } + + // The compiler won't synthesize support with the UNRECOGNIZED case. + public static let allCases: [Fuzzilli_Protobuf_WasmSimdLoadKind] = [ + .loads128, + .load8X8S, + .load8X8U, + .load16X4S, + .load16X4U, + .load32X2S, + .load32X2U, + .load8Splat, + .load16Splat, + .load32Splat, + .load64Splat, + ] + +} + /// Parameters used by function definitions, not an operation by itself. public struct Fuzzilli_Protobuf_Parameters: Sendable { // SwiftProtobuf.Message conformance is added in an extension below. See the @@ -4309,11 +4379,13 @@ public struct Fuzzilli_Protobuf_WasmI64x2ExtractLane: Sendable { public init() {} } -public struct Fuzzilli_Protobuf_WasmI64x2LoadSplat: Sendable { +public struct Fuzzilli_Protobuf_WasmSimdLoad: Sendable { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. + public var kind: Fuzzilli_Protobuf_WasmSimdLoadKind = .loads128 + public var staticOffset: Int64 = 0 public var isMemory64: Bool = false @@ -4488,6 +4560,22 @@ extension Fuzzilli_Protobuf_WasmMemoryStoreType: SwiftProtobuf._ProtoNameProvidi ] } +extension Fuzzilli_Protobuf_WasmSimdLoadKind: SwiftProtobuf._ProtoNameProviding { + public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 0: .same(proto: "LOADS128"), + 1: .same(proto: "LOAD8x8S"), + 2: .same(proto: "LOAD8x8U"), + 3: .same(proto: "LOAD16x4S"), + 4: .same(proto: "LOAD16x4U"), + 5: .same(proto: "LOAD32x2S"), + 6: .same(proto: "LOAD32x2U"), + 7: .same(proto: "LOAD8SPLAT"), + 8: .same(proto: "LOAD16SPLAT"), + 9: .same(proto: "LOAD32SPLAT"), + 10: .same(proto: "LOAD64SPLAT"), + ] +} + extension Fuzzilli_Protobuf_Parameters: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { public static let protoMessageName: String = _protobuf_package + ".Parameters" public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ @@ -12597,11 +12685,12 @@ extension Fuzzilli_Protobuf_WasmI64x2ExtractLane: SwiftProtobuf.Message, SwiftPr } } -extension Fuzzilli_Protobuf_WasmI64x2LoadSplat: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { - public static let protoMessageName: String = _protobuf_package + ".WasmI64x2LoadSplat" +extension Fuzzilli_Protobuf_WasmSimdLoad: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + public static let protoMessageName: String = _protobuf_package + ".WasmSimdLoad" public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ - 1: .same(proto: "staticOffset"), - 2: .same(proto: "isMemory64"), + 1: .same(proto: "kind"), + 2: .same(proto: "staticOffset"), + 3: .same(proto: "isMemory64"), ] public mutating func decodeMessage(decoder: inout D) throws { @@ -12610,24 +12699,29 @@ extension Fuzzilli_Protobuf_WasmI64x2LoadSplat: SwiftProtobuf.Message, SwiftProt // allocates stack space for every case branch when no optimizations are // enabled. https://github.com/apple/swift-protobuf/issues/1034 switch fieldNumber { - case 1: try { try decoder.decodeSingularInt64Field(value: &self.staticOffset) }() - case 2: try { try decoder.decodeSingularBoolField(value: &self.isMemory64) }() + case 1: try { try decoder.decodeSingularEnumField(value: &self.kind) }() + case 2: try { try decoder.decodeSingularInt64Field(value: &self.staticOffset) }() + case 3: try { try decoder.decodeSingularBoolField(value: &self.isMemory64) }() default: break } } } public func traverse(visitor: inout V) throws { + if self.kind != .loads128 { + try visitor.visitSingularEnumField(value: self.kind, fieldNumber: 1) + } if self.staticOffset != 0 { - try visitor.visitSingularInt64Field(value: self.staticOffset, fieldNumber: 1) + try visitor.visitSingularInt64Field(value: self.staticOffset, fieldNumber: 2) } if self.isMemory64 != false { - try visitor.visitSingularBoolField(value: self.isMemory64, fieldNumber: 2) + try visitor.visitSingularBoolField(value: self.isMemory64, fieldNumber: 3) } try unknownFields.traverse(visitor: &visitor) } - public static func ==(lhs: Fuzzilli_Protobuf_WasmI64x2LoadSplat, rhs: Fuzzilli_Protobuf_WasmI64x2LoadSplat) -> Bool { + public static func ==(lhs: Fuzzilli_Protobuf_WasmSimdLoad, rhs: Fuzzilli_Protobuf_WasmSimdLoad) -> Bool { + if lhs.kind != rhs.kind {return false} if lhs.staticOffset != rhs.staticOffset {return false} if lhs.isMemory64 != rhs.isMemory64 {return false} if lhs.unknownFields != rhs.unknownFields {return false} diff --git a/Sources/Fuzzilli/Protobuf/operations.proto b/Sources/Fuzzilli/Protobuf/operations.proto index 2859b496..e9ae34bf 100644 --- a/Sources/Fuzzilli/Protobuf/operations.proto +++ b/Sources/Fuzzilli/Protobuf/operations.proto @@ -1255,7 +1255,22 @@ message WasmI64x2Splat { message WasmI64x2ExtractLane { } -message WasmI64x2LoadSplat { - int64 staticOffset = 1; - bool isMemory64 = 2; +enum WasmSimdLoadKind { + LOADS128 = 0; + LOAD8x8S = 1; + LOAD8x8U = 2; + LOAD16x4S = 3; + LOAD16x4U = 4; + LOAD32x2S = 5; + LOAD32x2U = 6; + LOAD8SPLAT = 7; + LOAD16SPLAT = 8; + LOAD32SPLAT = 9; + LOAD64SPLAT = 10; +} + +message WasmSimdLoad { + WasmSimdLoadKind kind = 1; + int64 staticOffset = 2; + bool isMemory64 = 3; } diff --git a/Sources/Fuzzilli/Protobuf/program.pb.swift b/Sources/Fuzzilli/Protobuf/program.pb.swift index f7f85942..eeaa73cf 100644 --- a/Sources/Fuzzilli/Protobuf/program.pb.swift +++ b/Sources/Fuzzilli/Protobuf/program.pb.swift @@ -2233,12 +2233,12 @@ public struct Fuzzilli_Protobuf_Instruction: Sendable { set {operation = .wasmI64X2ExtractLane(newValue)} } - public var wasmI64X2LoadSplat: Fuzzilli_Protobuf_WasmI64x2LoadSplat { + public var wasmSimdLoad: Fuzzilli_Protobuf_WasmSimdLoad { get { - if case .wasmI64X2LoadSplat(let v)? = operation {return v} - return Fuzzilli_Protobuf_WasmI64x2LoadSplat() + if case .wasmSimdLoad(let v)? = operation {return v} + return Fuzzilli_Protobuf_WasmSimdLoad() } - set {operation = .wasmI64X2LoadSplat(newValue)} + set {operation = .wasmSimdLoad(newValue)} } public var wasmUnreachable: Fuzzilli_Protobuf_WasmUnreachable { @@ -2533,7 +2533,7 @@ public struct Fuzzilli_Protobuf_Instruction: Sendable { case wasmSimd128FloatBinOp(Fuzzilli_Protobuf_WasmSimd128FloatBinOp) case wasmI64X2Splat(Fuzzilli_Protobuf_WasmI64x2Splat) case wasmI64X2ExtractLane(Fuzzilli_Protobuf_WasmI64x2ExtractLane) - case wasmI64X2LoadSplat(Fuzzilli_Protobuf_WasmI64x2LoadSplat) + case wasmSimdLoad(Fuzzilli_Protobuf_WasmSimdLoad) case wasmUnreachable(Fuzzilli_Protobuf_WasmUnreachable) case wasmSelect(Fuzzilli_Protobuf_WasmSelect) @@ -2859,7 +2859,7 @@ extension Fuzzilli_Protobuf_Instruction: SwiftProtobuf.Message, SwiftProtobuf._M 272: .same(proto: "wasmSimd128FloatBinOp"), 273: .same(proto: "wasmI64x2Splat"), 274: .same(proto: "wasmI64x2ExtractLane"), - 275: .same(proto: "wasmI64x2LoadSplat"), + 275: .same(proto: "wasmSimdLoad"), 276: .same(proto: "wasmUnreachable"), 277: .same(proto: "wasmSelect"), ] @@ -6416,16 +6416,16 @@ extension Fuzzilli_Protobuf_Instruction: SwiftProtobuf.Message, SwiftProtobuf._M } }() case 275: try { - var v: Fuzzilli_Protobuf_WasmI64x2LoadSplat? + var v: Fuzzilli_Protobuf_WasmSimdLoad? var hadOneofValue = false if let current = self.operation { hadOneofValue = true - if case .wasmI64X2LoadSplat(let m) = current {v = m} + if case .wasmSimdLoad(let m) = current {v = m} } try decoder.decodeSingularMessageField(value: &v) if let v = v { if hadOneofValue {try decoder.handleConflictingOneOf()} - self.operation = .wasmI64X2LoadSplat(v) + self.operation = .wasmSimdLoad(v) } }() case 276: try { @@ -7560,8 +7560,8 @@ extension Fuzzilli_Protobuf_Instruction: SwiftProtobuf.Message, SwiftProtobuf._M guard case .wasmI64X2ExtractLane(let v)? = self.operation else { preconditionFailure() } try visitor.visitSingularMessageField(value: v, fieldNumber: 274) }() - case .wasmI64X2LoadSplat?: try { - guard case .wasmI64X2LoadSplat(let v)? = self.operation else { preconditionFailure() } + case .wasmSimdLoad?: try { + guard case .wasmSimdLoad(let v)? = self.operation else { preconditionFailure() } try visitor.visitSingularMessageField(value: v, fieldNumber: 275) }() case .wasmUnreachable?: try { diff --git a/Sources/Fuzzilli/Protobuf/program.proto b/Sources/Fuzzilli/Protobuf/program.proto index f984245f..c3bd42a1 100644 --- a/Sources/Fuzzilli/Protobuf/program.proto +++ b/Sources/Fuzzilli/Protobuf/program.proto @@ -298,7 +298,7 @@ message Instruction { WasmSimd128FloatBinOp wasmSimd128FloatBinOp = 272; WasmI64x2Splat wasmI64x2Splat = 273; WasmI64x2ExtractLane wasmI64x2ExtractLane = 274; - WasmI64x2LoadSplat wasmI64x2LoadSplat = 275; + WasmSimdLoad wasmSimdLoad = 275; WasmUnreachable wasmUnreachable = 276; WasmSelect wasmSelect = 277; } diff --git a/Tests/FuzzilliTests/WasmTests.swift b/Tests/FuzzilliTests/WasmTests.swift index 37f73367..cbd4b28a 100644 --- a/Tests/FuzzilliTests/WasmTests.swift +++ b/Tests/FuzzilliTests/WasmTests.swift @@ -690,6 +690,45 @@ class WasmFoundationTests: XCTestCase { try allMemoryStoreTypesExecution(isMemory64: true) } + func wasmSimdLoad(isMemory64: Bool) throws { + let runner = try GetJavaScriptExecutorOrSkipTest() + let liveTestConfig = Configuration(logLevel: .error, enableInspection: true) + let fuzzer = makeMockFuzzer(config: liveTestConfig, environment: JavaScriptEnvironment()) + let b = fuzzer.makeBuilder() + + let module = b.buildWasmModule { wasmModule in + let memory = wasmModule.addMemory(minPages: 5, maxPages: 12, isMemory64: isMemory64) + + wasmModule.addWasmFunction(with: [] => .wasmi64) { function, _ in + let const = isMemory64 ? function.consti64 : {function.consti32(Int32($0))} + function.wasmMemoryStore(memory: memory, dynamicOffset: const(0), + value: function.consti64(3), storeType: .I64StoreMem, staticOffset: 0) + function.wasmMemoryStore(memory: memory, dynamicOffset: const(8), + value: function.consti64(6), storeType: .I64StoreMem, staticOffset: 0) + + let val = function.wasmSimdLoad(kind: .LoadS128, memory: memory, + dynamicOffset: const(0), staticOffset: 0) + let sum = function.wasmi64BinOp(function.wasmI64x2ExtractLane(val, 0), + function.wasmI64x2ExtractLane(val, 1), binOpKind: .Add) + function.wasmReturn(sum) + } + } + + let res0 = b.callMethod(module.getExportedMethod(at: 0), on: module.loadExports()) + b.callFunction(b.createNamedVariable(forBuiltin: "output"), withArgs: [b.callMethod("toString", on: res0)]) + + let jsProg = fuzzer.lifter.lift(b.finalize()) + testForOutput(program: jsProg, runner: runner, outputString: "9\n") + } + + func testWasmSimdLoadOnMemory32() throws { + try wasmSimdLoad(isMemory64: false) + } + + func testWasmSimdLoadOnMemory64() throws { + try wasmSimdLoad(isMemory64: true) + } + func testLoops() throws { let runner = try GetJavaScriptExecutorOrSkipTest() let liveTestConfig = Configuration(logLevel: .error, enableInspection: true)