[odb-users] odb crashes when querying object with section

Anton Paymyshev anton.paymyshev at gmail.com
Tue May 23 04:22:22 EDT 2017


Hello,
I'm having issues with
odb 2.5.0.a11
sqlite 3.13.0
vs2015 update 3
windows 10
both release and debug

Schema and code below.

Test case requires two runs.
On the first run sqlite database file is created and filled with a single
row.
On the second run it tries to query that single row and crashes in
*result.begin() line, crash stack(note garbage in capacity argument value)
is similar to:
  KernelBase.dll!_RaiseException at 16() Unknown
> vcruntime140.dll!_CxxThrowException(void * pExceptionObject=0x008ff654,
const _s__ThrowInfo * pThrowInfo=0x0f73a2fc) Line 131 C++
  odb-2.5.dll!__scrt_throw_std_bad_alloc() Line 33 C++
  odb-2.5.dll!operator new(unsigned int size=0xcdcdcdcd) Line 19 C++
  odb-2.5.dll!odb::details::basic_buffer_base::capacity(unsigned int
c=0xcdcdcdcd, unsigned int data_size=0x00000000) Line 21 C++
  odbbugtest.exe!odb::sqlite::object_result_impl<Test>::load_image() Line
132 C++
  odbbugtest.exe!odb::sqlite::object_result_impl<Test>::load_id() Line 95
C++
  odbbugtest.exe!odb::object_result_impl<Test>::load() Line 25 C++

My analysis:
- db->query<Test>() line runs object_statements<Test> construction which
leaves image_ field filled with garbage from heap. (Test case requires
"prepared" heap to be reproducible in release build)
- then object_result_impl<Test>::load_image() gets "truncated" result from
"statement_->load()" and goes to access::object_traits_impl< ::Test,
id_sqlite >::grow which tries to set sec1_value capacity to previously
uninitialized value(0xcdcdcdcd).


//-----schema (Schema.h):
#include <odb/core.hxx>
#include <odb/section.hxx>

#pragma db object
class Test
{
public:
#pragma db id
unsigned long id;

std::string str;

#pragma db section(mysection)
std::string sec1;

#pragma db load(lazy)
odb::section mysection;
};

//-----code (main.cpp):

#include <odb/sqlite/database.hxx>
#include <odb/schema-catalog.hxx>
#include <odb/query.hxx>

#include "Schema-odb.hxx"

int main()
{
std::unique_ptr<odb::sqlite::database> db;
odb::connection_ptr c;

try
{
db.reset(new odb::sqlite::database(L"test.db", SQLITE_OPEN_READWRITE));
c = db->connection();
}
catch (odb::exception &) //first run goes here, setup schema and a single
Test row
{
db.reset(new odb::sqlite::database(L"test.db", SQLITE_OPEN_READWRITE |
SQLITE_OPEN_CREATE));

c = db->connection();

odb::transaction t(c->begin());
odb::schema_catalog::create_schema(*db);

Test test;
test.id = 12345;
test.str = std::string(1024, 'x'); // comment that line and test case runs
OK

db->persist(test);

t.commit();

return 0;
}

odb::transaction t(c->begin());

{ // fill heap with garbage
for (auto i = 1; i < 10240; ++i)
std::vector<unsigned int> ttt(i, 0xcdcdcdcd);
}

auto result = db->query<Test>(odb::query<Test>::id == 12345);

auto &row = *result.begin(); // <--- crash here

//ASSERT(row.id == 12345)

t.commit();

return 0;
}


More information about the odb-users mailing list