@@ -15,15 +15,15 @@ public struct Parser<Stream: ByteStream> {
1515 public private( set) var hasDataCount : Bool = false
1616 public let features : WasmFeatureSet
1717 let limits : ParsingLimits
18+ var orderTracking = OrderTracking ( )
1819
1920 enum NextParseTarget {
2021 case header
2122 case section
2223 }
2324 private var nextParseTarget : NextParseTarget
2425
25- @usableFromInline
26- var currentIndex : Int {
26+ public var offset : Int {
2727 return stream. currentIndex
2828 }
2929
@@ -37,7 +37,7 @@ public struct Parser<Stream: ByteStream> {
3737
3838 @usableFromInline
3939 internal func makeError( _ message: WasmParserError . Message ) -> WasmParserError {
40- return WasmParserError ( message, offset: currentIndex )
40+ return WasmParserError ( message, offset: offset )
4141 }
4242}
4343
@@ -147,7 +147,7 @@ public struct ExpressionParser {
147147 var lastCode : InstructionCode ?
148148
149149 public var offset : Int {
150- self . codeOffset + self . parser. currentIndex - self . initialStreamOffset
150+ self . codeOffset + self . parser. offset - self . initialStreamOffset
151151 }
152152
153153 public init ( code: Code ) {
@@ -157,7 +157,7 @@ public struct ExpressionParser {
157157 hasDataCount: code. hasDataCount
158158 )
159159 self . codeOffset = code. offset
160- self . initialStreamOffset = self . parser. currentIndex
160+ self . initialStreamOffset = self . parser. offset
161161 }
162162
163163 @inlinable
@@ -322,10 +322,6 @@ extension WasmParserError.Message {
322322}
323323
324324extension WasmParserError {
325- // TODO: Remove
326- public static var sectionOutOfOrder : Self {
327- Self ( . sectionOutOfOrder, offset: 0 )
328- }
329325 public static func inconsistentFunctionAndCodeLength( functionCount: Int , codeCount: Int ) -> Self {
330326 Self ( . inconsistentFunctionAndCodeLength( functionCount: functionCount, codeCount: codeCount) , offset: 0 )
331327 }
@@ -449,7 +445,7 @@ extension Parser {
449445 case 0x70 : return . ref( . funcRef)
450446 case 0x6F : return . ref( . externRef)
451447 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 ) )
453449 }
454450 }
455451
@@ -547,7 +543,7 @@ extension Parser {
547543 case 0x6F :
548544 elementType = . externRef
549545 default :
550- throw StreamError . unexpected ( b, index: currentIndex , expected: [ 0x6F , 0x70 ] )
546+ throw StreamError . unexpected ( b, index: offset , expected: [ 0x6F , 0x70 ] )
551547 }
552548
553549 let limits = try parseLimits ( )
@@ -1220,6 +1216,33 @@ extension Parser {
12201216 return version
12211217 }
12221218
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+
12231246 /// Attempts to parse a chunk of the Wasm binary stream.
12241247 ///
12251248 /// - Returns: A `ParsingPayload` if the parsing was successful, otherwise `nil`.
@@ -1264,28 +1287,57 @@ extension Parser {
12641287 let sectionStart = stream. currentIndex
12651288
12661289 let payload : ParsingPayload
1290+ let order : OrderTracking . Order ?
12671291 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 ( ) )
12801328 case 12 :
1329+ order = . dataCount
12811330 hasDataCount = true
12821331 payload = . dataCount( try parseDataCountSection ( ) )
12831332 default :
12841333 throw makeError ( . malformedSectionID( sectionID) )
12851334 }
1335+ if let order = order {
1336+ try orderTracking. track ( order: order, parser: self )
1337+ }
12861338 let expectedSectionEnd = sectionStart + Int( sectionSize)
12871339 guard expectedSectionEnd == stream. currentIndex else {
1288- throw makeError ( . sectionSizeMismatch( expected: expectedSectionEnd, actual: currentIndex ) )
1340+ throw makeError ( . sectionSizeMismatch( expected: expectedSectionEnd, actual: offset ) )
12891341 }
12901342 return payload
12911343 }
0 commit comments