90fb2daaf151

fix: Bound cumulative locked sync inbox (v2.14.15)

time
2026-08-11 17:27 UTC · 2 months ago
machine
koh2
agent
gpt-5.6-sol
session
opaque locked background sync
parent
c7780c7fe52a
3 files VERSION+1 −1app/src/main/java/com/peachpasswords/sync/LockedSyncSpoolStore.kt+8 −1app/src/test/java/com/peachpasswords/sync/LockedSyncSpoolModelTest.kt+35 −0
VERSION+1 −1
@@ -1 +1 @@1-2.14.141+2.14.15

view file

app/src/main/java/com/peachpasswords/sync/LockedSyncSpoolStore.kt+8 −1
@@ -28,7 +28,14 @@2828     val tombstones: Map<String, Long>,2929     val inboxEntries: Map<String, LockedSyncCachedEntry> = emptyMap(),3030     val inboxTombstones: Map<String, Long> = emptyMap(),31-)31+) {32+    init {33+        require(entries.size <= SyncLimits.MAX_ENTRY_COUNT) { "sync_entry_count_exceeded" }34+        require(inboxEntries.size <= SyncLimits.MAX_ENTRY_COUNT) { "sync_entry_count_exceeded" }35+        require(tombstones.size <= SyncLimits.MAX_TOMBSTONE_COUNT) { "sync_tombstone_count_exceeded" }36+        require(inboxTombstones.size <= SyncLimits.MAX_TOMBSTONE_COUNT) { "sync_tombstone_count_exceeded" }37+    }38+}3239 3340 /** A Keystore-encrypted cache of opaque entry envelopes and transport identity. */3441 @Singleton

view file

app/src/test/java/com/peachpasswords/sync/LockedSyncSpoolModelTest.kt+35 −0
@@ -0,0 +1,35 @@1+package com.peachpasswords.sync2+3+import org.junit.Assert.assertThrows4+import org.junit.Test5+6+class LockedSyncSpoolModelTest {7+    @Test fun cumulative_inbox_counts_are_bounded_when_state_is_rebuilt() {8+        val entries = (0..SyncLimits.MAX_ENTRY_COUNT).associate { index ->9+            "entry-$index" to LockedSyncCachedEntry(1, "AA==")10+        }11+        val tombstones = (0..SyncLimits.MAX_TOMBSTONE_COUNT).associate { index ->12+            "tombstone-$index" to 1L13+        }14+15+        assertThrows(IllegalArgumentException::class.java) { state(inboxEntries = entries) }16+        assertThrows(IllegalArgumentException::class.java) { state(inboxTombstones = tombstones) }17+    }18+19+    private fun state(20+        inboxEntries: Map<String, LockedSyncCachedEntry> = emptyMap(),21+        inboxTombstones: Map<String, Long> = emptyMap(),22+    ) = LockedSyncSpool(23+        vaultId = "a".repeat(64),24+        deviceId = "device",25+        deviceName = "Android",26+        localVersion = 1,27+        longTermPublicKeyHex = "b".repeat(64),28+        longTermPrivateKeyHex = "c".repeat(64),29+        signingPublicKeyHex = "d".repeat(64),30+        entries = emptyMap(),31+        tombstones = emptyMap(),32+        inboxEntries = inboxEntries,33+        inboxTombstones = inboxTombstones,34+    )35+}

view file