@@ -15,15 +15,15 @@ public struct Parser<Stream: ByteStream> {
15
15
public private( set) var hasDataCount : Bool = false
16
16
public let features : WasmFeatureSet
17
17
let limits : ParsingLimits
18
+ var orderTracking = OrderTracking ( )
18
19
19
20
enum NextParseTarget {
20
21
case header
21
22
case section
22
23
}
23
24
private var nextParseTarget : NextParseTarget
24
25
25
- @usableFromInline
26
- var currentIndex : Int {
26
+ public var offset : Int {
27
27
return stream. currentIndex
28
28
}
29
29
@@ -37,7 +37,7 @@ public struct Parser<Stream: ByteStream> {
37
37
38
38
@usableFromInline
39
39
internal func makeError( _ message: WasmParserError . Message ) -> WasmParserError {
40
- return WasmParserError ( message, offset: currentIndex )
40
+ return WasmParserError ( message, offset: offset )
41
41
}
42
42
}
43
43
@@ -147,7 +147,7 @@ public struct ExpressionParser {
147
147
var lastCode : InstructionCode ?
148
148
149
149
public var offset : Int {
150
- self . codeOffset + self . parser. currentIndex - self . initialStreamOffset
150
+ self . codeOffset + self . parser. offset - self . initialStreamOffset
151
151
}
152
152
153
153
public init ( code: Code ) {
@@ -157,7 +157,7 @@ public struct ExpressionParser {
157
157
hasDataCount: code. hasDataCount
158
158
)
159
159
self . codeOffset = code. offset
160
- self . initialStreamOffset = self . parser. currentIndex
160
+ self . initialStreamOffset = self . parser. offset
161
161
}
162
162
163
163
@inlinable
@@ -322,10 +322,6 @@ extension WasmParserError.Message {
322
322
}
323
323
324
324
extension WasmParserError {
325
- // TODO: Remove
326
- public static var sectionOutOfOrder : Self {
327
- Self ( . sectionOutOfOrder, offset: 0 )
328
- }
329
325
public static func inconsistentFunctionAndCodeLength( functionCount: Int , codeCount: Int ) -> Self {
330
326
Self ( . inconsistentFunctionAndCodeLength( functionCount: functionCount, codeCount: codeCount) , offset: 0 )
331
327
}
@@ -449,7 +445,7 @@ extension Parser {
449
445
case 0x70 : return . ref( . funcRef)
450
446
case 0x6F : return . ref( . externRef)
451
447
default :
452
- throw StreamError< Stream . Element> . unexpected( b, index: currentIndex , expected: Set ( 0x7C ... 0x7F ) )
448
+ throw StreamError< Stream . Element> . unexpected( b, index: offset , expected: Set ( 0x7C ... 0x7F ) )
453
449
}
454
450
}
455
451
@@ -547,7 +543,7 @@ extension Parser {
547
543
case 0x6F :
548
544
elementType = . externRef
549
545
default :
550
- throw StreamError . unexpected ( b, index: currentIndex , expected: [ 0x6F , 0x70 ] )
546
+ throw StreamError . unexpected ( b, index: offset , expected: [ 0x6F , 0x70 ] )
551
547
}
552
548
553
549
let limits = try parseLimits ( )
@@ -1220,6 +1216,33 @@ extension Parser {
1220
1216
return version
1221
1217
}
1222
1218
1219
+ struct OrderTracking {
1220
+ enum Order : UInt8 {
1221
+ case initial = 0
1222
+ case type
1223
+ case _import
1224
+ case function
1225
+ case table
1226
+ case memory
1227
+ case tag
1228
+ case global
1229
+ case export
1230
+ case start
1231
+ case element
1232
+ case dataCount
1233
+ case code
1234
+ case data
1235
+ }
1236
+
1237
+ private var last : Order = . initial
1238
+ mutating func track( order: Order , parser: Parser ) throws {
1239
+ guard last. rawValue < order. rawValue else {
1240
+ throw parser. makeError ( . sectionOutOfOrder)
1241
+ }
1242
+ last = order
1243
+ }
1244
+ }
1245
+
1223
1246
/// Attempts to parse a chunk of the Wasm binary stream.
1224
1247
///
1225
1248
/// - Returns: A `ParsingPayload` if the parsing was successful, otherwise `nil`.
@@ -1264,28 +1287,57 @@ extension Parser {
1264
1287
let sectionStart = stream. currentIndex
1265
1288
1266
1289
let payload : ParsingPayload
1290
+ let order : OrderTracking . Order ?
1267
1291
switch sectionID {
1268
- case 0 : payload = . customSection( try parseCustomSection ( size: sectionSize) )
1269
- case 1 : payload = . typeSection( try parseTypeSection ( ) )
1270
- case 2 : payload = . importSection( try parseImportSection ( ) )
1271
- case 3 : payload = . functionSection( try parseFunctionSection ( ) )
1272
- case 4 : payload = . tableSection( try parseTableSection ( ) )
1273
- case 5 : payload = . memorySection( try parseMemorySection ( ) )
1274
- case 6 : payload = . globalSection( try parseGlobalSection ( ) )
1275
- case 7 : payload = . exportSection( try parseExportSection ( ) )
1276
- case 8 : payload = . startSection( try parseStartSection ( ) )
1277
- case 9 : payload = . elementSection( try parseElementSection ( ) )
1278
- case 10 : payload = . codeSection( try parseCodeSection ( ) )
1279
- case 11 : payload = . dataSection( try parseDataSection ( ) )
1292
+ case 0 :
1293
+ order = nil
1294
+ payload = . customSection( try parseCustomSection ( size: sectionSize) )
1295
+ case 1 :
1296
+ order = . type
1297
+ payload = . typeSection( try parseTypeSection ( ) )
1298
+ case 2 :
1299
+ order = . _import
1300
+ payload = . importSection( try parseImportSection ( ) )
1301
+ case 3 :
1302
+ order = . function
1303
+ payload = . functionSection( try parseFunctionSection ( ) )
1304
+ case 4 :
1305
+ order = . table
1306
+ payload = . tableSection( try parseTableSection ( ) )
1307
+ case 5 :
1308
+ order = . memory
1309
+ payload = . memorySection( try parseMemorySection ( ) )
1310
+ case 6 :
1311
+ order = . global
1312
+ payload = . globalSection( try parseGlobalSection ( ) )
1313
+ case 7 :
1314
+ order = . export
1315
+ payload = . exportSection( try parseExportSection ( ) )
1316
+ case 8 :
1317
+ order = . start
1318
+ payload = . startSection( try parseStartSection ( ) )
1319
+ case 9 :
1320
+ order = . element
1321
+ payload = . elementSection( try parseElementSection ( ) )
1322
+ case 10 :
1323
+ order = . code
1324
+ payload = . codeSection( try parseCodeSection ( ) )
1325
+ case 11 :
1326
+ order = . data
1327
+ payload = . dataSection( try parseDataSection ( ) )
1280
1328
case 12 :
1329
+ order = . dataCount
1281
1330
hasDataCount = true
1282
1331
payload = . dataCount( try parseDataCountSection ( ) )
1283
1332
default :
1284
1333
throw makeError ( . malformedSectionID( sectionID) )
1285
1334
}
1335
+ if let order = order {
1336
+ try orderTracking. track ( order: order, parser: self )
1337
+ }
1286
1338
let expectedSectionEnd = sectionStart + Int( sectionSize)
1287
1339
guard expectedSectionEnd == stream. currentIndex else {
1288
- throw makeError ( . sectionSizeMismatch( expected: expectedSectionEnd, actual: currentIndex ) )
1340
+ throw makeError ( . sectionSizeMismatch( expected: expectedSectionEnd, actual: offset ) )
1289
1341
}
1290
1342
return payload
1291
1343
}
0 commit comments