From 1a9f6befd43dd854ee011991b8c642922ad4b989 Mon Sep 17 00:00:00 2001 From: Taksh Date: Tue, 25 Aug 2026 07:40:04 +0530 Subject: [PATCH] fix: destroy conversation database files when panic wipe throws If SQLite clearAll fails mid-panic, in-memory state was already cleared but a process restart could reload encrypted history from disk (#699). Fall back to deleting the database files before reporting failure. --- .../android/services/ConversationRepository.kt | 17 +++++++++++++++++ .../services/ConversationDatabaseTest.kt | 16 ++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/app/src/main/java/com/bitchat/android/services/ConversationRepository.kt b/app/src/main/java/com/bitchat/android/services/ConversationRepository.kt index 84420ec0..bc474158 100644 --- a/app/src/main/java/com/bitchat/android/services/ConversationRepository.kt +++ b/app/src/main/java/com/bitchat/android/services/ConversationRepository.kt @@ -317,6 +317,7 @@ class ConversationRepository internal constructor( true } catch (error: Exception) { Log.e(TAG, "Unable to synchronously clear private conversations", error) + database.destroyStorage() _storeState.value = ConversationStoreState.Error( error.message ?: "Unable to erase conversations" ) @@ -1097,6 +1098,22 @@ internal class ConversationDatabase( writableDatabase.rawQuery("PRAGMA incremental_vacuum", null).use { } } + /** + * Last-resort panic cleanup when [clearAll] throws: drop the encrypted database + * files so a later reload cannot resurrect erased conversations (#699). + */ + fun destroyStorage() { + try { + clearAll() + } catch (error: Exception) { + Log.e(TAG, "clearAll failed during destroyStorage; deleting database files", error) + } + try { + close() + } catch (_: Exception) { } + applicationContext.deleteDatabase(databaseName) + } + fun pruneToRetentionLimits(): Set { val db = writableDatabase val orphanedMediaPaths = linkedSetOf() diff --git a/app/src/test/kotlin/com/bitchat/android/services/ConversationDatabaseTest.kt b/app/src/test/kotlin/com/bitchat/android/services/ConversationDatabaseTest.kt index 9a01ef37..65f484a8 100644 --- a/app/src/test/kotlin/com/bitchat/android/services/ConversationDatabaseTest.kt +++ b/app/src/test/kotlin/com/bitchat/android/services/ConversationDatabaseTest.kt @@ -433,6 +433,22 @@ class ConversationDatabaseTest { } } + @Test + fun `destroy storage deletes database files so history cannot reload`() { + database.upsertMessage( + "contact_alice", + setOf("contact_alice"), + "alice", + message("survives-failure", "alice", 1L), + true + ) + assertTrue(context.databaseList().contains(databaseName)) + + database.destroyStorage() + + assertFalse(context.databaseList().contains(databaseName)) + } + @Test fun `version one plaintext database migrates without losing history`() { database.close()