Skip to content

Commit 8c3092d

Browse files
Validation: Check element segment
1 parent 1bf8017 commit 8c3092d

File tree

3 files changed

+40
-18
lines changed

3 files changed

+40
-18
lines changed

Sources/WasmKit/Execution/ConstEvaluation.swift

Lines changed: 35 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -61,25 +61,43 @@ extension ConstExpression {
6161

6262
extension WasmParser.ElementSegment {
6363
func evaluateInits<C: ConstEvaluationContextProtocol>(context: C) throws -> [Reference] {
64-
try self.initializer.map { expression -> Reference in
65-
switch expression[0] {
66-
case let .refFunc(index):
67-
return try context.functionRef(index)
68-
case .refNull(.funcRef):
69-
return .function(nil)
70-
case .refNull(.externRef):
71-
return .extern(nil)
72-
case .globalGet(let index):
73-
let value = try context.globalValue(index)
74-
switch value {
75-
case .ref(.function(let addr)):
76-
return .function(addr)
77-
default:
78-
throw Trap._raw("Unexpected global value type for element initializer expression")
79-
}
64+
return try self.initializer.map { expression -> Reference in
65+
let result = try Self._evaluateInits(context: context, expression: expression)
66+
try result.checkType(self.type)
67+
return result
68+
}
69+
}
70+
static func _evaluateInits<C: ConstEvaluationContextProtocol>(
71+
context: C, expression: ConstExpression
72+
) throws -> Reference {
73+
switch expression[0] {
74+
case let .refFunc(index):
75+
return try context.functionRef(index)
76+
case .refNull(.funcRef):
77+
return .function(nil)
78+
case .refNull(.externRef):
79+
return .extern(nil)
80+
case .globalGet(let index):
81+
let value = try context.globalValue(index)
82+
switch value {
83+
case .ref(.function(let addr)):
84+
return .function(addr)
8085
default:
81-
throw Trap._raw("Unexpected element initializer expression: \(expression)")
86+
throw Trap._raw("Unexpected global value type for element initializer expression")
8287
}
88+
default:
89+
throw Trap._raw("Unexpected element initializer expression: \(expression)")
90+
}
91+
}
92+
}
93+
94+
fileprivate extension WasmTypes.Reference {
95+
func checkType(_ type: WasmTypes.ReferenceType) throws {
96+
switch (self, type) {
97+
case (.function, .funcRef): return
98+
case (.extern, .externRef): return
99+
default:
100+
throw ValidationError("Expect \(type) but got \(self)")
83101
}
84102
}
85103
}

Sources/WasmKit/Module.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,11 @@ public struct Module {
162162
"Expect \(ValueType.addressType(isMemory64: table.limits.isMemory64)) offset of active element segment but got \(offsetValue)"
163163
)
164164
}
165+
guard table.tableType.elementType == element.type else {
166+
throw ValidationError(
167+
"Element segment type \(element.type) does not match table element type \(table.tableType.elementType)"
168+
)
169+
}
165170
let references = try element.evaluateInits(context: constEvalContext)
166171
try table.initialize(
167172
references, from: 0, to: Int(offset), count: references.count

Tests/WasmKitTests/SpectestTests.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ final class SpectestTests: XCTestCase {
2222
path: Self.testPaths,
2323
include: [],
2424
exclude: [
25-
"elem.wast",
2625
"exports.wast",
2726
"func.wast",
2827
"func_ptrs.wast",

0 commit comments

Comments
 (0)