Skip to content

Commit 6d18850

Browse files
LiedtkeV8-internal LUCI CQ
authored andcommitted
[wasm] Fix crash of tag without .wasmTagType
This fixes a crash in Fuzzilli where we have the following pattern: v0 <- CreateWasmTag [.wasmi32] v1 <- CreateWasmTag [.wasmi64] v2 <- LoadBoolean 'true' v3 <- TernaryOperation v2, v0, v1 The type of v3 is the union(type(v0), type(v1)) which resulted in having a .object(ofGroup: "WasmTag") as both inputs are tags but not having a WasmTypeExtension as these are incompatible (two different) tag types. When the WasmTypeExtension gets invalidated by the union, we now also remove the object group from the TypeExtension. Change-Id: I00da60a29974e768d7321c577b0015cdd31f8029 Reviewed-on: https://chrome-internal-review.googlesource.com/c/v8/fuzzilli/+/8444056 Reviewed-by: Samuel Groß <[email protected]> Reviewed-by: Carl Smith <[email protected]> Commit-Queue: Matthias Liedtke <[email protected]>
1 parent a8511db commit 6d18850

File tree

2 files changed

+33
-4
lines changed

2 files changed

+33
-4
lines changed

Sources/Fuzzilli/FuzzIL/TypeSystem.swift

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -643,8 +643,14 @@ public struct ILType: Hashable {
643643
let commonMethods = self.methods.intersection(other.methods)
644644
let signature = self.signature == other.signature ? self.signature : nil // TODO: this is overly coarse, we could also see if one signature subsumes the other, then take the subsuming one.
645645
let receiver = other.receiver != nil && other.receiver != nil ? self.receiver?.intersection(with: other.receiver!) : nil
646-
let group = self.group == other.group ? self.group : nil
646+
var group = self.group == other.group ? self.group : nil
647647
let wasmExt = self.wasmType != nil && other.wasmType != nil ? self.wasmType!.union(other.wasmType!) : nil
648+
// Object groups are used to describe certain wasm types. If the WasmTypeExtension is lost,
649+
// the group should also be invalidated. This ensures that e.g. any
650+
// `.object(ofGroup: "WasmTag")` always has a `.wasmTagType` extension.
651+
if wasmExt == nil && (self.wasmType ?? other.wasmType) != nil {
652+
group = nil
653+
}
648654

649655
return ILType(definiteType: definiteType, possibleType: possibleType, ext: TypeExtension(group: group, properties: commonProperties, methods: commonMethods, signature: signature, wasmExt: wasmExt, receiver: receiver))
650656
}

Tests/FuzzilliTests/TypeSystemTest.swift

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -611,18 +611,22 @@ class TypeSystemTests: XCTestCase {
611611
XCTAssertEqual(ILTypeGlobalI32Mutable | ILTypeGlobalI32Mutable, ILTypeGlobalI32Mutable)
612612

613613
// Types with not equal WasmTypeExtension don't have a WasmTypeExtension in their union.
614-
let unionMutabilityDiff = ILType.object(ofGroup: "WasmGlobal", withProperties: ["value"])
614+
let unionMutabilityDiff = ILType.object(withProperties: ["value"])
615615
XCTAssertEqual(ILTypeGlobalI32Mutable | ILTypeGlobalI32NonMutable, unionMutabilityDiff)
616616
// Invariant: the union of two types subsumes both types.
617617
XCTAssert(unionMutabilityDiff >= ILTypeGlobalI32Mutable)
618618
XCTAssert(unionMutabilityDiff >= ILTypeGlobalI32NonMutable)
619619

620-
let unionValueTypeDiff = ILType.object(ofGroup: "WasmGlobal", withProperties: ["value"])
620+
let unionValueTypeDiff = ILType.object(withProperties: ["value"])
621621
XCTAssertEqual(ILTypeGlobalI32Mutable | ILTypeGlobalF32Mutable, unionValueTypeDiff)
622622
XCTAssert(unionValueTypeDiff >= ILTypeGlobalI32Mutable)
623623
XCTAssert(unionValueTypeDiff >= ILTypeGlobalI32NonMutable)
624624

625-
XCTAssertEqual(ILTypeGlobalI32Mutable | .object(ofGroup: "WasmGlobal"), .object(ofGroup: "WasmGlobal"))
625+
// When removing the WasmTypeExtension, the group is also removed. (Note that this specific
626+
// case is artificial as a .object(ofGroup: WasmGlobal) should only be used e.g. as a
627+
// search criteria but never appear as a type for a variable without a corresponding
628+
// .wasmGlobalType extension.)
629+
XCTAssertEqual(ILTypeGlobalI32Mutable | .object(ofGroup: "WasmGlobal"), .object())
626630
XCTAssert(.object(ofGroup: "WasmGlobal") >= ILTypeGlobalI32Mutable)
627631
XCTAssertEqual(ILTypeGlobalI32Mutable | .object(withProperties: ["value"]), .object(withProperties: ["value"]))
628632
XCTAssert(.object(withProperties: ["value"]) >= ILTypeGlobalI32Mutable)
@@ -1155,6 +1159,25 @@ class TypeSystemTests: XCTestCase {
11551159
}
11561160
}
11571161

1162+
func testWasmTypeExtensionUnionTypeExtensionVsWasmTypeExtension() {
1163+
let tagA = ILType.object(ofGroup: "WasmTag", withWasmType: WasmTagType([.wasmi32]))
1164+
let tagB = ILType.object(ofGroup: "WasmTag", withWasmType: WasmTagType([.wasmi64]))
1165+
// The union with itself doesn't modify the type.
1166+
XCTAssertEqual(tagA.union(with: tagA), tagA)
1167+
// The union of two distinct wasm tags / WasmTypeExtensions leads to the removal of the wasm
1168+
// type extension. To make the types easier to use (e.g. a catch might just want to search
1169+
// for any wasm tag by doing `required(.object(ofGroup: "WasmTag"))` and expect to get a tag
1170+
// with a valid type extension), if the WasmTypeExtension is removed, also any object group
1171+
// is invalidated on the TypeExtension.
1172+
let tagUnion = tagA.union(with: tagB)
1173+
XCTAssertNil(tagUnion.wasmType)
1174+
XCTAssertNil(tagUnion.group)
1175+
// The intersection of two unequal tags always leads to an invalid type (as tags never
1176+
// subsume each other).
1177+
let tagIntersection = tagA.intersection(with: tagB)
1178+
XCTAssertEqual(tagIntersection, .nothing)
1179+
}
1180+
11581181
func testUnboundFunctionSubsumptionRules() {
11591182
XCTAssertEqual(ILType.unboundFunction(), .unboundFunction())
11601183
XCTAssertNotEqual(ILType.unboundFunction([] => .object()), .unboundFunction())

0 commit comments

Comments
 (0)