From 0c1b304917c01d4051008a68a1190eac2e9d46d0 Mon Sep 17 00:00:00 2001 From: baldurk Date: Fri, 28 Aug 2020 11:59:16 +0100 Subject: [PATCH] Verify JSON documents being saved don't contain byte arrays * Newer Qt versions will base64 the byte arrays even if we've already base64'd them so they're safe. To prevent this we explicitly convert to QString afterwards. --- qrenderdoc/Code/QRDUtils.cpp | 42 +++++++++++++++++++++++++++++-- qrenderdoc/Windows/MainWindow.cpp | 2 +- 2 files changed, 41 insertions(+), 3 deletions(-) diff --git a/qrenderdoc/Code/QRDUtils.cpp b/qrenderdoc/Code/QRDUtils.cpp index be2b66c82..9b359fa25 100644 --- a/qrenderdoc/Code/QRDUtils.cpp +++ b/qrenderdoc/Code/QRDUtils.cpp @@ -1397,13 +1397,51 @@ void addStructuredObjects(RDTreeWidgetItem *parent, const StructuredObjectList & } } +static void validateForJSON(const QVariant &data, QString path = QString()) +{ + switch((QMetaType::Type)data.type()) + { + case QMetaType::QVariantList: + { + QVariantList list = data.toList(); + int i = 0; + for(QVariant &v : list) + validateForJSON(v, path + QFormatStr("[%1]").arg(i++)); + break; + } + case QMetaType::QVariantMap: + { + QVariantMap map = data.toMap(); + for(const QString &str : map.keys()) + validateForJSON(map[str], path + lit(".") + str); + break; + } + case QMetaType::QByteArray: + { + qCritical() << "Qt can't reliably serialise QByteArray to JSON.\n" + << "Older versions write it as a byte string, new versions base64 encode it.\n" + << "Manually encode if needed and add value as string." << path; + } + default: + // all other types we assume are fine + break; + } +} + +static QJsonDocument validateAndMakeJSON(const QVariantMap &data) +{ + validateForJSON(data); + + return QJsonDocument::fromVariant(data); +} + bool SaveToJSON(QVariantMap &data, QIODevice &f, const char *magicIdentifier, uint32_t magicVersion) { // marker that this data is valid if(magicIdentifier) data[QString::fromLatin1(magicIdentifier)] = magicVersion; - QJsonDocument doc = QJsonDocument::fromVariant(data); + QJsonDocument doc = validateAndMakeJSON(data); if(doc.isEmpty() || doc.isNull()) { @@ -1463,7 +1501,7 @@ bool LoadFromJSON(QVariantMap &data, QIODevice &f, const char *magicIdentifier, QString VariantToJSON(const QVariantMap &data) { - return QString::fromUtf8(QJsonDocument::fromVariant(data).toJson(QJsonDocument::Indented)); + return QString::fromUtf8(validateAndMakeJSON(data).toJson(QJsonDocument::Indented)); } QVariantMap JSONToVariant(const QString &json) diff --git a/qrenderdoc/Windows/MainWindow.cpp b/qrenderdoc/Windows/MainWindow.cpp index 81aead6a2..2c263e0cc 100644 --- a/qrenderdoc/Windows/MainWindow.cpp +++ b/qrenderdoc/Windows/MainWindow.cpp @@ -2952,7 +2952,7 @@ QVariantMap MainWindow::saveState() { QVariantMap state = ui->toolWindowManager->saveState(); - state[lit("mainWindowGeometry")] = saveGeometry().toBase64(); + state[lit("mainWindowGeometry")] = QString::fromLatin1(saveGeometry().toBase64()); return state; }