Skip to content

Commit 4960d02

Browse files
Validation: Check global mutability and types
1 parent ae3902a commit 4960d02

File tree

6 files changed

+44
-7
lines changed

6 files changed

+44
-7
lines changed

Sources/WasmKit/Execution/ConstEvaluation.swift

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,13 @@ struct ConstEvaluationContext: ConstEvaluationContextProtocol {
3434
}
3535

3636
extension ConstExpression {
37-
func evaluate<C: ConstEvaluationContextProtocol>(context: C) throws -> Value {
37+
func evaluate<C: ConstEvaluationContextProtocol>(context: C, expectedType: WasmTypes.ValueType) throws -> Value {
38+
let result = try self._evaluate(context: context)
39+
try result.checkType(expectedType)
40+
return result
41+
}
42+
43+
private func _evaluate<C: ConstEvaluationContextProtocol>(context: C) throws -> Value {
3844
guard self.last == .end, self.count == 2 else {
3945
throw InstantiationError.unsupported("Expect `end` at the end of offset expression")
4046
}
@@ -101,3 +107,18 @@ fileprivate extension WasmTypes.Reference {
101107
}
102108
}
103109
}
110+
111+
fileprivate extension Value {
112+
func checkType(_ type: WasmTypes.ValueType) throws {
113+
switch (self, type) {
114+
case (.i32, .i32): return
115+
case (.i64, .i64): return
116+
case (.f32, .f32): return
117+
case (.f64, .f64): return
118+
case (.ref(let ref), .ref(let refType)):
119+
try ref.checkType(refType)
120+
default:
121+
throw ValidationError("Expect \(type) but got \(self)")
122+
}
123+
}
124+
}

Sources/WasmKit/Execution/StoreAllocator.swift

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -361,16 +361,17 @@ extension StoreAllocator {
361361
)
362362

363363
// Step 5.
364-
var constEvalContext = ConstEvaluationContext(
364+
let constEvalContext = ConstEvaluationContext(
365365
functions: functions,
366366
globals: importedGlobals.map(\.value)
367367
)
368368
let globals = try allocateEntities(
369369
imports: importedGlobals,
370370
internals: module.globals,
371371
allocateHandle: { global, i in
372-
let initialValue = try global.initializer.evaluate(context: constEvalContext)
373-
constEvalContext.globals.append(initialValue)
372+
let initialValue = try global.initializer.evaluate(
373+
context: constEvalContext, expectedType: global.type.valueType
374+
)
374375
return allocate(globalType: global.type, initialValue: initialValue)
375376
}
376377
)

Sources/WasmKit/Module.swift

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -154,8 +154,11 @@ public struct Module {
154154
do {
155155
for element in elements {
156156
guard case let .active(tableIndex, offset) = element.mode else { continue }
157-
let offsetValue = try offset.evaluate(context: constEvalContext)
158157
let table = try instance.tables[validating: Int(tableIndex)]
158+
let offsetValue = try offset.evaluate(
159+
context: constEvalContext,
160+
expectedType: .addressType(isMemory64: table.limits.isMemory64)
161+
)
159162
try table.withValue { table in
160163
guard let offset = offsetValue.maybeAddressOffset(table.limits.isMemory64) else {
161164
throw InstantiationError.unsupported(
@@ -182,8 +185,11 @@ public struct Module {
182185
// Step 16.
183186
do {
184187
for case let .active(data) in data {
185-
let offsetValue = try data.offset.evaluate(context: constEvalContext)
186188
let memory = try instance.memories[validating: Int(data.index)]
189+
let offsetValue = try data.offset.evaluate(
190+
context: constEvalContext,
191+
expectedType: .addressType(isMemory64: memory.limit.isMemory64)
192+
)
187193
try memory.withValue { memory in
188194
guard let offset = offsetValue.maybeAddressOffset(memory.limit.isMemory64) else {
189195
throw InstantiationError.unsupported(

Sources/WasmKit/Translator.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1537,6 +1537,7 @@ struct InstructionTranslator<Context: TranslatorContext>: InstructionVisitor {
15371537
// Skip actual code emission if validation-only mode
15381538
return
15391539
}
1540+
try validator.validateGlobalSet(global.globalType)
15401541
emit(.globalSet(Instruction.GlobalAndVRegOperand(reg: LLVReg(value), global: global)))
15411542
}
15421543

Sources/WasmKit/Validator.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,13 @@ struct InstructionValidator {
1414
throw ValidationError("Alignment 2**\(memarg.align) is out of limit \(naturalAlignment)")
1515
}
1616
}
17+
18+
func validateGlobalSet(_ type: GlobalType) throws {
19+
switch type.mutability {
20+
case .constant:
21+
throw ValidationError("Cannot set a constant global")
22+
case .variable:
23+
break
24+
}
25+
}
1726
}

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-
"global.wast",
2625
"if.wast",
2726
"imports.wast",
2827
"labels.wast",

0 commit comments

Comments
 (0)