Skip to content

Commit 7fb8254

Browse files
LiedtkeV8-internal LUCI CQ
authored andcommitted
[wasm] Properly fix typing issue in WasmBeginCatch
The first attempt of fixing this was commit 89691a1, however this means we might end up not typing the inner outputs (the tag's "elements" available inside the catch) which breaks the typer's assumptions that everything gets typed. Typing it with some dummy value can also lead to issues downstream (e.g. by the next instruction taking now an input that isn't of the needed type any more), so instead we solve this issue by always also adding a signature as an input. As the signature is defined in Wasm, input replacement can only happen with strict type checks, so it is safe to rely on this. It's a bit annoying for the WasmBeginCatch to take an extra input for this specific problem, however, WasmBeginCatch is anyways related to the "legacy" exception handling which isn't a properly spec'ed Wasm feature but a "browsers have been shipping this without a finished spec" kind of thing. Bug: 448860865 Change-Id: I06638ccbb5ed0c9dbb7355ac198b7ace25f521b8 Reviewed-on: https://chrome-internal-review.googlesource.com/c/v8/fuzzilli/+/9129497 Reviewed-by: Michael Achenbach <machenbach@google.com> Auto-Submit: Matthias Liedtke <mliedtke@google.com> Commit-Queue: Matthias Liedtke <mliedtke@google.com>
1 parent 6bac790 commit 7fb8254

File tree

3 files changed

+33
-15
lines changed

3 files changed

+33
-15
lines changed

Sources/Fuzzilli/Base/ProgramBuilder.swift

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4092,18 +4092,28 @@ public class ProgramBuilder {
40924092
catchAllBody: ((Variable) -> Void)? = nil) {
40934093
let signature = [] => []
40944094
let signatureDef = b.wasmDefineAdHocSignatureType(signature: signature)
4095+
4096+
// Define tag signatures before the try block so they don't interfere with the try/catch
4097+
// bodies and their scoping.
4098+
// TODO(mliedtke): We should reuse the signature of the tag once tags use a wasm-gc
4099+
// signature.
4100+
let tagSignatures = catchClauses.map {
4101+
b.wasmDefineAdHocSignatureType(signature: b.type(of: $0.tag).wasmTagType!.parameters => [])
4102+
}
4103+
40954104
let instr = b.emit(WasmBeginTry(
40964105
parameterCount: 0), withInputs: [signatureDef], types: [.wasmTypeDef()])
40974106
assert(instr.innerOutputs.count == 1)
40984107
body(instr.innerOutput(0))
4099-
for (tag, generator) in catchClauses {
4108+
for (i, (tag, generator)) in catchClauses.enumerated() {
41004109
b.reportErrorIf(!b.type(of: tag).isWasmTagType,
41014110
"Expected tag misses the WasmTagType extension for variable \(tag), typed \(b.type(of: tag)).")
4111+
let tagSignatureDef = tagSignatures[i]
41024112
let instr = b.emit(WasmBeginCatch(
41034113
blockOutputCount: signature.outputTypes.count,
41044114
labelParameterCount: b.type(of: tag).wasmTagType!.parameters.count),
4105-
withInputs: [signatureDef, tag],
4106-
types: [.wasmTypeDef(), .object(ofGroup: "WasmTag")] + signature.outputTypes)
4115+
withInputs: [signatureDef, tag, tagSignatureDef],
4116+
types: [.wasmTypeDef(), .object(ofGroup: "WasmTag"), .wasmTypeDef()] + signature.outputTypes)
41074117
generator(instr.innerOutput(0), instr.innerOutput(1), Array(instr.innerOutputs(2...)))
41084118
}
41094119
if let catchAllBody {
@@ -4125,18 +4135,28 @@ public class ProgramBuilder {
41254135
catchClauses: [(tag: Variable, body: (Variable, Variable, [Variable]) -> [Variable])] = [],
41264136
catchAllBody: ((Variable) -> [Variable])? = nil) -> [Variable] {
41274137
let parameterCount = signature.parameterTypes.count
4138+
4139+
// Define tag signatures before the try block so they don't interfere with the try/catch
4140+
// bodies and their scoping.
4141+
// TODO(mliedtke): We should reuse the signature of the tag once tags use a wasm-gc
4142+
// signature.
4143+
let tagSignatures = catchClauses.map {
4144+
b.wasmDefineAdHocSignatureType(signature: b.type(of: $0.tag).wasmTagType!.parameters => [])
4145+
}
4146+
41284147
let instr = b.emit(WasmBeginTry(parameterCount: parameterCount),
41294148
withInputs: [signatureDef] + args,
41304149
types: [.wasmTypeDef()] + signature.parameterTypes)
41314150
var result = body(instr.innerOutput(0), Array(instr.innerOutputs(1...)))
4132-
for (tag, generator) in catchClauses {
4151+
for (i, (tag, generator)) in catchClauses.enumerated() {
41334152
b.reportErrorIf(!b.type(of: tag).isWasmTagType,
41344153
"Expected tag misses the WasmTagType extension for variable \(tag), typed \(b.type(of: tag)).")
4154+
let tagSignatureDef = tagSignatures[i]
41354155
let instr = b.emit(WasmBeginCatch(
41364156
blockOutputCount: signature.outputTypes.count,
41374157
labelParameterCount: b.type(of: tag).wasmTagType!.parameters.count),
4138-
withInputs: [signatureDef, tag] + result,
4139-
types: [.wasmTypeDef(), .object(ofGroup: "WasmTag")] + signature.outputTypes)
4158+
withInputs: [signatureDef, tag, tagSignatureDef] + result,
4159+
types: [.wasmTypeDef(), .object(ofGroup: "WasmTag"), .wasmTypeDef()] + signature.outputTypes)
41404160
result = generator(instr.innerOutput(0), instr.innerOutput(1), Array(instr.innerOutputs(2...)))
41414161
}
41424162
if let catchAllBody = catchAllBody {

Sources/Fuzzilli/FuzzIL/JSTyper.swift

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -883,13 +883,11 @@ public struct JSTyper: Analyzer {
883883
// exception with the legacy exception handling proposal. (This is similar to the
884884
// exnref in the standard exception handling spec.)
885885
setType(of: instr.innerOutput(1), to: .exceptionLabel)
886-
// Type the tag parameters.
887-
// If the input isn't typed as a Wasm tag any more (this can happen as tags can be
888-
// defined in JS and there a reassign as part of a CodeGenMutator run can loosen the
889-
// inferred type), just act as if there weren't any label parameters. In that case
890-
// the lifter will fail and the test case will be discarded.
891-
let labelParameters = type(of: instr.input(1)).wasmTagType?.parameters ?? []
892-
for (innerOutput, paramType) in zip(instr.innerOutputs.dropFirst(2), labelParameters) {
886+
// Type the tag parameters based on the tag's signature definition.
887+
// This guarantees that the inner outputs are properly typed, even if a mutator
888+
// changed the tag variable to something that's not typed as a Wasm tag anymore.
889+
let tagSignature = type(of: instr.input(2)).wasmFunctionSignatureDefSignature
890+
for (innerOutput, paramType) in zip(instr.innerOutputs.dropFirst(2), tagSignature.parameterTypes) {
893891
setType(of: innerOutput, to: paramType)
894892
}
895893
for (output, outputType) in zip(instr.outputs, blockSignature.outputTypes) {

Sources/Fuzzilli/FuzzIL/WasmOperations.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1408,9 +1408,9 @@ final class WasmBeginCatch : WasmOperation {
14081408
// the usage. For now, we just emit a label for branching and the ".exceptionLabel" for
14091409
// rethrows.
14101410
super.init(
1411-
// Inputs: The block signature, the tag and the outputs of the preceding try or catch
1411+
// Inputs: The block signature, the tag, the tag signature, and the outputs of the preceding try or catch
14121412
// (all) block.
1413-
numInputs: 2 + blockOutputCount,
1413+
numInputs: 3 + blockOutputCount,
14141414
// Inner outputs are the branch label, the exception label and the tag parameters.
14151415
numInnerOutputs: 2 + labelParameterCount,
14161416
attributes: [

0 commit comments

Comments
 (0)