1 /*
2  * Copyright 2021 Google Inc. All rights reserved.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 import XCTest
18 @testable import FlatBuffers
19 
20 final class FlatbuffersVerifierTests: XCTestCase {
21 
22   lazy var validStorage: ByteBuffer.Storage = ByteBuffer.Storage(
23     count: Int(FlatBufferMaxSize) - 1,
24     alignment: 1)
25   lazy var errorStorage: ByteBuffer.Storage = ByteBuffer.Storage(
26     count: Int(FlatBufferMaxSize) + 1,
27     alignment: 1)
28 
29   var buffer: ByteBuffer!
30 
31   var validFlatbuffersObject: ByteBuffer!
32   var invalidFlatbuffersObject: ByteBuffer!
33 
setUpnull34   override func setUp() {
35     // swiftformat:disable all
36     buffer = ByteBuffer(initialSize: 32)
37     add(buffer: &buffer, v: 4, p: 16)
38     add(buffer: &buffer, v: 4, p: 20)
39 
40     validFlatbuffersObject = ByteBuffer(bytes: [48, 0, 0, 0, 77, 79, 78, 83, 0, 0, 0, 0, 36, 0, 72, 0, 40, 0, 0, 0, 38, 0, 32, 0, 0, 0, 28, 0, 0, 0, 27, 0, 20, 0, 16, 0, 12, 0, 4, 0, 0, 0, 0, 0, 0, 0, 11, 0, 36, 0, 0, 0, 164, 0, 0, 0, 0, 0, 0, 1, 60, 0, 0, 0, 68, 0, 0, 0, 76, 0, 0, 0, 0, 0, 0, 1, 88, 0, 0, 0, 120, 0, 0, 0, 0, 0, 80, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 64, 2, 0, 5, 0, 6, 0, 0, 0, 2, 0, 0, 0, 64, 0, 0, 0, 48, 0, 0, 0, 2, 0, 0, 0, 30, 0, 40, 0, 10, 0, 20, 0, 152, 255, 255, 255, 4, 0, 0, 0, 4, 0, 0, 0, 70, 114, 101, 100, 0, 0, 0, 0, 5, 0, 0, 0, 0, 1, 2, 3, 4, 0, 0, 0, 5, 0, 0, 0, 116, 101, 115, 116, 50, 0, 0, 0, 5, 0, 0, 0, 116, 101, 115, 116, 49, 0, 0, 0, 9, 0, 0, 0, 77, 121, 77, 111, 110, 115, 116, 101, 114, 0, 0, 0, 3, 0, 0, 0, 20, 0, 0, 0, 36, 0, 0, 0, 4, 0, 0, 0, 240, 255, 255, 255, 32, 0, 0, 0, 248, 255, 255, 255, 36, 0, 0, 0, 12, 0, 8, 0, 0, 0, 0, 0, 0, 0, 4, 0, 12, 0, 0, 0, 28, 0, 0, 0, 5, 0, 0, 0, 87, 105, 108, 109, 97, 0, 0, 0, 6, 0, 0, 0, 66, 97, 114, 110, 101, 121, 0, 0, 5, 0, 0, 0, 70, 114, 111, 100, 111, 0, 0, 0])
41 
42     invalidFlatbuffersObject = ByteBuffer(bytes: [0, 48, 0, 0, 0, 77, 79, 78, 83, 0, 0, 0, 0, 36, 0, 72, 0, 40, 0, 0, 0, 38, 0, 32, 0, 0, 0, 28, 0, 0, 0, 27, 0, 20, 0, 16, 0, 12, 0, 4, 0, 0, 0, 0, 0, 0, 0, 11, 0, 36, 0, 0, 0, 164, 0, 0, 0, 0, 0, 0, 1, 60, 0, 0, 0, 68, 0, 0, 0, 76, 0, 0, 0, 0, 0, 0, 1, 88, 0, 0, 0, 120, 0, 0, 0, 0, 0, 80, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 64, 2, 0, 5, 0, 6, 0, 0, 0, 2, 0, 0, 0, 64, 0, 0, 0, 48, 0, 0, 0, 2, 0, 0, 0, 30, 0, 40, 0, 10, 0, 20, 0, 152, 255, 255, 255, 4, 0, 0, 0, 4, 0, 0, 0, 70, 114, 101, 100, 0, 0, 0, 0, 5, 0, 0, 0, 0, 1, 2, 3, 4, 0, 0, 0, 5, 0, 0, 0, 116, 101, 115, 116, 50, 0, 0, 0, 5, 0, 0, 0, 116, 101, 115, 116, 49, 0, 0, 0, 9, 0, 0, 0, 77, 121, 77, 111, 110, 115, 116, 101, 114, 0, 0, 0, 3, 0, 0, 0, 20, 0, 0, 0, 36, 0, 0, 0, 4, 0, 0, 0, 240, 255, 255, 255, 32, 0, 0, 0, 248, 255, 255, 255, 36, 0, 0, 0, 12, 0, 8, 0, 0, 0, 0, 0, 0, 0, 4, 0, 12, 0, 0, 0, 28, 0, 0, 0, 5, 0, 0, 0, 87, 105, 108, 109, 97, 0, 0, 0, 6, 0, 0, 0, 66, 97, 114, 110, 101, 121, 0, 0, 5, 0, 0, 0, 70, 114, 111, 100, 111, 0, 0, 0])
43 
44     // swiftformat:enable all
45   }
46 
testVeriferInitPassingnull47   func testVeriferInitPassing() {
48     var buffer = ByteBuffer(initialSize: 0)
49     buffer._storage = validStorage
50     XCTAssertNoThrow(try Verifier(buffer: &buffer))
51   }
52 
testVeriferInitFailingnull53   func testVeriferInitFailing() {
54     var buffer = ByteBuffer(initialSize: 0)
55     buffer._storage = errorStorage
56     XCTAssertThrowsError(try Verifier(buffer: &buffer))
57   }
58 
testVerifierCheckAlignmentnull59   func testVerifierCheckAlignment() {
60     var verifier = try! Verifier(buffer: &buffer)
61     do {
62       try verifier.isAligned(position: 20, type: Int.self)
63     } catch {
64       XCTAssertEqual(
65         error as? FlatbuffersErrors,
66         .missAlignedPointer(position: 20, type: "Int"))
67     }
68     XCTAssertNoThrow(try verifier.isAligned(position: 16, type: Int.self))
69 
70     var newVerifer = try! Verifier(buffer: &buffer, checkAlignment: false)
71     XCTAssertNoThrow(try newVerifer.isAligned(position: 16, type: Int.self))
72   }
73 
testRangeInBuffernull74   func testRangeInBuffer() {
75     var verifier = try! Verifier(buffer: &buffer)
76     let size = MemoryLayout<Int64>.size
77     XCTAssertNoThrow(try verifier.rangeInBuffer(position: 24, size: size))
78     XCTAssertThrowsError(try verifier.rangeInBuffer(position: 26, size: size))
79     XCTAssertThrowsError(try verifier.rangeInBuffer(position: 26, size: size))
80     XCTAssertThrowsError(try verifier.rangeInBuffer(position: 30, size: size))
81     XCTAssertThrowsError(try verifier.rangeInBuffer(position: 32, size: size))
82     XCTAssertThrowsError(try verifier.rangeInBuffer(position: 34, size: size))
83 
84     verifier = try! Verifier(
85       buffer: &buffer,
86       options: .init(maxDepth: 0, maxTableCount: 0, maxApparentSize: 4))
87     do {
88       try verifier.rangeInBuffer(position: 24, size: size)
89     } catch {
90       XCTAssertEqual(
91         error as! FlatbuffersErrors,
92         .apparentSizeTooLarge)
93     }
94   }
95 
testPositionInBuffernull96   func testPositionInBuffer() {
97     var verifier = try! Verifier(buffer: &buffer)
98     XCTAssertNoThrow(try verifier.inBuffer(position: 0, of: Int64.self))
99     XCTAssertNoThrow(try verifier.inBuffer(position: 24, of: Int64.self))
100     XCTAssertThrowsError(try verifier.inBuffer(position: -9, of: Int64.self))
101     XCTAssertThrowsError(try verifier.inBuffer(position: 25, of: Int64.self))
102     XCTAssertThrowsError(try verifier.inBuffer(position: 26, of: Int32.self))
103     XCTAssertThrowsError(try verifier.inBuffer(position: 26, of: Int64.self))
104     XCTAssertThrowsError(try verifier.inBuffer(position: 30, of: Int64.self))
105     XCTAssertThrowsError(try verifier.inBuffer(position: 32, of: Int64.self))
106     XCTAssertThrowsError(try verifier.inBuffer(position: 34, of: Int64.self))
107   }
108 
testVisitTablenull109   func testVisitTable() {
110     var verifier = try! Verifier(buffer: &validFlatbuffersObject)
111     XCTAssertNoThrow(try verifier.visitTable(at: 48))
112     verifier.reset()
113   }
114 
testTableVerifiernull115   func testTableVerifier() {
116     var verifier = try! Verifier(buffer: &validFlatbuffersObject)
117 
118     var tableVerifer = try! verifier.visitTable(at: 48)
119     XCTAssertNoThrow(try tableVerifer.visit(
120       field: 4,
121       fieldName: "Vec",
122       required: false,
123       type: Vec3.self))
124     XCTAssertNoThrow(try tableVerifer.visit(
125       field: 8,
126       fieldName: "hp",
127       required: false,
128       type: Int16.self))
129 
130     XCTAssertNoThrow(try tableVerifer.visit(
131       field: 10,
132       fieldName: "name",
133       required: true,
134       type: ForwardOffset<String>.self))
135 
136     XCTAssertNoThrow(try tableVerifer.visit(
137       field: 14,
138       fieldName: "inventory",
139       required: false,
140       type: ForwardOffset<Vector<UInt8, UInt8>>.self))
141 
142     XCTAssertNoThrow(try tableVerifer.visit(
143       field: 22,
144       fieldName: "test4",
145       required: false,
146       type: ForwardOffset<Vector<MyGame_Example_Test, MyGame_Example_Test>>
147         .self))
148 
149     XCTAssertNoThrow(try tableVerifer.visit(
150       field: 24,
151       fieldName: "Vector of strings",
152       required: false,
153       type: ForwardOffset<Vector<ForwardOffset<String>, String>>.self))
154 
155     do {
156       try tableVerifer.visit(
157         field: 13,
158         fieldName: "notvalid",
159         required: false,
160         type: Int16.self)
161     } catch {
162       XCTAssertEqual(
163         error as! FlatbuffersErrors,
164         .missAlignedPointer(position: 25, type: "UInt16"))
165     }
166 
167     do {
168       try tableVerifer.visit(
169         unionKey: 18,
170         unionField: 20,
171         unionKeyName: "testType",
172         fieldName: "test",
173         required: false,
174         completion: { (verifier, key: MyGame_Example_Any_, pos) in
175           switch key {
176           case .none_:
177             break
178           case .monster:
179             try ForwardOffset<MyGame_Example_Monster>.verify(
180               &verifier,
181               at: pos,
182               of: MyGame_Example_Monster.self)
183 
184           case .testsimpletablewithenum:
185             break
186           case .mygameExample2Monster:
187             break
188           }
189         })
190     } catch {
191       XCTAssertEqual(
192         error as! FlatbuffersErrors,
193         .missAlignedPointer(position: 25, type: "UInt16"))
194     }
195   }
196 
testVerifyUnionVectorsnull197   func testVerifyUnionVectors() {
198     // swiftformat:disable all
199     var byteBuffer = ByteBuffer(bytes: [20, 0, 0, 0, 77, 79, 86, 73, 12, 0, 12, 0, 0, 0, 0, 0, 8, 0, 4, 0, 12, 0, 0, 0, 8, 0, 0, 0, 20, 0, 0, 0, 3, 0, 0, 0, 24, 0, 0, 0, 32, 0, 0, 0, 12, 0, 0, 0, 3, 0, 0, 0, 3, 1, 4, 0, 2, 0, 0, 0, 7, 0, 0, 0, 0, 0, 6, 0, 8, 0, 4, 0, 6, 0, 0, 0, 8, 0, 0, 0])
200     // swiftformat:enable all
201     XCTAssertNoThrow(try getCheckedRoot(byteBuffer: &byteBuffer) as Movie)
202   }
203 
testErrorWrongFileIdnull204   func testErrorWrongFileId() {
205     // swiftformat:disable all
206     var byteBuffer = ByteBuffer(bytes: [20, 0, 0, 0, 77, 79, 86, 73, 12, 0, 12, 0, 0, 0, 0, 0, 8, 0, 4, 0, 12, 0, 0, 0, 8, 0, 0, 0, 20, 0, 0, 0, 3, 0, 0, 0, 24, 0, 0, 0, 32, 0, 0, 0, 12, 0, 0, 0, 3, 0, 0, 0, 3, 1, 4, 0, 2, 0, 0, 0, 7, 0, 0, 0, 0, 0, 6, 0, 8, 0, 4, 0, 6, 0, 0, 0, 8, 0, 0, 0])
207     // swiftformat:enable all
208     XCTAssertThrowsError(try getCheckedRoot(byteBuffer: &byteBuffer, fileId: "FLEX") as Movie)
209   }
210 
testVerifyPrefixedBuffernull211   func testVerifyPrefixedBuffer() {
212     // swiftformat:disable all
213     var byteBuffer = ByteBuffer(bytes: [0, 0, 0, 1, 20, 0, 0, 0, 77, 79, 86, 73, 12, 0, 12, 0, 0, 0, 0, 0, 8, 0, 4, 0, 12, 0, 0, 0, 8, 0, 0, 0, 20, 0, 0, 0, 3, 0, 0, 0, 24, 0, 0, 0, 32, 0, 0, 0, 12, 0, 0, 0, 3, 0, 0, 0, 3, 1, 4, 0, 2, 0, 0, 0, 7, 0, 0, 0, 0, 0, 6, 0, 8, 0, 4, 0, 6, 0, 0, 0, 8, 0, 0, 0])
214     // swiftformat:enable all
215     XCTAssertThrowsError(
216       try getCheckedPrefixedSizeRoot(byteBuffer: &byteBuffer) as Movie)
217   }
218 
testFullVerifiernull219   func testFullVerifier() {
220     XCTAssertNoThrow(
221       try getCheckedRoot(
222         byteBuffer: &validFlatbuffersObject) as MyGame_Example_Monster)
223   }
224 
testFullVerifierWithFileIdnull225   func testFullVerifierWithFileId() {
226     XCTAssertNoThrow(
227       try getCheckedRoot(
228         byteBuffer: &validFlatbuffersObject,
229         fileId: MyGame_Example_Monster.id) as MyGame_Example_Monster)
230   }
231 
testInvalidBuffernull232   func testInvalidBuffer() {
233     XCTAssertThrowsError(
234       try getCheckedRoot(
235         byteBuffer: &invalidFlatbuffersObject) as MyGame_Example_Monster)
236   }
237 
testValidUnionBuffernull238   func testValidUnionBuffer() {
239     let string = "Awesome \\\\t\t\nstring!"
240     var fb = FlatBufferBuilder()
241     let stringOffset = fb.create(string: string)
242     let characterType: [Character] = [.bookfan, .other]
243 
244     let characters = [
245       fb.create(struct: BookReader(booksRead: 7)),
246       stringOffset,
247     ]
248     let types = fb.createVector(characterType)
249     let characterVector = fb.createVector(ofOffsets: characters)
250 
251     let end = Movie.createMovie(
252       &fb,
253       mainCharacterType: .other,
254       mainCharacterOffset: Offset(offset: stringOffset.o),
255       charactersTypeVectorOffset: types,
256       charactersVectorOffset: characterVector)
257     Movie.finish(&fb, end: end)
258     var buf = fb.sizedBuffer
259     XCTAssertNoThrow(try getCheckedRoot(byteBuffer: &buf) as Movie)
260   }
261 
addnull262   func add(buffer: inout ByteBuffer, v: Int32, p: Int) {
263     buffer.write(value: v, index: p)
264   }
265 }
266