fix use-afrer-free crash caused by QtConcurrent

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
This commit is contained in:
Trial97
2025-12-09 23:31:01 +02:00
parent 808b09c403
commit 9cd199a49e
5 changed files with 42 additions and 43 deletions
-1
View File
@@ -121,7 +121,6 @@ QString cleanPath(QString path)
void InstanceImportTask::processZipPack() void InstanceImportTask::processZipPack()
{ {
setStatus(tr("Attempting to determine instance type")); setStatus(tr("Attempting to determine instance type"));
setDetails("");
QDir extractDir(m_stagingPath); QDir extractDir(m_stagingPath);
qDebug() << "Attempting to create instance from" << m_archivePath; qDebug() << "Attempting to create instance from" << m_archivePath;
+15 -15
View File
@@ -26,9 +26,9 @@ void ExportToZipTask::executeTask()
{ {
setStatus("Adding files..."); setStatus("Adding files...");
setProgress(0, m_files.length()); setProgress(0, m_files.length());
m_build_zip_future = QtConcurrent::run(QThreadPool::globalInstance(), [this]() { return exportZip(); }); m_buildZipFuture = QtConcurrent::run(QThreadPool::globalInstance(), [this]() { return exportZip(); });
connect(&m_build_zip_watcher, &QFutureWatcher<ZipResult>::finished, this, &ExportToZipTask::finish); connect(&m_buildZipWatcher, &QFutureWatcher<ZipResult>::finished, this, &ExportToZipTask::finish);
m_build_zip_watcher.setFuture(m_build_zip_future); m_buildZipWatcher.setFuture(m_buildZipFuture);
} }
auto ExportToZipTask::exportZip() -> ZipResult auto ExportToZipTask::exportZip() -> ZipResult
@@ -40,30 +40,30 @@ auto ExportToZipTask::exportZip() -> ZipResult
return ZipResult(tr("Could not create file")); return ZipResult(tr("Could not create file"));
} }
for (auto fileName : m_extra_files.keys()) { for (auto fileName : m_extraFiles.keys()) {
if (m_build_zip_future.isCanceled()) if (m_buildZipFuture.isCanceled())
return ZipResult(); return ZipResult();
if (!m_output.addFile(fileName, m_extra_files[fileName])) { if (!m_output.addFile(fileName, m_extraFiles[fileName])) {
return ZipResult(tr("Could not add:") + fileName); return ZipResult(tr("Could not add:") + fileName);
} }
} }
for (const QFileInfo& file : m_files) { for (const QFileInfo& file : m_files) {
if (m_build_zip_future.isCanceled()) if (m_buildZipFuture.isCanceled())
return ZipResult(); return ZipResult();
auto absolute = file.absoluteFilePath(); auto absolute = file.absoluteFilePath();
auto relative = m_dir.relativeFilePath(absolute); auto relative = m_dir.relativeFilePath(absolute);
setStatus("Compressing: " + relative); setStatus("Compressing: " + relative);
setProgress(m_progress + 1, m_progressTotal); setProgress(m_progress + 1, m_progressTotal);
if (m_follow_symlinks) { if (m_followSymlinks) {
if (file.isSymLink()) if (file.isSymLink())
absolute = file.symLinkTarget(); absolute = file.symLinkTarget();
else else
absolute = file.canonicalFilePath(); absolute = file.canonicalFilePath();
} }
if (!m_exclude_files.contains(relative) && !m_output.addFile(absolute, m_destination_prefix + relative)) { if (!m_excludeFiles.contains(relative) && !m_output.addFile(absolute, m_destinationPrefix + relative)) {
return ZipResult(tr("Could not read and compress %1").arg(relative)); return ZipResult(tr("Could not read and compress %1").arg(relative));
} }
} }
@@ -76,11 +76,11 @@ auto ExportToZipTask::exportZip() -> ZipResult
void ExportToZipTask::finish() void ExportToZipTask::finish()
{ {
if (m_build_zip_future.isCanceled()) { if (m_buildZipFuture.isCanceled()) {
FS::deletePath(m_output_path); FS::deletePath(m_outputPath);
emitAborted(); emitAborted();
} else if (auto result = m_build_zip_future.result(); result.has_value()) { } else if (auto result = m_buildZipFuture.result(); result.has_value()) {
FS::deletePath(m_output_path); FS::deletePath(m_outputPath);
emitFailed(result.value()); emitFailed(result.value());
} else { } else {
emitSucceeded(); emitSucceeded();
@@ -89,8 +89,8 @@ void ExportToZipTask::finish()
bool ExportToZipTask::abort() bool ExportToZipTask::abort()
{ {
if (m_build_zip_future.isRunning()) { if (m_buildZipFuture.isRunning()) {
m_build_zip_future.cancel(); m_buildZipFuture.cancel();
// NOTE: Here we don't do `emitAborted()` because it will be done when `m_build_zip_future` actually cancels, which may not occur // NOTE: Here we don't do `emitAborted()` because it will be done when `m_build_zip_future` actually cancels, which may not occur
// immediately. // immediately.
return true; return true;
+12 -12
View File
@@ -30,12 +30,12 @@ class ExportToZipTask : public Task {
Q_OBJECT Q_OBJECT
public: public:
ExportToZipTask(QString outputPath, QDir dir, QFileInfoList files, QString destinationPrefix = "", bool followSymlinks = false) ExportToZipTask(QString outputPath, QDir dir, QFileInfoList files, QString destinationPrefix = "", bool followSymlinks = false)
: m_output_path(outputPath) : m_outputPath(outputPath)
, m_output(outputPath) , m_output(outputPath)
, m_dir(dir) , m_dir(dir)
, m_files(files) , m_files(files)
, m_destination_prefix(destinationPrefix) , m_destinationPrefix(destinationPrefix)
, m_follow_symlinks(followSymlinks) , m_followSymlinks(followSymlinks)
{ {
setAbortable(true); setAbortable(true);
}; };
@@ -44,8 +44,8 @@ class ExportToZipTask : public Task {
virtual ~ExportToZipTask() = default; virtual ~ExportToZipTask() = default;
void setExcludeFiles(QStringList excludeFiles) { m_exclude_files = excludeFiles; } void setExcludeFiles(QStringList excludeFiles) { m_excludeFiles = excludeFiles; }
void addExtraFile(QString fileName, QByteArray data) { m_extra_files.insert(fileName, data); } void addExtraFile(QString fileName, QByteArray data) { m_extraFiles.insert(fileName, data); }
using ZipResult = std::optional<QString>; using ZipResult = std::optional<QString>;
@@ -57,16 +57,16 @@ class ExportToZipTask : public Task {
void finish(); void finish();
private: private:
QString m_output_path; QString m_outputPath;
ArchiveWriter m_output; ArchiveWriter m_output;
QDir m_dir; QDir m_dir;
QFileInfoList m_files; QFileInfoList m_files;
QString m_destination_prefix; QString m_destinationPrefix;
bool m_follow_symlinks; bool m_followSymlinks;
QStringList m_exclude_files; QStringList m_excludeFiles;
QHash<QString, QByteArray> m_extra_files; QHash<QString, QByteArray> m_extraFiles;
QFuture<ZipResult> m_build_zip_future; QFuture<ZipResult> m_buildZipFuture;
QFutureWatcher<ZipResult> m_build_zip_watcher; QFutureWatcher<ZipResult> m_buildZipWatcher;
}; };
} // namespace MMCZip } // namespace MMCZip
+11 -11
View File
@@ -25,14 +25,14 @@ namespace MMCZip {
void ExtractZipTask::executeTask() void ExtractZipTask::executeTask()
{ {
m_zip_future = QtConcurrent::run(QThreadPool::globalInstance(), [this]() { return extractZip(); }); m_zipFuture = QtConcurrent::run(QThreadPool::globalInstance(), [this]() { return extractZip(); });
connect(&m_zip_watcher, &QFutureWatcher<ZipResult>::finished, this, &ExtractZipTask::finish); connect(&m_zipWatcher, &QFutureWatcher<ZipResult>::finished, this, &ExtractZipTask::finish);
m_zip_watcher.setFuture(m_zip_future); m_zipWatcher.setFuture(m_zipFuture);
} }
auto ExtractZipTask::extractZip() -> ZipResult auto ExtractZipTask::extractZip() -> ZipResult
{ {
auto target = m_output_dir.absolutePath(); auto target = m_outputDir.absolutePath();
auto target_top_dir = QUrl::fromLocalFile(target); auto target_top_dir = QUrl::fromLocalFile(target);
QStringList extracted; QStringList extracted;
@@ -52,8 +52,9 @@ auto ExtractZipTask::extractZip() -> ZipResult
setStatus("Extracting files..."); setStatus("Extracting files...");
setProgress(0, m_input.getFiles().count()); setProgress(0, m_input.getFiles().count());
ZipResult result; ZipResult result;
auto fileName = m_input.getZipName();
if (!m_input.parse([this, &result, &target, &target_top_dir, ext, &extracted](ArchiveReader::File* f) { if (!m_input.parse([this, &result, &target, &target_top_dir, ext, &extracted](ArchiveReader::File* f) {
if (m_zip_future.isCanceled()) if (m_zipFuture.isCanceled())
return false; return false;
setProgress(m_progress + 1, m_progressTotal); setProgress(m_progress + 1, m_progressTotal);
QString file_name = f->filename(); QString file_name = f->filename();
@@ -104,17 +105,16 @@ auto ExtractZipTask::extractZip() -> ZipResult
return true; return true;
})) { })) {
FS::removeFiles(extracted); FS::removeFiles(extracted);
return result.has_value() || m_zip_future.isCanceled() ? result return result.has_value() ? result : ZipResult(tr("Failed to parse file %1").arg(fileName));
: ZipResult(tr("Failed to parse file %1").arg(m_input.getZipName()));
} }
return ZipResult(); return ZipResult();
} }
void ExtractZipTask::finish() void ExtractZipTask::finish()
{ {
if (m_zip_future.isCanceled()) { if (m_zipFuture.isCanceled()) {
emitAborted(); emitAborted();
} else if (auto result = m_zip_future.result(); result.has_value()) { } else if (auto result = m_zipFuture.result(); result.has_value()) {
emitFailed(result.value()); emitFailed(result.value());
} else { } else {
emitSucceeded(); emitSucceeded();
@@ -123,8 +123,8 @@ void ExtractZipTask::finish()
bool ExtractZipTask::abort() bool ExtractZipTask::abort()
{ {
if (m_zip_future.isRunning()) { if (m_zipFuture.isRunning()) {
m_zip_future.cancel(); m_zipFuture.cancel();
// NOTE: Here we don't do `emitAborted()` because it will be done when `m_build_zip_future` actually cancels, which may not occur // NOTE: Here we don't do `emitAborted()` because it will be done when `m_build_zip_future` actually cancels, which may not occur
// immediately. // immediately.
return true; return true;
+4 -4
View File
@@ -29,7 +29,7 @@ class ExtractZipTask : public Task {
Q_OBJECT Q_OBJECT
public: public:
ExtractZipTask(QString input, QDir outputDir, QString subdirectory = "") ExtractZipTask(QString input, QDir outputDir, QString subdirectory = "")
: m_input(input), m_output_dir(outputDir), m_subdirectory(subdirectory) : m_input(input), m_outputDir(outputDir), m_subdirectory(subdirectory)
{} {}
virtual ~ExtractZipTask() = default; virtual ~ExtractZipTask() = default;
@@ -44,10 +44,10 @@ class ExtractZipTask : public Task {
private: private:
ArchiveReader m_input; ArchiveReader m_input;
QDir m_output_dir; QDir m_outputDir;
QString m_subdirectory; QString m_subdirectory;
QFuture<ZipResult> m_zip_future; QFuture<ZipResult> m_zipFuture;
QFutureWatcher<ZipResult> m_zip_watcher; QFutureWatcher<ZipResult> m_zipWatcher;
}; };
} // namespace MMCZip } // namespace MMCZip