From a63e652d38993865fe39ecd3612e94b28086c38c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20S=C3=B8rvig?= Date: Fri, 24 Jun 2022 13:10:33 +0200 Subject: [PATCH] wasm: don't access deleted settings objects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The emscripten_idb_async_ functions are async, so there is no guarantee that the QSettings object which made the request will be live by the time the completion callback is made. Keep track of live QWasmSettingsPrivate objects, return early from the callbacks if userData does not point to a valid QWasmSettingsPrivate. Change-Id: Ia319b1875dcf2c329ba27954e3f026e004fe0aac Reviewed-by: Morten Johan Sørvig Reviewed-by: Lorn Potter (cherry picked from commit 25c2d05340eee01cf55457b8327f8f69d408879a) Reviewed-by: Qt Cherry-pick Bot --- src/corelib/io/qsettings_wasm.cpp | 43 +++++++++++++++++++++---------- 1 file changed, 29 insertions(+), 14 deletions(-) diff --git a/src/corelib/io/qsettings_wasm.cpp b/src/corelib/io/qsettings_wasm.cpp index ba081997fda..5c15e6d89b6 100644 --- a/src/corelib/io/qsettings_wasm.cpp +++ b/src/corelib/io/qsettings_wasm.cpp @@ -13,6 +13,8 @@ #include #include +#include + #include QT_BEGIN_NAMESPACE @@ -27,6 +29,7 @@ public: QWasmSettingsPrivate(QSettings::Scope scope, const QString &organization, const QString &application); ~QWasmSettingsPrivate(); + static QWasmSettingsPrivate *get(void *userData); std::optional get(const QString &key) const override; QStringList children(const QString &prefix, ChildSpec spec) const override; @@ -43,14 +46,19 @@ public: private: QString databaseName; QString id; + static QList liveSettings; }; +QList QWasmSettingsPrivate::liveSettings; + static void QWasmSettingsPrivate_onLoad(void *userData, void *dataPtr, int size) { - QWasmSettingsPrivate *wasm = reinterpret_cast(userData); + QWasmSettingsPrivate *settings = QWasmSettingsPrivate::get(userData); + if (!settings) + return; - QFile file(wasm->fileName()); - QFileInfo fileInfo(wasm->fileName()); + QFile file(settings->fileName()); + QFileInfo fileInfo(settings->fileName()); QDir dir(fileInfo.path()); if (!dir.exists()) dir.mkpath(fileInfo.path()); @@ -58,32 +66,29 @@ static void QWasmSettingsPrivate_onLoad(void *userData, void *dataPtr, int size) if (file.open(QFile::WriteOnly)) { file.write(reinterpret_cast(dataPtr), size); file.close(); - wasm->setReady(); + settings->setReady(); } } static void QWasmSettingsPrivate_onError(void *userData) { - QWasmSettingsPrivate *wasm = reinterpret_cast(userData); - if (wasm) - wasm->setStatus(QSettings::AccessError); + if (QWasmSettingsPrivate *settings = QWasmSettingsPrivate::get(userData)) + settings->setStatus(QSettings::AccessError); } static void QWasmSettingsPrivate_onStore(void *userData) { - QWasmSettingsPrivate *wasm = reinterpret_cast(userData); - if (wasm) - wasm->setStatus(QSettings::NoError); + if (QWasmSettingsPrivate *settings = QWasmSettingsPrivate::get(userData)) + settings->setStatus(QSettings::NoError); } static void QWasmSettingsPrivate_onCheck(void *userData, int exists) { - QWasmSettingsPrivate *wasm = reinterpret_cast(userData); - if (wasm) { + if (QWasmSettingsPrivate *settings = QWasmSettingsPrivate::get(userData)) { if (exists) - wasm->loadLocal(wasm->fileName().toLocal8Bit()); + settings->loadLocal(settings->fileName().toLocal8Bit()); else - wasm->setReady(); + settings->setReady(); } } @@ -114,6 +119,8 @@ QWasmSettingsPrivate::QWasmSettingsPrivate(QSettings::Scope scope, const QString const QString &application) : QConfFileSettingsPrivate(QSettings::NativeFormat, scope, organization, application) { + liveSettings.push_back(this); + setStatus(QSettings::AccessError); // access error until sandbox gets loaded databaseName = organization; id = application; @@ -127,6 +134,14 @@ QWasmSettingsPrivate::QWasmSettingsPrivate(QSettings::Scope scope, const QString QWasmSettingsPrivate::~QWasmSettingsPrivate() { + liveSettings.removeAll(this); +} + +QWasmSettingsPrivate *QWasmSettingsPrivate::get(void *userData) +{ + if (QWasmSettingsPrivate::liveSettings.contains(userData)) + return reinterpret_cast(userData); + return nullptr; } void QWasmSettingsPrivate::initAccess()