QVariant: don't use the static CanUseInternalSpace with existing objects
It's possible for the QVariant to have been created by an older or newer build of the library in question in which the type in question was relocatable but has ceased to be, or wasn't relocatable but now is. [ChangeLog][QtCore][QVariant] Fixed a bug where QVariant could misbehave regarding types that changed from non-relocatable to relocatable (or vice-versa) and not all uses of it were recompiled. To benefit from this fix, applications must be recompiled, but they will be safe going forward. Change-Id: I222806b3804df6272abdfffd45f96312d23be1af Reviewed-by: Marc Mutz <marc.mutz@qt.io> Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io> (cherry picked from commit eb87b0444ac8fec4d86bc26dc4bec80f82953f7c) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> (cherry picked from commit c1bb08ab269a2e0e734f9ffe70149e1b480a95e5)bb10
parent
4a97fd2f8e
commit
9760d84262
|
|
@ -305,11 +305,18 @@ static QVariant::Private clonePrivate(const QVariant::Private &other)
|
|||
if (d.is_shared) {
|
||||
d.data.shared->ref.ref();
|
||||
} else if (const QtPrivate::QMetaTypeInterface *iface = d.typeInterface()) {
|
||||
Q_ASSERT(d.canUseInternalSpace(iface));
|
||||
if (Q_LIKELY(d.canUseInternalSpace(iface))) {
|
||||
// if not trivially copyable, ask to copy (if it's trivially
|
||||
// copyable, we've already copied it)
|
||||
if (iface->copyCtr)
|
||||
QtMetaTypePrivate::copyConstruct(iface, d.data.data, other.data.data);
|
||||
} else {
|
||||
// highly unlikely, but possible case: type has changed relocatability
|
||||
// between builds
|
||||
d.data.shared = QVariant::PrivateShared::create(iface->size, iface->alignment);
|
||||
QtMetaTypePrivate::copyConstruct(iface, d.data.shared->data(), other.data.data);
|
||||
}
|
||||
|
||||
// if not trivially copyable, ask to copy
|
||||
if (iface->copyCtr)
|
||||
QtMetaTypePrivate::copyConstruct(iface, d.data.data, other.data.data);
|
||||
}
|
||||
return d;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -124,9 +124,8 @@ public:
|
|||
const void *storage() const
|
||||
{ return is_shared ? data.shared->data() : &data.data; }
|
||||
|
||||
// determine internal storage at compile time
|
||||
template<typename T> const T &get() const
|
||||
{ return *static_cast<const T *>(CanUseInternalSpace<T> ? &data.data : data.shared->data()); }
|
||||
{ return *static_cast<const T *>(storage()); }
|
||||
|
||||
inline const QtPrivate::QMetaTypeInterface *typeInterface() const
|
||||
{
|
||||
|
|
@ -771,7 +770,7 @@ template<typename T> inline T qvariant_cast(QVariant &&v)
|
|||
{
|
||||
QMetaType targetType = QMetaType::fromType<T>();
|
||||
if (v.d.type() == targetType) {
|
||||
if constexpr (QVariant::Private::CanUseInternalSpace<T>) {
|
||||
if (!v.d.is_shared) {
|
||||
return std::move(*reinterpret_cast<T *>(v.d.data.data));
|
||||
} else {
|
||||
if (v.d.data.shared->ref.loadRelaxed() == 1)
|
||||
|
|
|
|||
Loading…
Reference in New Issue