Size verifier fix 2 (#8740)

* Fixes to make SizeVerifier work.

In particular change all the places in the Flatbuffers library
and generated code that were using `Verifier` to instead use
`VerifierTemplate<TrackBufferSize>` and wrap them all inside
`template <bool TrackBufferSize = false>`.

Also add unit tests for SizeVerifier.

* Format using `sh scripts/clang-format-git.sh`

* Use `B` rather than `TrackBufferSize` for the name of the template parameter.

* Update generated files.
This commit is contained in:
Fergus Henderson
2025-11-24 12:11:32 +00:00
committed by GitHub
parent 7ea8db05d8
commit 20548ff3b6
30 changed files with 588 additions and 305 deletions

View File

@@ -681,17 +681,20 @@ class CppGenerator : public BaseGenerator {
code_.SetValue("ID", "nullptr");
}
code_ += "template <bool B = false>";
code_ += "inline bool Verify{{STRUCT_NAME}}Buffer(";
code_ += " ::flatbuffers::Verifier &verifier) {";
code_ += " return verifier.VerifyBuffer<{{CPP_NAME}}>({{ID}});";
code_ += " ::flatbuffers::VerifierTemplate<B> &verifier) {";
code_ += " return verifier.template VerifyBuffer<{{CPP_NAME}}>({{ID}});";
code_ += "}";
code_ += "";
code_ += "template <bool B = false>";
code_ += "inline bool VerifySizePrefixed{{STRUCT_NAME}}Buffer(";
code_ += " ::flatbuffers::Verifier &verifier) {";
code_ += " ::flatbuffers::VerifierTemplate<B> &verifier) {";
code_ +=
" return "
"verifier.VerifySizePrefixedBuffer<{{CPP_NAME}}{{SIZE_T}}>({{ID}});";
"verifier.template "
"VerifySizePrefixedBuffer<{{CPP_NAME}}{{SIZE_T}}>({{ID}});";
code_ += "}";
code_ += "";
@@ -1102,19 +1105,31 @@ class CppGenerator : public BaseGenerator {
}
}
// For the initial declaration, we specify the template parameters,
// including template default arguments.
std::string UnionVerifyTemplateDecl() { return "template <bool B = false>"; }
// For the subsequent definition, we must not redeclare the template default
// arguments.
std::string UnionVerifyTemplateDef() { return "template <bool B>"; }
// Should be used in conjunction with
// UnionVerifyTemplateDecl()/UnionVerifyTemplateDef().
std::string UnionVerifySignature(const EnumDef& enum_def) {
return "bool Verify" + Name(enum_def) +
"(::flatbuffers::Verifier &verifier, const void *obj, " +
Name(enum_def) + " type)";
"(::flatbuffers::VerifierTemplate<B> &verifier, " +
"const void *obj, " + Name(enum_def) + " type)";
}
// Should be used in conjunction with
// UnionVerifyTemplateDecl()/UnionVerifyTemplateDef().
std::string UnionVectorVerifySignature(const EnumDef& enum_def) {
const std::string name = Name(enum_def);
const std::string& type =
opts_.scoped_enums ? name
: GenTypeBasic(enum_def.underlying_type, false);
return "bool Verify" + name + "Vector" +
"(::flatbuffers::Verifier &verifier, " +
"(::flatbuffers::VerifierTemplate<B> &verifier, " +
"const ::flatbuffers::Vector<::flatbuffers::Offset<void>> "
"*values, " +
"const ::flatbuffers::Vector<" + type + "> *types)";
@@ -1409,7 +1424,9 @@ class CppGenerator : public BaseGenerator {
GenEnumObjectBasedAPI(enum_def);
if (enum_def.is_union) {
code_ += UnionVerifyTemplateDecl();
code_ += UnionVerifySignature(enum_def) + ";";
code_ += UnionVerifyTemplateDecl();
code_ += UnionVectorVerifySignature(enum_def) + ";";
code_ += "";
}
@@ -1638,6 +1655,7 @@ class CppGenerator : public BaseGenerator {
// on the wrong type.
code_.SetValue("ENUM_NAME", Name(enum_def));
code_ += UnionVerifyTemplateDef();
code_ += "inline " + UnionVerifySignature(enum_def) + " {";
code_ += " switch (type) {";
for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); ++it) {
@@ -1654,7 +1672,7 @@ class CppGenerator : public BaseGenerator {
code_.SetValue("ALIGN",
NumToString(ev.union_type.struct_def->minalign));
code_ +=
" return verifier.VerifyField<{{TYPE}}>("
" return verifier.template VerifyField<{{TYPE}}>("
"static_cast<const uint8_t *>(obj), 0, {{ALIGN}});";
} else {
code_ += getptr;
@@ -1678,6 +1696,7 @@ class CppGenerator : public BaseGenerator {
code_ += "}";
code_ += "";
code_ += UnionVerifyTemplateDef();
code_ += "inline " + UnionVectorVerifySignature(enum_def) + " {";
code_ += " if (!values || !types) return !values && !types;";
code_ += " if (values->size() != types->size()) return false;";
@@ -2412,7 +2431,7 @@ class CppGenerator : public BaseGenerator {
code_.SetValue("CPP_NAME", nfn);
// FIXME: file_identifier.
code_ +=
"{{PRE}}verifier.VerifyNestedFlatBuffer<{{CPP_NAME}}>"
"{{PRE}}verifier.template VerifyNestedFlatBuffer<{{CPP_NAME}}>"
"({{NAME}}(), nullptr)\\";
} else if (field.flexbuffer) {
code_ +=
@@ -3001,7 +3020,10 @@ class CppGenerator : public BaseGenerator {
// Generate a verifier function that can check a buffer from an untrusted
// source will never cause reads outside the buffer.
code_ += " bool Verify(::flatbuffers::Verifier &verifier) const {";
code_ += " template <bool B = false>";
code_ +=
" bool Verify(::flatbuffers::VerifierTemplate<B> "
"&verifier) const {";
code_ += " return VerifyTableStart(verifier)\\";
for (const auto& field : struct_def.fields.vec) {
if (field->deprecated) {