Skip to content

[C++] : Issue with generated code when naked buffer on a field #8403

Closed as not planned
@nolankramer

Description

@nolankramer

This issue includes the issue pointed to by #8144, but was never actually fixed upstream due to developer inactivity.

As such, I'm riving their issue, and expanding on it - I found another place where it was assumed the user would never use naked pointers in the object API.

Here was their original example:

static_assert( FLATBUFFERS_VERSION_MAJOR == 23 &&
               FLATBUFFERS_VERSION_MINOR == 5 &&
               FLATBUFFERS_VERSION_REVISION == 26,
               "Non-compatible flatbuffers version included" );

Given this simplified schema:

table A{

    field1: uint32;

}

table B {

    list : [A] (required, cpp_ptr_type:"naked");

}

root_type B;

The erronous code is produced here:

inline void B::UnPackTo ( BT *_o, const ::flatbuffers::resolver_function_t *_resolver ) const {
        (void)_o;
        (void)_resolver;
        {
                auto _e = list();

                if ( _e ){
                        _o->list.resize( _e->size() );

                        for ( ::flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++ ){
                                if ( _o->list[_i] ){
                                        _e->Get( _i )->UnPackTo( _o->list[_i].get(), _resolver ); //here is the error : the .get()
                                }
                                else {
                                        _o->list[_i] = ( _e->Get( _i )->UnPack( _resolver ) );
                                }

                                ;
                        }
                }
                else {
                        _o->list.resize( 0 );
                }
        }
}

Additionally, defining just a field with a naked_ptr attribute on a circular table type can also result in erronous code:

table A{
  field1: B (cpp_ptr_type:"naked");
  field2: B (cpp_ptr_type:"naked");
}

table B {
   blah: uint;
}

root_type B;
inline void A::UnPackTo(AT*_o, const ::flatbuffers::resolver_function_t *_resolver) const {
  (void)_o;
  (void)_resolver;
  { auto _e = field1(); if (_e) { if(_o->field1) { _e->UnPackTo(_o->field1.get(), _resolver); } else { _o->field1 = (_e->UnPack(_resolver)); } } else if (_o->field1) { _o->field1.reset(); } } // Notice that .get() and .reset() are called
  { auto _e = field2(); if (_e) { if(_o->field2) { _e->UnPackTo(_o->field2.get(), _resolver); } else { _o->field2 = (_e->UnPack(_resolver)); } } else if (_o->field2) { _o->field2.reset(); } } // Notice that .get() and .reset() are called
}

In order to address this, I'm issuing a new PR that I will carry all the way through. The PR will include the fix from the included issue, as well as the fix for the second example.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions