Skip to content

Commit c554be0

Browse files
Validation: Add memory type validation
1 parent 125e91c commit c554be0

File tree

4 files changed

+48
-5
lines changed

4 files changed

+48
-5
lines changed

Sources/WasmKit/Execution/Instances.swift

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -418,6 +418,10 @@ public struct Table: Equatable {
418418
struct MemoryEntity /* : ~Copyable */ {
419419
static let pageSize = 64 * 1024
420420

421+
static func maxPageCount(isMemory64: Bool) -> UInt64 {
422+
isMemory64 ? UInt64.max : UInt64(1 << 32) / UInt64(pageSize)
423+
}
424+
421425
var data: [UInt8]
422426
let maxPageCount: UInt64
423427
let limit: Limits
@@ -428,7 +432,7 @@ struct MemoryEntity /* : ~Copyable */ {
428432
throw Trap._raw("Initial memory size exceeds the resource limit: \(byteSize) bytes")
429433
}
430434
data = Array(repeating: 0, count: byteSize)
431-
let defaultMaxPageCount = (memoryType.isMemory64 ? UInt64.max : UInt64(UInt32.max)) / UInt64(Self.pageSize)
435+
let defaultMaxPageCount = Self.maxPageCount(isMemory64: memoryType.isMemory64)
432436
maxPageCount = memoryType.max ?? defaultMaxPageCount
433437
limit = memoryType
434438
}

Sources/WasmKit/Module.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ public struct Module {
129129
/// > Note:
130130
/// <https://webassembly.github.io/spec/core/exec/modules.html#instantiation>
131131
private func instantiateHandle(store: Store, imports: Imports) throws -> InternalInstance {
132-
try ModuleValidator().validate(self)
132+
try ModuleValidator(module: self).validate()
133133

134134
// Steps 5-8.
135135

Sources/WasmKit/Validator.swift

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,50 @@ struct InstructionValidator {
3535
}
3636

3737
struct ModuleValidator {
38-
func validate(_ module: Module) throws {
38+
let module: Module
39+
init(module: Module) {
40+
self.module = module
41+
}
42+
43+
func validate() throws {
3944
if module.memoryTypes.count > 1 {
4045
throw ValidationError("Multiple memories are not permitted")
4146
}
47+
for memoryType in module.memoryTypes {
48+
try Self.checkMemoryType(memoryType, features: module.features)
49+
}
50+
}
51+
52+
static func checkMemoryType(_ type: MemoryType, features: WasmFeatureSet) throws {
53+
try checkLimit(type)
54+
55+
if type.isMemory64 {
56+
guard features.contains(.memory64) else {
57+
throw ValidationError("memory64 feature is required for 64-bit memories")
58+
}
59+
}
60+
61+
let hardMax = MemoryEntity.maxPageCount(isMemory64: type.isMemory64)
62+
63+
if type.min > hardMax {
64+
throw ValidationError("size minimum must not be greater than \(hardMax)")
65+
}
66+
67+
if let max = type.max, max > hardMax {
68+
throw ValidationError("size maximum must not be greater than \(hardMax)")
69+
}
70+
71+
if type.shared {
72+
guard features.contains(.threads) else {
73+
throw ValidationError("reference-types feature is required for shared memories")
74+
}
75+
}
76+
}
77+
78+
private static func checkLimit(_ limit: Limits) throws {
79+
guard let max = limit.max else { return }
80+
if limit.min > max {
81+
throw ValidationError("size minimum must not be greater than maximum")
82+
}
4283
}
4384
}

Tests/WasmKitTests/SpectestTests.swift

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,6 @@ final class SpectestTests: XCTestCase {
2222
path: Self.testPaths,
2323
include: [],
2424
exclude: [
25-
"loop.wast",
26-
"memory.wast",
2725
"memory_grow.wast",
2826
"memory_size.wast",
2927
"proposals/memory64/align64.wast",

0 commit comments

Comments
 (0)