From 30a0787907981da3811390735bf234068fc89944 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 5 Mar 2020 15:31:38 -0800 Subject: [PATCH] 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 --- src/corelib/serialization/qjsonarray.cpp | 7 +++++-- src/corelib/serialization/qjsonobject.cpp | 7 +++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/corelib/serialization/qjsonarray.cpp b/src/corelib/serialization/qjsonarray.cpp index 08702771a8..05138ad610 100644 --- a/src/corelib/serialization/qjsonarray.cpp +++ b/src/corelib/serialization/qjsonarray.cpp @@ -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 args) { - initialize(); for (const auto & arg : args) append(arg); } diff --git a/src/corelib/serialization/qjsonobject.cpp b/src/corelib/serialization/qjsonobject.cpp index aceb465920..b76e50e2d2 100644 --- a/src/corelib/serialization/qjsonobject.cpp +++ b/src/corelib/serialization/qjsonobject.cpp @@ -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 > args) { - initialize(); for (const auto &arg : args) insert(arg.first, arg.second); }