[Development] QString, QVariant and QSQLite

Alberto Mardegan mardy at users.sourceforge.net
Wed May 26 21:39:49 CEST 2021


Hi there!
  I'm encountering some sort of memory corruption issue in a library I'm
using, which does not cause a crash, but rather a QSQLite query to
sometimes simply return no results, without errors or warnings.

You can find the valgrind trace here:
https://git.sailfishos.org/mer-core/qtcontacts-sqlite/issues/7#note_90394

What is happening is that we bind a couple of SQLite parameters to a
prepared query. The first bound parameter is a QString.

1) The string is stored into a QVariant
2) QSqlQuery::bindValue() is called
3) in the sqlite plugin, the qvariant is copied into a const QVariant:
https://code.qt.io/cgit/qt/qtbase.git/tree/src/plugins/sqldrivers/sqlite/qsql_sqlite.cpp?h=5.12#n503
4) in line 539 of the SQLite plugin, the contents of the QVariant are
obtained just by calling QString::utf16() on the string data, without
extracting it from the QVariant.
5) the data is passed to sqlite with SQLITE_STATIC (sqlite will NOT copy it)
6) we move forward and iterate to the next bound parameter
7) our const QVariant goes out of scope (though valgrind shows that the
destructor is actually called on the next iteration of the for loop --
but I guess this is not fundamental)
8) the destructor of the const QVariant calls the destructor of the
QString stored in it, which frees the memory allocated in point 4 by
QString::utf16()

Now, I haven't dug very deep in QString and QVariant, I preferred to let
the experts talk first :-) Does the code in the QSQLite plugin look
correct to you?
Is it expected that QString::utf16() makes a memory allocation? And is
it correct that this happens even when the QString is const?
And why destroying a const QVariant causes the deallocation of the data
created by QString::utf16()??

The most plausible explanation is that I have some memory corruption
somewhere else in the program, but I find it curious that it never
crashes the program and that it manifests itself always in this code
path. Notice also that if I call QString::detach() on my parameter
before storing it into the QVariant I pass to QSqlQuery::bindValue(),
then valgrind never complains and QSQLite returns the expected results.

Or do you think it could be a bug in the QSQLite plugin?

Ciao,
  Alberto

-- 
http://www.mardy.it - Geek in un lingua international


More information about the Development mailing list