diff --git a/include/flatbuffers/flatbuffers.h b/include/flatbuffers/flatbuffers.h index 8cab3cd36..921d1dac1 100644 --- a/include/flatbuffers/flatbuffers.h +++ b/include/flatbuffers/flatbuffers.h @@ -356,7 +356,8 @@ public: void MutateOffset(uoffset_t i, const uint8_t *val) { assert(i < size()); assert(sizeof(T) == sizeof(uoffset_t)); - WriteScalar(data() + i, val - (Data() + i * sizeof(uoffset_t))); + WriteScalar(data() + i, + static_cast(val - (Data() + i * sizeof(uoffset_t)))); } // Get a mutable pointer to tables/strings inside this vector. @@ -1495,7 +1496,8 @@ class Table { bool SetPointer(voffset_t field, const uint8_t *val) { auto field_offset = GetOptionalFieldOffset(field); if (!field_offset) return false; - WriteScalar(data_ + field_offset, val - (data_ + field_offset)); + WriteScalar(data_ + field_offset, + static_cast(val - (data_ + field_offset))); return true; } diff --git a/src/reflection.cpp b/src/reflection.cpp index ff499ae99..8f2fc6905 100644 --- a/src/reflection.cpp +++ b/src/reflection.cpp @@ -204,72 +204,76 @@ class ResizeContext { if (DagCheck(table)) return; // Table already visited. auto vtable = table->GetVTable(); - // Check if the vtable offset points beyond the insertion point. - Straddle(table, vtable, table); - // This direction shouldn't happen because vtables that sit before tables - // are always directly adjacent, but check just in case we ever change the - // way flatbuffers are built. - Straddle(vtable, table, table); // Early out: since all fields inside the table must point forwards in // memory, if the insertion point is before the table we can stop here. auto tableloc = reinterpret_cast(table); - if (startptr_ <= tableloc) return; - // Check each field. - auto fielddefs = objectdef.fields(); - for (auto it = fielddefs->begin(); it != fielddefs->end(); ++it) { - auto &fielddef = **it; - auto base_type = fielddef.type()->base_type(); - // Ignore scalars. - if (base_type <= reflection::Double) continue; - // Ignore fields that are not stored. - auto offset = table->GetOptionalFieldOffset(fielddef.offset()); - if (!offset) continue; - // Ignore structs. - auto subobjectdef = base_type == reflection::Obj ? - schema_.objects()->Get(fielddef.type()->index()) : nullptr; - if (subobjectdef && subobjectdef->is_struct()) continue; - // Get this fields' offset, and read it if safe. - auto offsetloc = tableloc + offset; - if (DagCheck(offsetloc)) - continue; // This offset already visited. - auto ref = offsetloc + ReadScalar(offsetloc); - Straddle(offsetloc, ref, offsetloc); - // Recurse. - switch (base_type) { - case reflection::Obj: { - ResizeTable(*subobjectdef, reinterpret_cast(ref)); - break; - } - case reflection::Vector: { - auto elem_type = fielddef.type()->element(); - if (elem_type != reflection::Obj && elem_type != reflection::String) + if (startptr_ <= tableloc) { + // Check if insertion point is between the table and a vtable that + // precedes it. This can't happen in current construction code, but check + // just in case we ever change the way flatbuffers are built. + Straddle(vtable, table, table); + } else { + // Check each field. + auto fielddefs = objectdef.fields(); + for (auto it = fielddefs->begin(); it != fielddefs->end(); ++it) { + auto &fielddef = **it; + auto base_type = fielddef.type()->base_type(); + // Ignore scalars. + if (base_type <= reflection::Double) continue; + // Ignore fields that are not stored. + auto offset = table->GetOptionalFieldOffset(fielddef.offset()); + if (!offset) continue; + // Ignore structs. + auto subobjectdef = base_type == reflection::Obj ? + schema_.objects()->Get(fielddef.type()->index()) : nullptr; + if (subobjectdef && subobjectdef->is_struct()) continue; + // Get this fields' offset, and read it if safe. + auto offsetloc = tableloc + offset; + if (DagCheck(offsetloc)) + continue; // This offset already visited. + auto ref = offsetloc + ReadScalar(offsetloc); + Straddle(offsetloc, ref, offsetloc); + // Recurse. + switch (base_type) { + case reflection::Obj: { + ResizeTable(*subobjectdef, reinterpret_cast
(ref)); break; - auto vec = reinterpret_cast *>(ref); - auto elemobjectdef = elem_type == reflection::Obj - ? schema_.objects()->Get(fielddef.type()->index()) - : nullptr; - if (elemobjectdef && elemobjectdef->is_struct()) break; - for (uoffset_t i = 0; i < vec->size(); i++) { - auto loc = vec->Data() + i * sizeof(uoffset_t); - if (DagCheck(loc)) - continue; // This offset already visited. - auto dest = loc + vec->Get(i); - Straddle(loc, dest ,loc); - if (elemobjectdef) - ResizeTable(*elemobjectdef, reinterpret_cast
(dest)); } - break; + case reflection::Vector: { + auto elem_type = fielddef.type()->element(); + if (elem_type != reflection::Obj && elem_type != reflection::String) + break; + auto vec = reinterpret_cast *>(ref); + auto elemobjectdef = elem_type == reflection::Obj + ? schema_.objects()->Get(fielddef.type()->index()) + : nullptr; + if (elemobjectdef && elemobjectdef->is_struct()) break; + for (uoffset_t i = 0; i < vec->size(); i++) { + auto loc = vec->Data() + i * sizeof(uoffset_t); + if (DagCheck(loc)) + continue; // This offset already visited. + auto dest = loc + vec->Get(i); + Straddle(loc, dest ,loc); + if (elemobjectdef) + ResizeTable(*elemobjectdef, reinterpret_cast
(dest)); + } + break; + } + case reflection::Union: { + ResizeTable(GetUnionType(schema_, objectdef, fielddef, *table), + reinterpret_cast
(ref)); + break; + } + case reflection::String: + break; + default: + assert(false); } - case reflection::Union: { - ResizeTable(GetUnionType(schema_, objectdef, fielddef, *table), - reinterpret_cast
(ref)); - break; - } - case reflection::String: - break; - default: - assert(false); } + // Check if the vtable offset points beyond the insertion point. + // Must do this last, since GetOptionalFieldOffset above still reads + // this value. + Straddle(table, vtable, table); } }