Skip to content

Commit 28ddfae

Browse files
authored
Fixes a bug that made a copy of the changing vars within the verifier leading to an incorrect count (#8451)
Removes all the unneeded keyword (mutating) from verifier Adds tests to verify depth
1 parent 7e59e07 commit 28ddfae

File tree

3 files changed

+104
-37
lines changed

3 files changed

+104
-37
lines changed

swift/Sources/FlatBuffers/Verifier.swift

Lines changed: 52 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -22,22 +22,29 @@ public struct Verifier {
2222

2323
/// Flag to check for alignment if true
2424
fileprivate let _checkAlignment: Bool
25-
/// Capacity of the current buffer
26-
fileprivate var _capacity: Int
27-
/// Current ApparentSize
28-
fileprivate var _apparentSize: UOffset = 0
29-
/// Amount of tables present within a buffer
30-
fileprivate var _tableCount = 0
31-
32-
/// Capacity of the buffer
33-
internal var capacity: Int { _capacity }
34-
/// Current reached depth within the buffer
35-
internal var _depth = 0
25+
/// Storage for all changing values within the verifier
26+
private let storage: Storage
3627
/// Current verifiable ByteBuffer
3728
internal var _buffer: ByteBuffer
3829
/// Options for verification
3930
internal let _options: VerifierOptions
4031

32+
/// Current stored capacity within the verifier
33+
var capacity: Int {
34+
storage.capacity
35+
}
36+
37+
/// Current depth of verifier
38+
var depth: Int {
39+
storage.depth
40+
}
41+
42+
/// Current table count
43+
var tableCount: Int {
44+
storage.tableCount
45+
}
46+
47+
4148
/// Initializer for the verifier
4249
/// - Parameters:
4350
/// - buffer: Bytebuffer that is required to be verified
@@ -54,23 +61,23 @@ public struct Verifier {
5461
}
5562

5663
_buffer = buffer
57-
_capacity = buffer.capacity
5864
_checkAlignment = checkAlignment
5965
_options = options
66+
storage = Storage(capacity: buffer.capacity)
6067
}
6168

6269
/// Resets the verifier to initial state
63-
public mutating func reset() {
64-
_depth = 0
65-
_tableCount = 0
70+
public func reset() {
71+
storage.depth = 0
72+
storage.tableCount = 0
6673
}
6774

6875
/// Checks if the value of type `T` is aligned properly in the buffer
6976
/// - Parameters:
7077
/// - position: Current position
7178
/// - type: Type of value to check
7279
/// - Throws: `missAlignedPointer` if the pointer is not aligned properly
73-
public mutating func isAligned<T>(position: Int, type: T.Type) throws {
80+
public func isAligned<T>(position: Int, type: T.Type) throws {
7481

7582
/// If check alignment is false this mutating function doesnt continue
7683
if !_checkAlignment { return }
@@ -94,13 +101,13 @@ public struct Verifier {
94101
/// - Throws: `outOfBounds` if the value is out of the bounds of the buffer
95102
/// and `apparentSizeTooLarge` if the apparent size is bigger than the one specified
96103
/// in `VerifierOptions`
97-
public mutating func rangeInBuffer(position: Int, size: Int) throws {
104+
public func rangeInBuffer(position: Int, size: Int) throws {
98105
let end = UInt(clamping: (position &+ size).magnitude)
99106
if end > _buffer.capacity {
100-
throw FlatbuffersErrors.outOfBounds(position: end, end: capacity)
107+
throw FlatbuffersErrors.outOfBounds(position: end, end: storage.capacity)
101108
}
102-
_apparentSize = _apparentSize &+ UInt32(size)
103-
if _apparentSize > _options._maxApparentSize {
109+
storage.apparentSize = storage.apparentSize &+ UInt32(size)
110+
if storage.apparentSize > _options._maxApparentSize {
104111
throw FlatbuffersErrors.apparentSizeTooLarge
105112
}
106113
}
@@ -111,7 +118,7 @@ public struct Verifier {
111118
/// - position: Current readable position
112119
/// - type: Type of value to check
113120
/// - Throws: FlatbuffersErrors
114-
public mutating func inBuffer<T>(position: Int, of type: T.Type) throws {
121+
public func inBuffer<T>(position: Int, of type: T.Type) throws {
115122
try isAligned(position: position, type: type)
116123
try rangeInBuffer(position: position, size: MemoryLayout<T>.size)
117124
}
@@ -131,15 +138,15 @@ public struct Verifier {
131138
type: VOffset.self)
132139
try rangeInBuffer(position: vtablePosition, size: length)
133140

134-
_tableCount += 1
141+
storage.tableCount += 1
135142

136-
if _tableCount > _options._maxTableCount {
143+
if storage.tableCount > _options._maxTableCount {
137144
throw FlatbuffersErrors.maximumTables
138145
}
139146

140-
_depth += 1
147+
storage.depth += 1
141148

142-
if _depth > _options._maxDepth {
149+
if storage.depth > _options._maxDepth {
143150
throw FlatbuffersErrors.maximumDepth
144151
}
145152

@@ -154,7 +161,7 @@ public struct Verifier {
154161
/// - Parameter position: Current position to be read
155162
/// - Throws: `inBuffer` errors
156163
/// - Returns: a value of type `T` usually a `VTable` or a table offset
157-
internal mutating func getValue<T>(at position: Int) throws -> T {
164+
internal func getValue<T>(at position: Int) throws -> T {
158165
try inBuffer(position: position, of: T.self)
159166
return _buffer.read(def: T.self, position: position)
160167
}
@@ -165,7 +172,7 @@ public struct Verifier {
165172
/// - Throws: `inBuffer` errors & `signedOffsetOutOfBounds`
166173
/// - Returns: Current readable position for a field
167174
@inline(__always)
168-
internal mutating func derefOffset(position: Int) throws -> Int {
175+
internal func derefOffset(position: Int) throws -> Int {
169176
try inBuffer(position: position, of: Int32.self)
170177

171178
let offset = _buffer.read(def: Int32.self, position: position)
@@ -197,14 +204,14 @@ public struct Verifier {
197204
}
198205

199206
/// finishes the current iteration of verification on an object
200-
internal mutating func finish() {
201-
_depth -= 1
207+
internal func finish() {
208+
storage.depth -= 1
202209
}
203210

204211
@inline(__always)
205-
mutating func verify(id: String) throws {
212+
func verify(id: String) throws {
206213
let size = MemoryLayout<Int32>.size
207-
guard _capacity >= (size * 2) else {
214+
guard storage.capacity >= (size * 2) else {
208215
throw FlatbuffersErrors.bufferDoesntContainID
209216
}
210217
let str = _buffer.readString(at: size, count: size)
@@ -214,4 +221,18 @@ public struct Verifier {
214221
throw FlatbuffersErrors.bufferIdDidntMatchPassedId
215222
}
216223

224+
final private class Storage {
225+
/// Current ApparentSize
226+
fileprivate var apparentSize: UOffset = 0
227+
/// Amount of tables present within a buffer
228+
fileprivate var tableCount = 0
229+
/// Capacity of the current buffer
230+
fileprivate let capacity: Int
231+
/// Current reached depth within the buffer
232+
fileprivate var depth = 0
233+
234+
init(capacity: Int) {
235+
self.capacity = capacity
236+
}
237+
}
217238
}

tests/swift/tests/Tests/FlatBuffers.Test.SwiftTests/FlatBuffersVectorsTests.swift

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,6 @@ final class FlatBuffersVectors: XCTestCase {
6565
var b = FlatBufferBuilder(initialSize: 100)
6666
let o = b.createVector(ofStructs: vector)
6767
b.finish(offset: o)
68-
vector.withUnsafeBytes { pointer in
69-
print(Array(pointer))
70-
}
7168
// swiftformat:disable all
7269
XCTAssertEqual(b.sizedByteArray, [4, 0, 0, 0, 3, 0, 0, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 0, 0, 128, 64, 0, 0, 160, 64, 0, 0, 192, 64, 0, 0, 224, 64, 0, 0, 0, 65, 0, 0, 16, 65])
7370
// swiftformat:enable all

tests/swift/tests/Tests/FlatBuffers.Test.SwiftTests/FlatbuffersVerifierTests.swift

Lines changed: 52 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ final class FlatbuffersVerifierTests: XCTestCase {
7575
}
7676

7777
func testVerifierCheckAlignment() {
78-
var verifier = try! Verifier(buffer: &buffer)
78+
let verifier = try! Verifier(buffer: &buffer)
7979
do {
8080
try verifier.isAligned(position: 20, type: Int.self)
8181
} catch {
@@ -85,7 +85,7 @@ final class FlatbuffersVerifierTests: XCTestCase {
8585
}
8686
XCTAssertNoThrow(try verifier.isAligned(position: 16, type: Int.self))
8787

88-
var newVerifer = try! Verifier(buffer: &buffer, checkAlignment: false)
88+
let newVerifer = try! Verifier(buffer: &buffer, checkAlignment: false)
8989
XCTAssertNoThrow(try newVerifer.isAligned(position: 16, type: Int.self))
9090
}
9191

@@ -112,7 +112,7 @@ final class FlatbuffersVerifierTests: XCTestCase {
112112
}
113113

114114
func testPositionInBuffer() {
115-
var verifier = try! Verifier(buffer: &buffer)
115+
let verifier = try! Verifier(buffer: &buffer)
116116
XCTAssertNoThrow(try verifier.inBuffer(position: 0, of: Int64.self))
117117
XCTAssertNoThrow(try verifier.inBuffer(position: 24, of: Int64.self))
118118
XCTAssertThrowsError(try verifier.inBuffer(position: -9, of: Int64.self))
@@ -134,6 +134,9 @@ final class FlatbuffersVerifierTests: XCTestCase {
134134
var verifier = try! Verifier(buffer: &validFlatbuffersObject)
135135

136136
var tableVerifer = try! verifier.visitTable(at: 48)
137+
XCTAssertEqual(verifier.depth, 1)
138+
XCTAssertEqual(verifier.tableCount, 1)
139+
137140
XCTAssertNoThrow(try tableVerifer.visit(
138141
field: 4,
139142
fieldName: "Vec",
@@ -210,6 +213,8 @@ final class FlatbuffersVerifierTests: XCTestCase {
210213
error as! FlatbuffersErrors,
211214
.missAlignedPointer(position: 25, type: "UInt16"))
212215
}
216+
tableVerifer.finish()
217+
XCTAssertEqual(verifier.depth, 0)
213218
}
214219

215220
func testVerifyUnionVectors() {
@@ -291,7 +296,51 @@ final class FlatbuffersVerifierTests: XCTestCase {
291296
XCTAssertNoThrow(try getCheckedRoot(byteBuffer: &buf) as Movie)
292297
}
293298

299+
func testNestedTables() throws {
300+
var builder = FlatBufferBuilder()
301+
let name = builder.create(string: "Monster")
302+
303+
let enemy = MyGame_Example_Monster.createMonster(
304+
&builder,
305+
nameOffset: name)
306+
let currentName = builder.create(string: "Main name")
307+
let monster = MyGame_Example_Monster.createMonster(
308+
&builder,
309+
nameOffset: currentName,
310+
enemyOffset: enemy)
311+
builder.finish(offset: monster)
312+
313+
var sizedBuffer = builder.sizedBuffer
314+
var verifier = try! Verifier(buffer: &sizedBuffer)
315+
var tableVerifer = try! verifier.visitTable(
316+
at: try getOffset(at: 0, within: verifier))
317+
XCTAssertEqual(verifier.depth, 1)
318+
XCTAssertEqual(verifier.tableCount, 1)
319+
320+
let position = try tableVerifer.dereference(28)!
321+
322+
var nestedTable = try verifier.visitTable(
323+
at: try getOffset(at: position, within: verifier))
324+
325+
XCTAssertEqual(verifier.depth, 2)
326+
XCTAssertEqual(verifier.tableCount, 2)
327+
nestedTable.finish()
328+
XCTAssertEqual(verifier.depth, 1)
329+
XCTAssertEqual(verifier.tableCount, 2)
330+
tableVerifer.finish()
331+
XCTAssertEqual(verifier.depth, 0)
332+
XCTAssertEqual(verifier.tableCount, 2)
333+
}
334+
294335
func add(buffer: inout ByteBuffer, v: Int32, p: Int) {
295336
buffer.write(value: v, index: p)
296337
}
338+
339+
private func getOffset(
340+
at value: Int,
341+
within verifier: Verifier) throws -> Int
342+
{
343+
let offset: UOffset = try verifier.getValue(at: value)
344+
return Int(clamping: (Int(offset) &+ 0).magnitude)
345+
}
297346
}

0 commit comments

Comments
 (0)