Fix binary compatibility issue in QJson{Array,Object} initializer_list

The rewrite using CBOR internals replaced one of the two naked pointers
that were members of QJsonArray and QJsonObject with a
QExplicitlySharedDataPointer. The problem is that its operator= will
read the current value to decrement the refcount and possibly delete the
pointed object.

But QJson{Array,Object}::initialize() are called from inlined code,
without initialization. So we can't call operator=. We need to memcpy to
write a nullptr.

This is not unit-testable because it requires compiling against 5.14 or
earlier, then running against 5.15.

Fixes: QTBUG-82700
Change-Id: Iaa63461109844e978376fffd15f98c62656d197c
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
This commit is contained in:
Thiago Macieira 2020-03-05 15:31:38 -08:00
parent c798b286bd
commit 30a0787907
2 changed files with 10 additions and 4 deletions

View File

@ -167,7 +167,11 @@ QJsonArray::QJsonArray(QCborContainerPrivate *array)
*/
void QJsonArray::initialize()
{
a = nullptr;
// Because we're being called with uninitialized state, we can't do:
// a = nullptr;
// QExplicitlyDataSharedPointer::operator= will read the current value
void *ptr = &a;
memset(ptr, 0, sizeof(a));
}
/*!
@ -177,7 +181,6 @@ QJsonArray::~QJsonArray() = default;
QJsonArray::QJsonArray(std::initializer_list<QJsonValue> args)
{
initialize();
for (const auto & arg : args)
append(arg);
}

View File

@ -150,7 +150,11 @@ QJsonObject::QJsonObject(QCborContainerPrivate *object)
void QJsonObject::initialize()
{
o = nullptr;
// Because we're being called with uninitialized state, we can't do:
// o = nullptr;
// QExplicitlyDataSharedPointer::operator= will read the current value
void *ptr = &o;
memset(ptr, 0, sizeof(o));
}
/*!
@ -160,7 +164,6 @@ QJsonObject::~QJsonObject() = default;
QJsonObject::QJsonObject(std::initializer_list<QPair<QString, QJsonValue> > args)
{
initialize();
for (const auto &arg : args)
insert(arg.first, arg.second);
}