Adds a way to verify/exposes Entities ids (#7221)

This commit is contained in:
mustiikhalil
2022-04-06 22:54:01 +02:00
committed by GitHub
parent 832c618f5f
commit 2049e52101
9 changed files with 98 additions and 14 deletions

View File

@@ -506,12 +506,13 @@ class SwiftGenerator : public BaseGenerator {
if (!struct_def.fixed) {
if (parser_.file_identifier_.length()) {
code_.SetValue("FILENAME", parser_.file_identifier_);
code_ += "{{ACCESS_TYPE}} static var id: String { \"{{FILENAME}}\" } ";
code_ +=
"{{ACCESS_TYPE}} static func finish(_ fbb: inout "
"FlatBufferBuilder, end: "
"Offset, prefix: Bool = false) { fbb.finish(offset: end, "
"fileId: "
"\"{{FILENAME}}\", addPrefix: prefix) }";
"{{STRUCTNAME}}.id, addPrefix: prefix) }";
}
code_ +=
"{{ACCESS_TYPE}} static func getRootAs{{SHORT_STRUCTNAME}}(bb: "

View File

@@ -400,10 +400,13 @@ public struct ByteBuffer {
/// SkipPrefix Skips the first 4 bytes in case one of the following
/// functions are called `getPrefixedSizeCheckedRoot` & `getPrefixedSizeRoot`
/// which allows us to skip the first 4 bytes instead of recreating the buffer
@discardableResult
@usableFromInline
mutating func skipPrefix() {
mutating func skipPrefix() -> Int32 {
_writerSize = _writerSize &- MemoryLayout<Int32>.size
return read(def: Int32.self, position: 0)
}
}
extension ByteBuffer: CustomDebugStringConvertible {

View File

@@ -19,6 +19,10 @@ import Foundation
/// Collection of thrown from the Flatbuffer verifier
public enum FlatbuffersErrors: Error, Equatable {
/// Thrown when verifying a file id that doesnt match buffer id
case bufferIdDidntMatchPassedId
/// Prefixed size doesnt match the current (readable) buffer size
case prefixedSizeNotEqualToBufferSize
/// Thrown when buffer is bigger than the allowed 2GiB
case exceedsMaxSizeAllowed
/// Thrown when there is an missaligned pointer at position

View File

@@ -28,10 +28,39 @@ import Foundation
/// the ``ByteBuffer`` and verifies the buffer by calling ``getCheckedRoot(byteBuffer:options:)``
public func getPrefixedSizeCheckedRoot<T: FlatBufferObject & Verifiable>(
byteBuffer: inout ByteBuffer,
fileId: String? = nil,
options: VerifierOptions = .init()) throws -> T
{
byteBuffer.skipPrefix()
return try getCheckedRoot(byteBuffer: &byteBuffer, options: options)
return try getCheckedRoot(
byteBuffer: &byteBuffer,
fileId: fileId,
options: options)
}
/// Takes in a prefixed sized buffer, where we check if the sized buffer is equal to prefix size.
/// And would verify that the buffer passed is a valid `Flatbuffers` Object.
/// - Parameters:
/// - byteBuffer: Buffer that needs to be checked and read
/// - options: Verifier options
/// - Throws: FlatbuffersErrors
/// - Returns: Returns a valid, checked Flatbuffers object
///
/// ``getPrefixedSizeCheckedRoot(byteBuffer:options:)`` would skip the first Bytes in
/// the ``ByteBuffer`` and verifies the buffer by calling ``getCheckedRoot(byteBuffer:options:)``
public func getCheckedPrefixedSizeRoot<T: FlatBufferObject & Verifiable>(
byteBuffer: inout ByteBuffer,
fileId: String? = nil,
options: VerifierOptions = .init()) throws -> T
{
let prefix = byteBuffer.skipPrefix()
if prefix != byteBuffer.size {
throw FlatbuffersErrors.prefixedSizeNotEqualToBufferSize
}
return try getCheckedRoot(
byteBuffer: &byteBuffer,
fileId: fileId,
options: options)
}
/// Takes in a prefixed sized buffer, where the prefixed size would be skipped.
@@ -61,9 +90,13 @@ public func getPrefixedSizeRoot<T: FlatBufferObject>(byteBuffer: inout ByteBuffe
/// and within the ``ByteBuffer`` range.
public func getCheckedRoot<T: FlatBufferObject & Verifiable>(
byteBuffer: inout ByteBuffer,
fileId: String? = nil,
options: VerifierOptions = .init()) throws -> T
{
var verifier = try Verifier(buffer: &byteBuffer, options: options)
if let fileId = fileId {
try verifier.verify(id: fileId)
}
try ForwardOffset<T>.verify(&verifier, at: 0, of: T.self)
return T.init(
byteBuffer,

View File

@@ -200,4 +200,14 @@ public struct Verifier {
internal mutating func finish() {
_depth -= 1
}
mutating func verify(id: String) throws {
let size = MemoryLayout<Int32>.size
let str = _buffer.readString(at: size, count: size)
if id == str {
return
}
throw FlatbuffersErrors.bufferIdDidntMatchPassedId
}
}

View File

@@ -201,12 +201,34 @@ final class FlatbuffersVerifierTests: XCTestCase {
XCTAssertNoThrow(try getCheckedRoot(byteBuffer: &byteBuffer) as Movie)
}
func testErrorWrongFileId() {
// swiftformat:disable all
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])
// swiftformat:enable all
XCTAssertThrowsError(try getCheckedRoot(byteBuffer: &byteBuffer, fileId: "FLEX") as Movie)
}
func testVerifyPrefixedBuffer() {
// swiftformat:disable all
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])
// swiftformat:enable all
XCTAssertThrowsError(
try getCheckedPrefixedSizeRoot(byteBuffer: &byteBuffer) as Movie)
}
func testFullVerifier() {
XCTAssertNoThrow(
try getCheckedRoot(
byteBuffer: &validFlatbuffersObject) as MyGame_Example_Monster)
}
func testFullVerifierWithFileId() {
XCTAssertNoThrow(
try getCheckedRoot(
byteBuffer: &validFlatbuffersObject,
fileId: MyGame_Example_Monster.id) as MyGame_Example_Monster)
}
func testInvalidBuffer() {
XCTAssertThrowsError(
try getCheckedRoot(

View File

@@ -683,7 +683,8 @@ public struct MyGame_InParentNamespace: FlatBufferObject, Verifiable, ObjectAPIP
public var __buffer: ByteBuffer! { return _accessor.bb }
private var _accessor: Table
public static func finish(_ fbb: inout FlatBufferBuilder, end: Offset, prefix: Bool = false) { fbb.finish(offset: end, fileId: "MONS", addPrefix: prefix) }
public static var id: String { "MONS" }
public static func finish(_ fbb: inout FlatBufferBuilder, end: Offset, prefix: Bool = false) { fbb.finish(offset: end, fileId: MyGame_InParentNamespace.id, addPrefix: prefix) }
public static func getRootAsInParentNamespace(bb: ByteBuffer) -> MyGame_InParentNamespace { return MyGame_InParentNamespace(Table(bb: bb, position: Int32(bb.read(def: UOffset.self, position: bb.reader)) + Int32(bb.reader))) }
private init(_ t: Table) { _accessor = t }
@@ -736,7 +737,8 @@ public struct MyGame_Example2_Monster: FlatBufferObject, Verifiable, ObjectAPIPa
public var __buffer: ByteBuffer! { return _accessor.bb }
private var _accessor: Table
public static func finish(_ fbb: inout FlatBufferBuilder, end: Offset, prefix: Bool = false) { fbb.finish(offset: end, fileId: "MONS", addPrefix: prefix) }
public static var id: String { "MONS" }
public static func finish(_ fbb: inout FlatBufferBuilder, end: Offset, prefix: Bool = false) { fbb.finish(offset: end, fileId: MyGame_Example2_Monster.id, addPrefix: prefix) }
public static func getRootAsMonster(bb: ByteBuffer) -> MyGame_Example2_Monster { return MyGame_Example2_Monster(Table(bb: bb, position: Int32(bb.read(def: UOffset.self, position: bb.reader)) + Int32(bb.reader))) }
private init(_ t: Table) { _accessor = t }
@@ -789,7 +791,8 @@ internal struct MyGame_Example_TestSimpleTableWithEnum: FlatBufferObject, Verifi
internal var __buffer: ByteBuffer! { return _accessor.bb }
private var _accessor: Table
internal static func finish(_ fbb: inout FlatBufferBuilder, end: Offset, prefix: Bool = false) { fbb.finish(offset: end, fileId: "MONS", addPrefix: prefix) }
internal static var id: String { "MONS" }
internal static func finish(_ fbb: inout FlatBufferBuilder, end: Offset, prefix: Bool = false) { fbb.finish(offset: end, fileId: MyGame_Example_TestSimpleTableWithEnum.id, addPrefix: prefix) }
internal static func getRootAsTestSimpleTableWithEnum(bb: ByteBuffer) -> MyGame_Example_TestSimpleTableWithEnum { return MyGame_Example_TestSimpleTableWithEnum(Table(bb: bb, position: Int32(bb.read(def: UOffset.self, position: bb.reader)) + Int32(bb.reader))) }
private init(_ t: Table) { _accessor = t }
@@ -871,7 +874,8 @@ public struct MyGame_Example_Stat: FlatBufferObject, Verifiable, ObjectAPIPacker
public var __buffer: ByteBuffer! { return _accessor.bb }
private var _accessor: Table
public static func finish(_ fbb: inout FlatBufferBuilder, end: Offset, prefix: Bool = false) { fbb.finish(offset: end, fileId: "MONS", addPrefix: prefix) }
public static var id: String { "MONS" }
public static func finish(_ fbb: inout FlatBufferBuilder, end: Offset, prefix: Bool = false) { fbb.finish(offset: end, fileId: MyGame_Example_Stat.id, addPrefix: prefix) }
public static func getRootAsStat(bb: ByteBuffer) -> MyGame_Example_Stat { return MyGame_Example_Stat(Table(bb: bb, position: Int32(bb.read(def: UOffset.self, position: bb.reader)) + Int32(bb.reader))) }
private init(_ t: Table) { _accessor = t }
@@ -1011,7 +1015,8 @@ public struct MyGame_Example_Referrable: FlatBufferObject, Verifiable, ObjectAPI
public var __buffer: ByteBuffer! { return _accessor.bb }
private var _accessor: Table
public static func finish(_ fbb: inout FlatBufferBuilder, end: Offset, prefix: Bool = false) { fbb.finish(offset: end, fileId: "MONS", addPrefix: prefix) }
public static var id: String { "MONS" }
public static func finish(_ fbb: inout FlatBufferBuilder, end: Offset, prefix: Bool = false) { fbb.finish(offset: end, fileId: MyGame_Example_Referrable.id, addPrefix: prefix) }
public static func getRootAsReferrable(bb: ByteBuffer) -> MyGame_Example_Referrable { return MyGame_Example_Referrable(Table(bb: bb, position: Int32(bb.read(def: UOffset.self, position: bb.reader)) + Int32(bb.reader))) }
private init(_ t: Table) { _accessor = t }
@@ -1118,7 +1123,8 @@ public struct MyGame_Example_Monster: FlatBufferObject, Verifiable, ObjectAPIPac
public var __buffer: ByteBuffer! { return _accessor.bb }
private var _accessor: Table
public static func finish(_ fbb: inout FlatBufferBuilder, end: Offset, prefix: Bool = false) { fbb.finish(offset: end, fileId: "MONS", addPrefix: prefix) }
public static var id: String { "MONS" }
public static func finish(_ fbb: inout FlatBufferBuilder, end: Offset, prefix: Bool = false) { fbb.finish(offset: end, fileId: MyGame_Example_Monster.id, addPrefix: prefix) }
public static func getRootAsMonster(bb: ByteBuffer) -> MyGame_Example_Monster { return MyGame_Example_Monster(Table(bb: bb, position: Int32(bb.read(def: UOffset.self, position: bb.reader)) + Int32(bb.reader))) }
private init(_ t: Table) { _accessor = t }
@@ -2275,7 +2281,8 @@ public struct MyGame_Example_TypeAliases: FlatBufferObject, Verifiable, ObjectAP
public var __buffer: ByteBuffer! { return _accessor.bb }
private var _accessor: Table
public static func finish(_ fbb: inout FlatBufferBuilder, end: Offset, prefix: Bool = false) { fbb.finish(offset: end, fileId: "MONS", addPrefix: prefix) }
public static var id: String { "MONS" }
public static func finish(_ fbb: inout FlatBufferBuilder, end: Offset, prefix: Bool = false) { fbb.finish(offset: end, fileId: MyGame_Example_TypeAliases.id, addPrefix: prefix) }
public static func getRootAsTypeAliases(bb: ByteBuffer) -> MyGame_Example_TypeAliases { return MyGame_Example_TypeAliases(Table(bb: bb, position: Int32(bb.read(def: UOffset.self, position: bb.reader)) + Int32(bb.reader))) }
private init(_ t: Table) { _accessor = t }

View File

@@ -33,7 +33,8 @@ public struct optional_scalars_ScalarStuff: FlatBufferObject, Verifiable {
public var __buffer: ByteBuffer! { return _accessor.bb }
private var _accessor: Table
public static func finish(_ fbb: inout FlatBufferBuilder, end: Offset, prefix: Bool = false) { fbb.finish(offset: end, fileId: "NULL", addPrefix: prefix) }
public static var id: String { "NULL" }
public static func finish(_ fbb: inout FlatBufferBuilder, end: Offset, prefix: Bool = false) { fbb.finish(offset: end, fileId: optional_scalars_ScalarStuff.id, addPrefix: prefix) }
public static func getRootAsScalarStuff(bb: ByteBuffer) -> optional_scalars_ScalarStuff { return optional_scalars_ScalarStuff(Table(bb: bb, position: Int32(bb.read(def: UOffset.self, position: bb.reader)) + Int32(bb.reader))) }
private init(_ t: Table) { _accessor = t }

View File

@@ -328,7 +328,8 @@ public struct Attacker: FlatBufferObject, Verifiable, ObjectAPIPacker {
public var __buffer: ByteBuffer! { return _accessor.bb }
private var _accessor: Table
public static func finish(_ fbb: inout FlatBufferBuilder, end: Offset, prefix: Bool = false) { fbb.finish(offset: end, fileId: "MOVI", addPrefix: prefix) }
public static var id: String { "MOVI" }
public static func finish(_ fbb: inout FlatBufferBuilder, end: Offset, prefix: Bool = false) { fbb.finish(offset: end, fileId: Attacker.id, addPrefix: prefix) }
public static func getRootAsAttacker(bb: ByteBuffer) -> Attacker { return Attacker(Table(bb: bb, position: Int32(bb.read(def: UOffset.self, position: bb.reader)) + Int32(bb.reader))) }
private init(_ t: Table) { _accessor = t }
@@ -410,7 +411,8 @@ public struct HandFan: FlatBufferObject, Verifiable, ObjectAPIPacker {
public var __buffer: ByteBuffer! { return _accessor.bb }
private var _accessor: Table
public static func finish(_ fbb: inout FlatBufferBuilder, end: Offset, prefix: Bool = false) { fbb.finish(offset: end, fileId: "MOVI", addPrefix: prefix) }
public static var id: String { "MOVI" }
public static func finish(_ fbb: inout FlatBufferBuilder, end: Offset, prefix: Bool = false) { fbb.finish(offset: end, fileId: HandFan.id, addPrefix: prefix) }
public static func getRootAsHandFan(bb: ByteBuffer) -> HandFan { return HandFan(Table(bb: bb, position: Int32(bb.read(def: UOffset.self, position: bb.reader)) + Int32(bb.reader))) }
private init(_ t: Table) { _accessor = t }
@@ -492,7 +494,8 @@ public struct Movie: FlatBufferObject, Verifiable, ObjectAPIPacker {
public var __buffer: ByteBuffer! { return _accessor.bb }
private var _accessor: Table
public static func finish(_ fbb: inout FlatBufferBuilder, end: Offset, prefix: Bool = false) { fbb.finish(offset: end, fileId: "MOVI", addPrefix: prefix) }
public static var id: String { "MOVI" }
public static func finish(_ fbb: inout FlatBufferBuilder, end: Offset, prefix: Bool = false) { fbb.finish(offset: end, fileId: Movie.id, addPrefix: prefix) }
public static func getRootAsMovie(bb: ByteBuffer) -> Movie { return Movie(Table(bb: bb, position: Int32(bb.read(def: UOffset.self, position: bb.reader)) + Int32(bb.reader))) }
private init(_ t: Table) { _accessor = t }