mirror of
https://github.com/google/flatbuffers.git
synced 2026-11-10 14:15:07 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9698e11376 | ||
|
|
6dda43bbaa | ||
|
|
9a8a511b52 | ||
|
|
b8431fbcd7 | ||
|
|
5761d6e67a |
@@ -504,7 +504,6 @@ grpc::string GenerateInterface(grpc_generator::File* file,
|
||||
const grpc::string& filename) {
|
||||
grpc::string output;
|
||||
|
||||
std::set<grpc::string> generated_functions;
|
||||
std::map<grpc::string, grpc::string> vars;
|
||||
|
||||
vars["PATH"] = file->package();
|
||||
|
||||
@@ -271,7 +271,7 @@ namespace flatbuffers {
|
||||
#if (defined(_MSC_VER) && _MSC_VER >= 1800) || \
|
||||
(defined(__ANDROID__) && defined(__ANDROID_API__) && __ANDROID_API__>= 26) || \
|
||||
(defined(_XOPEN_VERSION) && (_XOPEN_VERSION >= 700)) && \
|
||||
!defined(__Fuchsia__)
|
||||
!defined(__Fuchsia__) && (!defined(__linux__) || defined(__GLIBC__))
|
||||
#define FLATBUFFERS_LOCALE_INDEPENDENT 1
|
||||
#else
|
||||
#define FLATBUFFERS_LOCALE_INDEPENDENT 0
|
||||
|
||||
@@ -24,15 +24,14 @@ class handle:
|
||||
struct offset:
|
||||
o:int
|
||||
|
||||
enum sizeof:
|
||||
sz_8 = 1
|
||||
sz_16 = 2
|
||||
sz_32 = 4
|
||||
sz_64 = 8
|
||||
sz_voffset = 2
|
||||
sz_uoffset = 4
|
||||
sz_soffset = 4
|
||||
sz_metadata_fields = 2
|
||||
let sz_8 = 1
|
||||
let sz_16 = 2
|
||||
let sz_32 = 4
|
||||
let sz_64 = 8
|
||||
let sz_voffset = 2
|
||||
let sz_uoffset = 4
|
||||
let sz_soffset = 4
|
||||
let sz_metadata_fields = 2
|
||||
|
||||
class builder:
|
||||
buf = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
|
||||
|
||||
@@ -722,8 +722,6 @@ void BinaryAnnotator::BuildTable(const uint64_t table_offset,
|
||||
BinaryRegionComment offset_field_comment;
|
||||
offset_field_comment.type = BinaryRegionCommentType::TableOffsetField;
|
||||
offset_field_comment.name = field->name()->c_str();
|
||||
const std::string offset_prefix =
|
||||
"offset to field `" + std::string(field->name()->c_str()) + "`";
|
||||
|
||||
// Validate any field that isn't inline (i.e., non-structs).
|
||||
if (!IsInlineField(field)) {
|
||||
|
||||
+2
-3
@@ -404,7 +404,7 @@ class CppGenerator : public BaseGenerator {
|
||||
code_ += "struct {{STRUCT_NAME}}BinarySchema {";
|
||||
code_ += " static const uint8_t *data() {";
|
||||
code_ += " // Buffer containing the binary schema.";
|
||||
code_ += " static const uint8_t bfbsData[" +
|
||||
code_ += " alignas(uint64_t) static const uint8_t bfbsData[" +
|
||||
NumToString(parser_.builder_.GetSize()) + "] = {";
|
||||
code_ += binary_schema_hex_text;
|
||||
code_ += " };";
|
||||
@@ -2737,7 +2737,6 @@ class CppGenerator : public BaseGenerator {
|
||||
if (!field.IsScalarOptional()) {
|
||||
const bool is_scalar = IsScalar(type.base_type);
|
||||
std::string accessor;
|
||||
std::string offset_size = "";
|
||||
if (is_scalar) {
|
||||
accessor = "GetField<";
|
||||
} else if (IsStruct(type)) {
|
||||
@@ -2815,7 +2814,7 @@ class CppGenerator : public BaseGenerator {
|
||||
|
||||
void GenTableFieldType(const FieldDef& field) {
|
||||
const auto& type = field.value.type;
|
||||
const auto offset_str = GenFieldOffsetName(field);
|
||||
[[maybe_unused]] const auto offset_str = GenFieldOffsetName(field);
|
||||
if (!field.IsScalarOptional()) {
|
||||
std::string afterptr = " *" + NullableExtension();
|
||||
code_.SetValue("FIELD_TYPE",
|
||||
|
||||
@@ -1149,8 +1149,6 @@ static bool GenerateDart(const Parser& parser, const std::string& path,
|
||||
|
||||
static std::string DartMakeRule(const Parser& parser, const std::string& path,
|
||||
const std::string& file_name) {
|
||||
auto filebase =
|
||||
flatbuffers::StripPath(flatbuffers::StripExtension(file_name));
|
||||
dart::DartGenerator generator(parser, path, file_name);
|
||||
auto make_rule = generator.Filename("") + ": ";
|
||||
|
||||
|
||||
@@ -2176,7 +2176,7 @@ class JavaGenerator : public BaseGenerator {
|
||||
if (field.deprecated) continue;
|
||||
if (field.value.type.base_type == BASE_TYPE_UTYPE) continue;
|
||||
if (field.value.type.element == BASE_TYPE_UTYPE) continue;
|
||||
const auto get_field = namer_.Method("get", field);
|
||||
[[maybe_unused]] const auto get_field = namer_.Method("get", field);
|
||||
|
||||
code += " this." + namer_.Field(field) + " = ";
|
||||
const auto type_name =
|
||||
|
||||
@@ -966,8 +966,6 @@ class KotlinGenerator : public BaseGenerator {
|
||||
auto bbgetter = ByteBufferGetter(field.value.type, "bb");
|
||||
auto ucast = CastToUsigned(field);
|
||||
auto offset_val = NumToString(field.value.offset);
|
||||
auto offset_prefix =
|
||||
"val o = __offset(" + offset_val + "); return o != 0 ? ";
|
||||
auto value_base_type = field.value.type.base_type;
|
||||
// Most field accessors need to retrieve and test the field offset
|
||||
// first, this is the offset value for that:
|
||||
|
||||
@@ -146,7 +146,7 @@ class KotlinKMPGenerator : public BaseGenerator {
|
||||
|
||||
std::string code =
|
||||
"// " + std::string(FlatBuffersGeneratedWarning()) + "\n\n";
|
||||
auto qualified = ns.GetFullyQualifiedName("");
|
||||
[[maybe_unused]] auto qualified = ns.GetFullyQualifiedName("");
|
||||
std::string namespace_name = namer_.Namespace(ns);
|
||||
if (!namespace_name.empty()) {
|
||||
code += "package " + namespace_name;
|
||||
@@ -341,7 +341,6 @@ class KotlinKMPGenerator : public BaseGenerator {
|
||||
std::string GenDefaultBufferValue(const FieldDef& field) const {
|
||||
auto& value = field.value;
|
||||
auto base_type = value.type.base_type;
|
||||
auto field_name = field.name;
|
||||
std::string suffix = IsScalar(base_type) ? LiteralSuffix(value.type) : "";
|
||||
if (field.IsScalarOptional()) {
|
||||
return "null";
|
||||
@@ -373,7 +372,6 @@ class KotlinKMPGenerator : public BaseGenerator {
|
||||
std::string GenDefaultValue(const FieldDef& field) const {
|
||||
auto& value = field.value;
|
||||
auto base_type = value.type.base_type;
|
||||
auto field_name = field.name;
|
||||
std::string suffix = LiteralSuffix(value.type);
|
||||
if (field.IsScalarOptional()) {
|
||||
return "null";
|
||||
@@ -1082,8 +1080,6 @@ class KotlinKMPGenerator : public BaseGenerator {
|
||||
auto return_type = GetterReturnType(field);
|
||||
auto bbgetter = ByteBufferGetter(field.value.type, "bb");
|
||||
auto offset_val = NumToString(field.value.offset);
|
||||
auto offset_prefix =
|
||||
"val o = offset(" + offset_val + "); return o != 0 ? ";
|
||||
auto value_base_type = field.value.type.base_type;
|
||||
// Most field accessors need to retrieve and test the field offset
|
||||
// first, this is the offset value for that:
|
||||
|
||||
@@ -2010,8 +2010,8 @@ class PythonGenerator : public BaseGenerator {
|
||||
void InitializeFromPackedBuf(const StructDef& struct_def,
|
||||
std::string* code_ptr) const {
|
||||
auto& code = *code_ptr;
|
||||
const auto struct_var = namer_.Variable(struct_def);
|
||||
const auto struct_type = namer_.Type(struct_def);
|
||||
[[maybe_unused]] const auto struct_var = namer_.Variable(struct_def);
|
||||
[[maybe_unused]] const auto struct_type = namer_.Type(struct_def);
|
||||
|
||||
code += GenIndents(1) + "@classmethod";
|
||||
code += GenIndents(1) + "def InitFromPackedBuf(cls, buf, pos=0):";
|
||||
|
||||
@@ -787,7 +787,6 @@ class SwiftGenerator : public BaseGenerator {
|
||||
}
|
||||
|
||||
void GenTableReaderFields(const FieldDef& field) {
|
||||
const auto offset = NumToString(field.value.offset);
|
||||
const auto field_field = namer_.Field(field);
|
||||
const auto type = GenType(field.value.type);
|
||||
code_.SetValue("FIELDVAR", namer_.Variable(field));
|
||||
@@ -1142,7 +1141,6 @@ class SwiftGenerator : public BaseGenerator {
|
||||
it != struct_def.fields.vec.end(); ++it) {
|
||||
const auto& field = **it;
|
||||
if (field.deprecated) continue;
|
||||
const auto offset = NumToString(field.value.offset);
|
||||
|
||||
code_.SetValue("FIELDVAR", namer_.Variable(field));
|
||||
code_.SetValue("VALUETYPE", GenerateVerifierType(field));
|
||||
@@ -1382,7 +1380,7 @@ class SwiftGenerator : public BaseGenerator {
|
||||
const auto& field = **it;
|
||||
if (field.deprecated) continue;
|
||||
|
||||
const auto type = GenType(field.value.type);
|
||||
[[maybe_unused]] const auto type = GenType(field.value.type);
|
||||
code_.SetValue("FIELDVAR", namer_.Variable(field));
|
||||
if (IsArray(field.value.type)) {
|
||||
code_.SetValue(
|
||||
|
||||
+3
-5
@@ -196,7 +196,8 @@ class TsGenerator : public BaseGenerator {
|
||||
SkipDir::OutputPathAndTrailingPathSeparator);
|
||||
symbolic_name = definition.defined_namespace->components.back();
|
||||
} else {
|
||||
auto def_mod_name = namer_.File(definition, SkipFile::SuffixAndExtension);
|
||||
[[maybe_unused]] auto def_mod_name =
|
||||
namer_.File(definition, SkipFile::SuffixAndExtension);
|
||||
symbolic_name = file_name_;
|
||||
filepath = path_ + symbolic_name + ".ts";
|
||||
}
|
||||
@@ -286,12 +287,11 @@ class TsGenerator : public BaseGenerator {
|
||||
auto base_name =
|
||||
namer_.Directories(it.second.ns->components, SkipDir::OutputPath) +
|
||||
base_file_name;
|
||||
auto ts_file_path = base_name + ".ts";
|
||||
[[maybe_unused]] auto ts_file_path = base_name + ".ts";
|
||||
auto base_name_rel = std::string("./");
|
||||
base_name_rel +=
|
||||
namer_.Directories(rel_components, SkipDir::OutputPath);
|
||||
base_name_rel += base_file_name;
|
||||
auto ts_file_path_rel = base_name_rel + ".ts";
|
||||
auto type_name = def.first;
|
||||
auto fully_qualified_type_name =
|
||||
it.second.ns->GetFullyQualifiedName(type_name);
|
||||
@@ -311,7 +311,6 @@ class TsGenerator : public BaseGenerator {
|
||||
const auto child_ns_level = it.second.ns->components.size() + 1;
|
||||
for (const auto& it2 : ns_defs_) {
|
||||
if (it2.second.ns->components.size() != child_ns_level) continue;
|
||||
auto ts_file_path = it2.second.path + ".ts";
|
||||
code += "export * as " + it2.second.symbolic_name + " from './";
|
||||
int count = it2.second.ns->components.size() > 1 ? 2 : 1;
|
||||
std::vector<std::string> rel_path;
|
||||
@@ -1176,7 +1175,6 @@ class TsGenerator : public BaseGenerator {
|
||||
if (union_type.enum_def) {
|
||||
const auto& enum_def = *union_type.enum_def;
|
||||
const auto enum_type = AddImport(imports, dependent, enum_def).name;
|
||||
const std::string union_accessor = "this." + field_name;
|
||||
|
||||
const auto union_has_string = UnionHasStringType(enum_def);
|
||||
const auto field_binded_method = "this." + field_name + ".bind(this)";
|
||||
|
||||
@@ -16,6 +16,30 @@
|
||||
|
||||
import Foundation
|
||||
|
||||
@inline(__always)
|
||||
private func verifySizePrefix(
|
||||
byteBuffer: inout ByteBuffer,
|
||||
requireExactSize: Bool,
|
||||
options: VerifierOptions) throws
|
||||
{
|
||||
let verifier = try Verifier(buffer: &byteBuffer, options: options)
|
||||
let prefixPosition = byteBuffer.reader
|
||||
let prefix: UOffset = try verifier.getValue(at: prefixPosition)
|
||||
let availableSize = byteBuffer.size &- UOffset(MemoryLayout<UOffset>.size)
|
||||
|
||||
if requireExactSize {
|
||||
guard prefix == availableSize else {
|
||||
throw FlatbuffersErrors.prefixedSizeNotEqualToBufferSize
|
||||
}
|
||||
} else if prefix > availableSize {
|
||||
throw FlatbuffersErrors.outOfBounds(
|
||||
position: UInt(prefixPosition)
|
||||
&+ UInt(MemoryLayout<UOffset>.size)
|
||||
&+ UInt(prefix),
|
||||
end: byteBuffer.capacity)
|
||||
}
|
||||
}
|
||||
|
||||
/// Takes in a prefixed sized buffer, where the prefixed size would be skipped.
|
||||
/// And would verify that the buffer passed is a valid `Flatbuffers` Object.
|
||||
/// - Parameters:
|
||||
@@ -31,6 +55,10 @@ public func getPrefixedSizeCheckedRoot<T: FlatBufferTable & Verifiable>(
|
||||
fileId: String? = nil,
|
||||
options: VerifierOptions = .init()) throws -> T
|
||||
{
|
||||
try verifySizePrefix(
|
||||
byteBuffer: &byteBuffer,
|
||||
requireExactSize: false,
|
||||
options: options)
|
||||
byteBuffer.skipPrefix()
|
||||
return try getCheckedRoot(
|
||||
byteBuffer: &byteBuffer,
|
||||
@@ -53,10 +81,11 @@ public func getCheckedPrefixedSizeRoot<T: FlatBufferTable & Verifiable>(
|
||||
fileId: String? = nil,
|
||||
options: VerifierOptions = .init()) throws -> T
|
||||
{
|
||||
let prefix = byteBuffer.skipPrefix()
|
||||
if prefix != byteBuffer.size {
|
||||
throw FlatbuffersErrors.prefixedSizeNotEqualToBufferSize
|
||||
}
|
||||
try verifySizePrefix(
|
||||
byteBuffer: &byteBuffer,
|
||||
requireExactSize: true,
|
||||
options: options)
|
||||
byteBuffer.skipPrefix()
|
||||
return try getCheckedRoot(
|
||||
byteBuffer: &byteBuffer,
|
||||
fileId: fileId,
|
||||
@@ -95,14 +124,15 @@ public func getCheckedRoot<T: FlatBufferTable & Verifiable>(
|
||||
options: VerifierOptions = .init()) throws -> T
|
||||
{
|
||||
var verifier = try Verifier(buffer: &byteBuffer, options: options)
|
||||
let rootPosition = byteBuffer.reader
|
||||
if let fileId = fileId {
|
||||
try verifier.verify(id: fileId)
|
||||
try verifier.verify(id: fileId, at: rootPosition)
|
||||
}
|
||||
try ForwardOffset<T>.verify(&verifier, at: 0, of: T.self)
|
||||
try ForwardOffset<T>.verify(&verifier, at: rootPosition, of: T.self)
|
||||
return T.init(
|
||||
byteBuffer,
|
||||
o: Int32(byteBuffer.read(def: UOffset.self, position: byteBuffer.reader))
|
||||
&+ Int32(byteBuffer.reader))
|
||||
o: Int32(byteBuffer.read(def: UOffset.self, position: rootPosition))
|
||||
&+ Int32(rootPosition))
|
||||
}
|
||||
|
||||
/// Returns a `NON-Checked` flatbuffers object
|
||||
|
||||
@@ -215,12 +215,16 @@ public struct Verifier {
|
||||
}
|
||||
|
||||
@inline(__always)
|
||||
func verify(id: String) throws {
|
||||
func verify(id: String, at position: Int) throws {
|
||||
let size = MemoryLayout<Int32>.size
|
||||
guard storage.capacity >= (size &* 2) else {
|
||||
guard
|
||||
position >= 0,
|
||||
position <= storage.capacity,
|
||||
storage.capacity - position >= size &* 2
|
||||
else {
|
||||
throw FlatbuffersErrors.bufferDoesntContainID
|
||||
}
|
||||
let str = _buffer.readString(at: size, count: size)
|
||||
let str = _buffer.readString(at: position &+ size, count: size)
|
||||
if id == str {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -373,6 +373,58 @@ final class FlatbuffersVerifierTests {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
func testSizePrefixedVerifierUsesPostPrefixRoot() throws {
|
||||
// The size prefix points to a valid empty decoy table at byte 44. The real
|
||||
// root at byte 4 points to a truncated UInt64 vector that must be rejected.
|
||||
let bytes: [UInt8] = [
|
||||
44, 0, 0, 0,
|
||||
16, 0, 0, 0,
|
||||
6, 0, 8, 0, 4, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
12, 0, 0, 0,
|
||||
8, 0, 0, 0, 0, 0, 0, 0,
|
||||
2, 0, 0, 0, 65, 66,
|
||||
0, 0,
|
||||
4, 0, 4, 0,
|
||||
4, 0, 0, 0,
|
||||
]
|
||||
|
||||
var strictBuffer = ByteBuffer(bytes: bytes)
|
||||
#expect(throws: FlatbuffersErrors.self) {
|
||||
try getCheckedPrefixedSizeRoot(
|
||||
byteBuffer: &strictBuffer) as Swift_Tests_Vectors
|
||||
}
|
||||
|
||||
var prefixedBuffer = ByteBuffer(bytes: bytes)
|
||||
#expect(throws: FlatbuffersErrors.self) {
|
||||
try getPrefixedSizeCheckedRoot(
|
||||
byteBuffer: &prefixedBuffer) as Swift_Tests_Vectors
|
||||
}
|
||||
|
||||
var builder = FlatBufferBuilder()
|
||||
let movie = Movie.createMovie(&builder)
|
||||
Movie.finish(&builder, end: movie, prefix: true)
|
||||
var validBuffer = builder.sizedBuffer
|
||||
let _: Movie = try getCheckedPrefixedSizeRoot(
|
||||
byteBuffer: &validBuffer,
|
||||
fileId: Movie.id)
|
||||
|
||||
var shortBuffer = ByteBuffer(bytes: [0, 0, 0, 0])
|
||||
#expect(throws: FlatbuffersErrors.bufferDoesntContainID) {
|
||||
try getCheckedRoot(
|
||||
byteBuffer: &shortBuffer,
|
||||
fileId: Movie.id) as Movie
|
||||
}
|
||||
|
||||
var oversizedPrefix = ByteBuffer(bytes: [5, 0, 0, 0, 0, 0, 0, 0])
|
||||
#expect(throws: FlatbuffersErrors.outOfBounds(position: 9, end: 8)) {
|
||||
try getPrefixedSizeCheckedRoot(
|
||||
byteBuffer: &oversizedPrefix) as Movie
|
||||
}
|
||||
#expect(oversizedPrefix.reader == 0)
|
||||
}
|
||||
|
||||
@Test
|
||||
func testFullVerifier() throws {
|
||||
_ =
|
||||
|
||||
Reference in New Issue
Block a user