summaryrefslogtreecommitdiff
path: root/src/reflection.cpp
diff options
context:
space:
mode:
authorWouter van Oortmerssen <wvo@google.com>2016-07-25 14:43:41 -0700
committerWouter van Oortmerssen <wvo@google.com>2016-07-25 15:01:37 -0700
commit1bba4fd9ea3e06e5d6aa712dbce3e2e7c326321e (patch)
treee46015960730db5eff30245b1b4af058ba232ff1 /src/reflection.cpp
parentf98870715a56875616b9a476a5fd21f05264b445 (diff)
downloadflatbuffers-1bba4fd9ea3e06e5d6aa712dbce3e2e7c326321e.tar.gz
flatbuffers-1bba4fd9ea3e06e5d6aa712dbce3e2e7c326321e.tar.bz2
flatbuffers-1bba4fd9ea3e06e5d6aa712dbce3e2e7c326321e.zip
Fixed reflection.h not modifying certain table configurations.
It would write 64bits offsets instead of 32bit ones, and update the vtable pointer before the fields were processed. Change-Id: I0c0fa942bbd3b42839294f5653ba8fa048612624 Tested: on Linux.
Diffstat (limited to 'src/reflection.cpp')
-rw-r--r--src/reflection.cpp122
1 files changed, 63 insertions, 59 deletions
diff --git a/src/reflection.cpp b/src/reflection.cpp
index ff499ae9..8f2fc690 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<soffset_t, -1>(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<soffset_t, -1>(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<uint8_t *>(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<uoffset_t>(offsetloc);
- Straddle<uoffset_t, 1>(offsetloc, ref, offsetloc);
- // Recurse.
- switch (base_type) {
- case reflection::Obj: {
- ResizeTable(*subobjectdef, reinterpret_cast<Table *>(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<soffset_t, -1>(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<uoffset_t>(offsetloc);
+ Straddle<uoffset_t, 1>(offsetloc, ref, offsetloc);
+ // Recurse.
+ switch (base_type) {
+ case reflection::Obj: {
+ ResizeTable(*subobjectdef, reinterpret_cast<Table *>(ref));
break;
- auto vec = reinterpret_cast<Vector<uoffset_t> *>(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<uoffset_t, 1>(loc, dest ,loc);
- if (elemobjectdef)
- ResizeTable(*elemobjectdef, reinterpret_cast<Table *>(dest));
}
- break;
- }
- case reflection::Union: {
- ResizeTable(GetUnionType(schema_, objectdef, fielddef, *table),
- reinterpret_cast<Table *>(ref));
- break;
+ case reflection::Vector: {
+ auto elem_type = fielddef.type()->element();
+ if (elem_type != reflection::Obj && elem_type != reflection::String)
+ break;
+ auto vec = reinterpret_cast<Vector<uoffset_t> *>(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<uoffset_t, 1>(loc, dest ,loc);
+ if (elemobjectdef)
+ ResizeTable(*elemobjectdef, reinterpret_cast<Table *>(dest));
+ }
+ break;
+ }
+ case reflection::Union: {
+ ResizeTable(GetUnionType(schema_, objectdef, fielddef, *table),
+ reinterpret_cast<Table *>(ref));
+ break;
+ }
+ case reflection::String:
+ break;
+ default:
+ assert(false);
}
- 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<soffset_t, -1>(table, vtable, table);
}
}