Skip to content

Commit cb9f25f

Browse files
Fix deinit against uninited InstanceEntity
1 parent e3f8a40 commit cb9f25f

File tree

2 files changed

+35
-3
lines changed

2 files changed

+35
-3
lines changed

Sources/WasmKit/Execution/Instances.swift

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,21 @@ struct InstanceEntity /* : ~Copyable */ {
7878
var exports: [String: InternalExternalValue]
7979
var features: WasmFeatureSet
8080
var hasDataCount: Bool
81+
82+
static var empty: InstanceEntity {
83+
InstanceEntity(
84+
types: [],
85+
functions: ImmutableArray(),
86+
tables: ImmutableArray(),
87+
memories: ImmutableArray(),
88+
globals: ImmutableArray(),
89+
elementSegments: ImmutableArray(),
90+
dataSegments: ImmutableArray(),
91+
exports: [:],
92+
features: [],
93+
hasDataCount: false
94+
)
95+
}
8196
}
8297

8398
typealias InternalInstance = EntityHandle<InstanceEntity>

Sources/WasmKit/Execution/StoreAllocator.swift

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,11 @@ struct ImmutableArray<T> {
106106
buffer = UnsafeBufferPointer(mutable)
107107
}
108108

109+
/// Initializes an empty immutable array.
110+
init() {
111+
buffer = UnsafeBufferPointer(start: nil, count: 0)
112+
}
113+
109114
/// Accesses the element at the specified position.
110115
subscript(index: Int) -> T {
111116
buffer[index]
@@ -254,9 +259,6 @@ extension StoreAllocator {
254259
// Step 1 of module allocation algorithm, according to Wasm 2.0 spec.
255260

256261
let types = module.types
257-
// Uninitialized instance
258-
let instancePointer = instances.allocate()
259-
let instanceHandle = InternalInstance(unsafe: instancePointer)
260262
var importedFunctions: [InternalFunction] = []
261263
var importedTables: [InternalTable] = []
262264
var importedMemories: [InternalMemory] = []
@@ -318,6 +320,20 @@ extension StoreAllocator {
318320
}
319321
}
320322

323+
// Uninitialized instance
324+
let instancePointer = instances.allocate()
325+
var instanceInitialized = false
326+
defer {
327+
// If the instance is not initialized due to an exception, initialize it with an empty instance
328+
// to allow bump deallocation by the bump allocator.
329+
// This is not optimal as it leaves an empty instance without deallocating the space but
330+
// good at code simplicity.
331+
if !instanceInitialized {
332+
instancePointer.initialize(to: .empty)
333+
}
334+
}
335+
let instanceHandle = InternalInstance(unsafe: instancePointer)
336+
321337
// Step 2.
322338
let functions = allocateEntities(
323339
imports: importedFunctions,
@@ -430,6 +446,7 @@ extension StoreAllocator {
430446
hasDataCount: module.hasDataCount
431447
)
432448
instancePointer.initialize(to: instanceEntity)
449+
instanceInitialized = true
433450
return instanceHandle
434451
}
435452

0 commit comments

Comments
 (0)