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.
parent f9887071
...@@ -356,7 +356,8 @@ public: ...@@ -356,7 +356,8 @@ public:
void MutateOffset(uoffset_t i, const uint8_t *val) { void MutateOffset(uoffset_t i, const uint8_t *val) {
assert(i < size()); assert(i < size());
assert(sizeof(T) == sizeof(uoffset_t)); assert(sizeof(T) == sizeof(uoffset_t));
WriteScalar(data() + i, val - (Data() + i * sizeof(uoffset_t))); WriteScalar(data() + i,
static_cast<uoffset_t>(val - (Data() + i * sizeof(uoffset_t))));
} }
// Get a mutable pointer to tables/strings inside this vector. // Get a mutable pointer to tables/strings inside this vector.
...@@ -1495,7 +1496,8 @@ class Table { ...@@ -1495,7 +1496,8 @@ class Table {
bool SetPointer(voffset_t field, const uint8_t *val) { bool SetPointer(voffset_t field, const uint8_t *val) {
auto field_offset = GetOptionalFieldOffset(field); auto field_offset = GetOptionalFieldOffset(field);
if (!field_offset) return false; if (!field_offset) return false;
WriteScalar(data_ + field_offset, val - (data_ + field_offset)); WriteScalar(data_ + field_offset,
static_cast<uoffset_t>(val - (data_ + field_offset)));
return true; return true;
} }
......
...@@ -204,72 +204,76 @@ class ResizeContext { ...@@ -204,72 +204,76 @@ class ResizeContext {
if (DagCheck(table)) if (DagCheck(table))
return; // Table already visited. return; // Table already visited.
auto vtable = table->GetVTable(); 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 // 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. // memory, if the insertion point is before the table we can stop here.
auto tableloc = reinterpret_cast<uint8_t *>(table); auto tableloc = reinterpret_cast<uint8_t *>(table);
if (startptr_ <= tableloc) return; if (startptr_ <= tableloc) {
// Check each field. // Check if insertion point is between the table and a vtable that
auto fielddefs = objectdef.fields(); // precedes it. This can't happen in current construction code, but check
for (auto it = fielddefs->begin(); it != fielddefs->end(); ++it) { // just in case we ever change the way flatbuffers are built.
auto &fielddef = **it; Straddle<soffset_t, -1>(vtable, table, table);
auto base_type = fielddef.type()->base_type(); } else {
// Ignore scalars. // Check each field.
if (base_type <= reflection::Double) continue; auto fielddefs = objectdef.fields();
// Ignore fields that are not stored. for (auto it = fielddefs->begin(); it != fielddefs->end(); ++it) {
auto offset = table->GetOptionalFieldOffset(fielddef.offset()); auto &fielddef = **it;
if (!offset) continue; auto base_type = fielddef.type()->base_type();
// Ignore structs. // Ignore scalars.
auto subobjectdef = base_type == reflection::Obj ? if (base_type <= reflection::Double) continue;
schema_.objects()->Get(fielddef.type()->index()) : nullptr; // Ignore fields that are not stored.
if (subobjectdef && subobjectdef->is_struct()) continue; auto offset = table->GetOptionalFieldOffset(fielddef.offset());
// Get this fields' offset, and read it if safe. if (!offset) continue;
auto offsetloc = tableloc + offset; // Ignore structs.
if (DagCheck(offsetloc)) auto subobjectdef = base_type == reflection::Obj ?
continue; // This offset already visited. schema_.objects()->Get(fielddef.type()->index()) : nullptr;
auto ref = offsetloc + ReadScalar<uoffset_t>(offsetloc); if (subobjectdef && subobjectdef->is_struct()) continue;
Straddle<uoffset_t, 1>(offsetloc, ref, offsetloc); // Get this fields' offset, and read it if safe.
// Recurse. auto offsetloc = tableloc + offset;
switch (base_type) { if (DagCheck(offsetloc))
case reflection::Obj: { continue; // This offset already visited.
ResizeTable(*subobjectdef, reinterpret_cast<Table *>(ref)); auto ref = offsetloc + ReadScalar<uoffset_t>(offsetloc);
break; Straddle<uoffset_t, 1>(offsetloc, ref, offsetloc);
} // Recurse.
case reflection::Vector: { switch (base_type) {
auto elem_type = fielddef.type()->element(); case reflection::Obj: {
if (elem_type != reflection::Obj && elem_type != reflection::String) ResizeTable(*subobjectdef, reinterpret_cast<Table *>(ref));
break; 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::Vector: {
} auto elem_type = fielddef.type()->element();
case reflection::Union: { if (elem_type != reflection::Obj && elem_type != reflection::String)
ResizeTable(GetUnionType(schema_, objectdef, fielddef, *table), break;
reinterpret_cast<Table *>(ref)); auto vec = reinterpret_cast<Vector<uoffset_t> *>(ref);
break; 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);
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment