diff --git a/kde-apps/akonadi/akonadi-25.08.3-r1.ebuild b/kde-apps/akonadi/akonadi-25.08.3-r1.ebuild new file mode 100644 index 000000000000..a38341cbcfe7 --- /dev/null +++ b/kde-apps/akonadi/akonadi-25.08.3-r1.ebuild @@ -0,0 +1,68 @@ +# Copyright 1999-2025 Gentoo Authors +# Distributed under the terms of the GNU General Public License v2 + +EAPI=8 + +ECM_DESIGNERPLUGIN="true" +ECM_QTHELP="true" +ECM_TEST="forceoptional" +KFMIN=6.16.0 +QTMIN=6.9.1 +VIRTUALDBUS_TEST="true" +inherit ecm gear.kde.org xdg + +DESCRIPTION="Storage service for PIM data and libraries for PIM apps" +HOMEPAGE="https://community.kde.org/KDE_PIM/akonadi" + +LICENSE="LGPL-2.1+" +SLOT="6/$(ver_cut 1-2)" +KEYWORDS="~amd64 ~arm64" +IUSE="tools +webengine xml" + +REQUIRED_USE="test? ( tools )" + +# some akonadi tests time out, that probably needs more work as it's ~700 tests +RESTRICT="test" + +COMMON_DEPEND=" + app-arch/xz-utils + >=dev-qt/qtbase-${QTMIN}:6[dbus,gui,network,sql,widgets,xml] + >=dev-qt/qtdeclarative-${QTMIN}:6 + >=kde-frameworks/kcolorscheme-${KFMIN}:6 + >=kde-frameworks/kconfig-${KFMIN}:6 + >=kde-frameworks/kconfigwidgets-${KFMIN}:6 + >=kde-frameworks/kcoreaddons-${KFMIN}:6 + >=kde-frameworks/kcrash-${KFMIN}:6 + >=kde-frameworks/ki18n-${KFMIN}:6 + >=kde-frameworks/kiconthemes-${KFMIN}:6 + >=kde-frameworks/kitemmodels-${KFMIN}:6 + >=kde-frameworks/kwidgetsaddons-${KFMIN}:6 + >=kde-frameworks/kwindowsystem-${KFMIN}:6 + >=kde-frameworks/kxmlgui-${KFMIN}:6 + webengine? ( + kde-apps/kaccounts-integration:6 + >=net-libs/accounts-qt-1.17[qt6(+)] + ) + xml? ( dev-libs/libxml2:= ) +" +DEPEND="${COMMON_DEPEND} + dev-libs/libxslt + test? ( sys-apps/dbus ) +" +RDEPEND="${COMMON_DEPEND} + ! +Date: Thu, 16 Oct 2025 18:44:07 +0200 +Subject: [PATCH 1/4] fix(storage): segfault during database migration + +The `akonadi-db-migrator` tool reproducibly crashes with a segmentation +fault (or a failed assertion if built in debug mode) while executing +`prepareDatabase()` on the destination configuration. + +The root cause is that both `DbInitializer` and `DbUpdater` expect +`SchemaVersionTable` to be populated. This assumption is not met by a +freshly created destination database: the table itself exists, but it is +empty at this point. Consequently, `SchemaVersion::retrieveAll()` +returns an empty list and the subsequent attempt to obtain its first +element triggers an out-of-bounds read. + +Fix the issue by checking for an empty result list in both places. + +Refs: https://bugs.kde.org/show_bug.cgi?id=493393 +--- + src/server/storage/dbinitializer.cpp | 17 +++++++++++------ + src/server/storage/dbupdater.cpp | 8 ++++++-- + 2 files changed, 17 insertions(+), 8 deletions(-) + +diff --git a/src/server/storage/dbinitializer.cpp b/src/server/storage/dbinitializer.cpp +index 01b3359b7..3f430ae4d 100644 +--- a/src/server/storage/dbinitializer.cpp ++++ b/src/server/storage/dbinitializer.cpp +@@ -79,12 +79,17 @@ bool DbInitializer::run() + #ifndef DBINITIALIZER_UNITTEST + // Now finally check and set the generation identifier if necessary + auto store = DataStore::dataStoreForDatabase(mDatabase); +- SchemaVersion version = SchemaVersion::retrieveAll(store).at(0); +- if (version.generation() == 0) { +- version.setGeneration(QDateTime::currentDateTimeUtc().toSecsSinceEpoch()); +- version.update(store); +- +- qCDebug(AKONADISERVER_LOG) << "Generation:" << version.generation(); ++ const auto schemaVersions = SchemaVersion::retrieveAll(store); ++ if (schemaVersions.empty()) { ++ qCDebug(AKONADISERVER_LOG) << "DbInitializer: SchemaVersion not found; skipping generation update"; ++ } else { ++ auto version = schemaVersions.at(0); ++ if (version.generation() == 0) { ++ version.setGeneration(QDateTime::currentDateTimeUtc().toSecsSinceEpoch()); ++ version.update(store); ++ ++ qCDebug(AKONADISERVER_LOG) << "Generation:" << version.generation(); ++ } + } + #endif + +diff --git a/src/server/storage/dbupdater.cpp b/src/server/storage/dbupdater.cpp +index 527cb4f65..38976e0ea 100644 +--- a/src/server/storage/dbupdater.cpp ++++ b/src/server/storage/dbupdater.cpp +@@ -42,9 +42,13 @@ DbUpdater::DbUpdater(const QSqlDatabase &database, const QString &filename) + + bool DbUpdater::run() + { +- // TODO error handling + auto store = DataStore::dataStoreForDatabase(m_database); +- auto currentVersion = SchemaVersion::retrieveAll(store).at(0); ++ const auto schemaVersions = SchemaVersion::retrieveAll(store); ++ if (schemaVersions.empty()) { ++ qCDebug(AKONADISERVER_LOG) << "DbUpdater: SchemaVersion not found; skipping schema update"; ++ return true; ++ } ++ auto currentVersion = schemaVersions.at(0); + + UpdateSet::Map updates; + +-- +GitLab + + +From 63eb46ac4c77ed57a7b9afee2ecddfba9a3aa3a4 Mon Sep 17 00:00:00 2001 +From: Christoph Erhardt +Date: Fri, 17 Oct 2025 23:46:59 +0200 +Subject: [PATCH 2/4] fix(dbmigrator): remove leftover entries in + `db_migration` directory + +This avoids potential issues when `db_migration` already contains a +stale database created with an old schema version. +--- + src/server/dbmigrator/dbmigrator.cpp | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +diff --git a/src/server/dbmigrator/dbmigrator.cpp b/src/server/dbmigrator/dbmigrator.cpp +index 575a9da16..402e55452 100644 +--- a/src/server/dbmigrator/dbmigrator.cpp ++++ b/src/server/dbmigrator/dbmigrator.cpp +@@ -326,6 +326,19 @@ std::unique_ptr dbConfigFromServerRc(const QString &configFile, bool o + } + + const auto dbPath = overrideDbPath ? StandardDirs::saveDir("data", QStringLiteral("db_migration%1").arg(dbPathSuffix)) : QString{}; ++ ++ if (overrideDbPath) { ++ // Remove any directory entries left over from a previous run ++ try { ++ for (const auto &dirEntry : std::filesystem::directory_iterator(dbPath.toStdString())) { ++ std::filesystem::remove_all(dirEntry.path()); ++ } ++ } catch (const std::filesystem::filesystem_error &e) { ++ qCCritical(AKONADIDBMIGRATOR_LOG) << "Error: failed to clear migration directory " << dbPath << ": " << e.what(); ++ return {}; ++ } ++ } ++ + config->init(settings, true, dbPath); + + return config; +-- +GitLab + + +From 9a730ddf1938666d98552d592de1c9867ce6dc84 Mon Sep 17 00:00:00 2001 +From: Christoph Erhardt +Date: Thu, 16 Oct 2025 18:45:14 +0200 +Subject: [PATCH 3/4] chore: remove unused `#include`s + +Reported by clang-tidy. +--- + src/server/collectionscheduler.cpp | 1 - + src/server/storage/collectiontreecache.h | 2 -- + src/server/storage/dbinitializer.cpp | 2 -- + 3 files changed, 5 deletions(-) + +diff --git a/src/server/collectionscheduler.cpp b/src/server/collectionscheduler.cpp +index 41ca84ece..82098600d 100644 +--- a/src/server/collectionscheduler.cpp ++++ b/src/server/collectionscheduler.cpp +@@ -9,7 +9,6 @@ + #include "storage/datastore.h" + #include "storage/selectquerybuilder.h" + +-#include "private/tristate_p.h" + #include + + #include +diff --git a/src/server/storage/collectiontreecache.h b/src/server/storage/collectiontreecache.h +index d64e73cdb..cd741e749 100644 +--- a/src/server/storage/collectiontreecache.h ++++ b/src/server/storage/collectiontreecache.h +@@ -9,8 +9,6 @@ + #include "akthread.h" + #include "entities.h" + +-#include "private/tristate_p.h" +- + #include + #include + #include +diff --git a/src/server/storage/dbinitializer.cpp b/src/server/storage/dbinitializer.cpp +index 3f430ae4d..3a58acf89 100644 +--- a/src/server/storage/dbinitializer.cpp ++++ b/src/server/storage/dbinitializer.cpp +@@ -20,8 +20,6 @@ + + #include + +-#include "private/tristate_p.h" +- + using namespace Akonadi::Server; + + DbInitializer::Ptr DbInitializer::createInstance(const QSqlDatabase &database, Schema *schema) +-- +GitLab + + +From 19740df0fd4eaf2c5bb6e3d53a1daa32496ee01d Mon Sep 17 00:00:00 2001 +From: Christoph Erhardt +Date: Thu, 16 Oct 2025 18:46:15 +0200 +Subject: [PATCH 4/4] chore: use `QDateTime::currentSecsSinceEpoch()` + +Recommended by clazy. +--- + src/server/search/searchmanager.cpp | 2 +- + src/server/storage/dbinitializer.cpp | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/server/search/searchmanager.cpp b/src/server/search/searchmanager.cpp +index 7f7d7d05d..17072f28d 100644 +--- a/src/server/search/searchmanager.cpp ++++ b/src/server/search/searchmanager.cpp +@@ -294,7 +294,7 @@ void SearchManager::updateSearchImpl(const Collection &collection) + } + + // Query all plugins for search results +- const QByteArray id = "searchUpdate-" + QByteArray::number(QDateTime::currentDateTimeUtc().toSecsSinceEpoch()); ++ const QByteArray id = "searchUpdate-" + QByteArray::number(QDateTime::currentSecsSinceEpoch()); + SearchRequest request(id, *this, mAgentSearchManager); + request.setCollections(queryCollections); + request.setMimeTypes(queryMimeTypes); +diff --git a/src/server/storage/dbinitializer.cpp b/src/server/storage/dbinitializer.cpp +index 3a58acf89..4e8d18a07 100644 +--- a/src/server/storage/dbinitializer.cpp ++++ b/src/server/storage/dbinitializer.cpp +@@ -83,7 +83,7 @@ bool DbInitializer::run() + } else { + auto version = schemaVersions.at(0); + if (version.generation() == 0) { +- version.setGeneration(QDateTime::currentDateTimeUtc().toSecsSinceEpoch()); ++ version.setGeneration(QDateTime::currentSecsSinceEpoch()); + version.update(store); + + qCDebug(AKONADISERVER_LOG) << "Generation:" << version.generation(); +-- +GitLab +