[Development] QString, QVariant and QSQLite

Chris Adams chris.adams at qinetic.com.au
Thu May 27 05:12:33 CEST 2021


Hi,

On Thu, May 27, 2021 at 7:34 AM Alberto Mardegan <
mardy at users.sourceforge.net> wrote:

> On 26/05/21 23:31, Christian Ehrlicher wrote:
> > Your observation looks correct even though I wonder why this was never
> > found before since this was not changed since the initial Qt5 import :)
> > What Qt version do you use?
> > Please fill a bug report with a minimal, compilable example.
>
> I'm using Qt 5.12, but as you wrote, this part of code has not being
> deeply modified in years.
>
> I'll file a bug if I manage to code a small example which reproduces it.
>

 The following is pretty similar:

#include <QtCore/QString>
#include <QtCore/QChar>
#include <QtCore/QList>
#include <QtDebug>

int main(int, char **)
{
    const QChar ch('z');
    QString a(QStringLiteral("z"));
    QString b(QString::fromUtf8("z"));
    QString c(QString::fromRawData(&ch, 1));

    QString accumulated;
    for (int i = 0; i < 1000; ++i) {
        QList<const ushort*> pointers;

        // allocate some copies, store value returned from utf16(), destroy
copies.
        {
            const QString copyA = a;
            const QString copyB = b;
            const QString copyC = c;

            pointers.append(copyA.utf16());
            pointers.append(copyB.utf16());
            pointers.append(copyC.utf16());
        }

        // allocate some random stuff.
        QChar ych('y');
        QString w(QStringLiteral("w"));
        QString x(QString::fromUtf8("x"));
        QString y(QString::fromRawData(&ych, 1));

        // use the values which were previously returned from utf16()
        for (auto ptr : pointers) {
            accumulated.append(QString::fromUtf16(ptr, 1));
        }
    }

    if (accumulated.indexOf(QStringLiteral("w")) != -1
            || accumulated.indexOf(QStringLiteral("x")) != -1
            || accumulated.indexOf(QStringLiteral("y")) != -1) {
        qDebug() << accumulated;
        qFatal("oops!  we expected only z!");
    }

    qDebug() << "accumulated is fine.";
    return 0;
}

I think it's basically that storing the pointer returned by
QString::utf16() is invalid in this case, because utf16() reallocs in the
IS_RAW_DATA case, and thus is detached from the lifetime of the original
string data.
I would be inclined to call it a bug in the QtSqlite plugin, as the utf16()
docs do say that the returned value is only valid so long as the string is
not modified (and in this case, it is destroyed).
I suppose there are several possible solutions: either make the "copy"
variant just a reference, or require sqlite to copy the buffer by
specifying SQLITE_TRANSIENT, etc.

Nice catch, Alberto!

Best regards,
Chris.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.qt-project.org/pipermail/development/attachments/20210527/3d1422d9/attachment.html>


More information about the Development mailing list