Preserve installed card databases when Oracle refresh fails (#7739)
Some checks are pending
CodeQL / Analyze (cpp) (push) Waiting to run
CodeQL / Analyze (actions) (push) Waiting to run
Build Desktop / Configure (push) Waiting to run
Build Desktop / vcpkg baseline (push) Waiting to run
Build Desktop / Servatrice_Debian 12 (push) Blocked by required conditions
Build Desktop / Ubuntu 26.04 sanitize (push) Blocked by required conditions
Build Desktop / Debian 13 (push) Blocked by required conditions
Build Desktop / Fedora 44 (push) Blocked by required conditions
Build Desktop / Ubuntu 26.04 (push) Blocked by required conditions
Build Desktop / Arch (push) Blocked by required conditions
Build Desktop / Debian 12 (push) Blocked by required conditions
Build Desktop / Fedora 43 (push) Blocked by required conditions
Build Desktop / Ubuntu 24.04 (push) Blocked by required conditions
Build Desktop / Ubuntu 26.04 cover (push) Blocked by required conditions
Build Desktop / macOS 14 (push) Blocked by required conditions
Build Desktop / macOS 15 (push) Blocked by required conditions
Build Desktop / macOS 27 Debug (push) Blocked by required conditions
Build Desktop / Windows 10 (push) Blocked by required conditions
Build Desktop / macOS 13 Intel (push) Blocked by required conditions
Build Desktop / Prune caches (push) Waiting to run
Build Docker / Servatrice (arm) (push) Waiting to run
Build Docker / Servatrice (x86) (push) Waiting to run
Build Docker / Publish multi-platform Servatrice image (push) Blocked by required conditions

* Preserve installed card databases when Oracle refresh fails

* Fix the Oracle refresh verdict and cover the parser write path

A background refresh that already installed cards.xml exited 1 when the
token save afterwards failed, so the client kept its old in-memory
database and reported the update as failed. Return the same verdict
main() already computes: a reject after the database was written is a
successful update.

Cover the writer Oracle actually uses: add a short-write death test for
CockatriceXml4Parser::saveToFile, which reverted to QFile would truncate
an installed database without any test noticing.

Route a failed background token download through reject() instead of a
modal box on a hidden wizard, which left the client waiting with no
timeout and blocked later updates. Test the first non-space byte in
place rather than copying the payload, and report an import refusal with
the importer's own message.

---------

Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
This commit is contained in:
Bryce! 2026-11-04 11:33:49 -05:00 • committed by GitHub
parent e558c0dffa
commit 3a656c9c4a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
14 changed files with 517 additions and 72 deletions

View file

@ -1,6 +1,7 @@
#include "oraclewizard.h"
#include "client/settings/cache_settings.h"
#include "database_writer.h"
#include "main.h"
#include "oracleimporter.h"
#include "pages.h"
@ -141,6 +142,13 @@ void OracleWizard::reject()
}
QWizard::reject();
// A hidden wizard does not close the application's last visible window.
// Stop background refreshes explicitly so the hosting client receives a verdict,
// using the same rule as main(): a reject after the database was written is still
// a successful update, only a reject that wrote nothing counts as a failure.
if (backgroundMode) {
QCoreApplication::exit(hasSavedDatabase() ? 0 : 1);
}
}
void OracleWizard::runInBackground()
@ -212,17 +220,10 @@ void OracleWizard::disableButtons()
bool OracleWizard::saveTokensToFile(const QString &fileName)
{
QFile file(fileName);
if (!file.open(QIODevice::WriteOnly)) {
qDebug() << "File open (w) failed for" << fileName;
QString error;
if (!OracleDatabase::saveXml(fileName, tokensData, &error)) {
qWarning() << error;
return false;
}
if (file.write(tokensData) == -1) {
qDebug() << "File write (w) failed for" << fileName;
return false;
}
file.close();
return true;
}