From 85a9009f258e130a7bd4aaaa252724ea5fb58e79 Mon Sep 17 00:00:00 2001 From: Albert Astals Cid Date: Fri, 15 Mar 2019 11:01:31 +0100 Subject: [PATCH] QPixmap: More safe failing if qApp is not a QGuiApplication It can happen that QDataStream is fed a QVariant that contains a QPixmap representation, that will make the application crash when trying to restore it This is specially important for cases in which applications expose dbus interfaces with QVariantMaps Change-Id: Ife4feaef30f30e7e27d88464bd6b2a247f743123 Reported-by: Fabian Vogt Reviewed-by: Fabian Vogt Reviewed-by: Mitch Curtis Reviewed-by: Thiago Macieira --- src/gui/image/qpixmap.cpp | 15 ++++ .../qdatastream_core_pixmap.pro | 4 ++ .../tst_qdatastream_core_pixmap.cpp | 68 +++++++++++++++++++ .../corelib/serialization/serialization.pro | 1 + 4 files changed, 88 insertions(+) create mode 100644 tests/auto/corelib/serialization/qdatastream_core_pixmap/qdatastream_core_pixmap.pro create mode 100644 tests/auto/corelib/serialization/qdatastream_core_pixmap/tst_qdatastream_core_pixmap.cpp diff --git a/src/gui/image/qpixmap.cpp b/src/gui/image/qpixmap.cpp index ea6697cc394..7e862e98262 100644 --- a/src/gui/image/qpixmap.cpp +++ b/src/gui/image/qpixmap.cpp @@ -1543,6 +1543,11 @@ QPixmap QPixmap::fromImage(const QImage &image, Qt::ImageConversionFlags flags) if (image.isNull()) return QPixmap(); + if (Q_UNLIKELY(!qobject_cast(QCoreApplication::instance()))) { + qWarning("QPixmap::fromImage: QPixmap cannot be created without a QGuiApplication"); + return QPixmap(); + } + QScopedPointer data(QGuiApplicationPrivate::platformIntegration()->createPlatformPixmap(QPlatformPixmap::PixmapType)); data->fromImage(image, flags); return QPixmap(data.take()); @@ -1565,6 +1570,11 @@ QPixmap QPixmap::fromImageInPlace(QImage &image, Qt::ImageConversionFlags flags) if (image.isNull()) return QPixmap(); + if (Q_UNLIKELY(!qobject_cast(QCoreApplication::instance()))) { + qWarning("QPixmap::fromImageInPlace: QPixmap cannot be created without a QGuiApplication"); + return QPixmap(); + } + QScopedPointer data(QGuiApplicationPrivate::platformIntegration()->createPlatformPixmap(QPlatformPixmap::PixmapType)); data->fromImageInPlace(image, flags); return QPixmap(data.take()); @@ -1584,6 +1594,11 @@ QPixmap QPixmap::fromImageInPlace(QImage &image, Qt::ImageConversionFlags flags) */ QPixmap QPixmap::fromImageReader(QImageReader *imageReader, Qt::ImageConversionFlags flags) { + if (Q_UNLIKELY(!qobject_cast(QCoreApplication::instance()))) { + qWarning("QPixmap::fromImageReader: QPixmap cannot be created without a QGuiApplication"); + return QPixmap(); + } + QScopedPointer data(QGuiApplicationPrivate::platformIntegration()->createPlatformPixmap(QPlatformPixmap::PixmapType)); data->fromImageReader(imageReader, flags); return QPixmap(data.take()); diff --git a/tests/auto/corelib/serialization/qdatastream_core_pixmap/qdatastream_core_pixmap.pro b/tests/auto/corelib/serialization/qdatastream_core_pixmap/qdatastream_core_pixmap.pro new file mode 100644 index 00000000000..7e003304afd --- /dev/null +++ b/tests/auto/corelib/serialization/qdatastream_core_pixmap/qdatastream_core_pixmap.pro @@ -0,0 +1,4 @@ +CONFIG += testcase +TARGET = tst_qdatastream_core_pixmap +QT += testlib +SOURCES = tst_qdatastream_core_pixmap.cpp diff --git a/tests/auto/corelib/serialization/qdatastream_core_pixmap/tst_qdatastream_core_pixmap.cpp b/tests/auto/corelib/serialization/qdatastream_core_pixmap/tst_qdatastream_core_pixmap.cpp new file mode 100644 index 00000000000..c931016a615 --- /dev/null +++ b/tests/auto/corelib/serialization/qdatastream_core_pixmap/tst_qdatastream_core_pixmap.cpp @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include + +class tst_QDataStream : public QObject +{ +Q_OBJECT + +private slots: + void stream_with_pixmap(); + +}; + +void tst_QDataStream::stream_with_pixmap() +{ + // This is a QVariantMap with a 3x3 red QPixmap and two strings inside + const QByteArray ba = QByteArray::fromBase64("AAAAAwAAAAIAegAAAAoAAAAACgB0AGgAZQByAGUAAAACAHAAAABBAAAAAAGJUE5HDQoaCgAAAA1JSERSAAAAAwAAAAMIAgAAANlKIugAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAAQSURBVAiZY/zPAAVMDJgsAB1bAQXZn5ieAAAAAElFTkSuQmCCAAAAAgBhAAAACgAAAAAKAGgAZQBsAGwAbw=="); + QImage dummy; // Needed to make sure qtGui is loaded + + QTest::ignoreMessage(QtWarningMsg, "QPixmap::fromImageInPlace: QPixmap cannot be created without a QGuiApplication"); + + QVariantMap map; + QDataStream d(ba); + d.setVersion(QDataStream::Qt_5_12); + d >> map; + + QCOMPARE(map["a"].toString(), QString("hello")); + QCOMPARE(map["p"].value(), QPixmap()); // the pixmap is null because this is not a QGuiApplication + QCOMPARE(map["z"].toString(), QString("there")); +} + +QTEST_GUILESS_MAIN(tst_QDataStream) + +#include "tst_qdatastream_core_pixmap.moc" + diff --git a/tests/auto/corelib/serialization/serialization.pro b/tests/auto/corelib/serialization/serialization.pro index 9187de1bc5c..9638178cdc3 100644 --- a/tests/auto/corelib/serialization/serialization.pro +++ b/tests/auto/corelib/serialization/serialization.pro @@ -6,6 +6,7 @@ SUBDIRS = \ qcborvalue \ qcborvalue_json \ qdatastream \ + qdatastream_core_pixmap \ qtextstream \ qxmlstream