From 92dac661c448a456c993226e0657bd246972e23a Mon Sep 17 00:00:00 2001 From: darken Date: Mon, 31 Aug 2026 12:35:47 +0200 Subject: [PATCH] fix(device): Keep a log line for rejected malformed addresses Structurally broken addresses now fail the octet parse instead of throwing, so the catch-all error log no longer fires for them. Log the rejection at WARN with a redacted address so support logs still show it. Fixes review finding F1. --- .../core/apple/ble/protocol/RPAChecker.kt | 7 ++++- .../capod/monitor/core/RPACheckerTest.kt | 28 +++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/eu/darken/capod/pods/core/apple/ble/protocol/RPAChecker.kt b/app/src/main/java/eu/darken/capod/pods/core/apple/ble/protocol/RPAChecker.kt index c3db959e..422e5a17 100644 --- a/app/src/main/java/eu/darken/capod/pods/core/apple/ble/protocol/RPAChecker.kt +++ b/app/src/main/java/eu/darken/capod/pods/core/apple/ble/protocol/RPAChecker.kt @@ -30,7 +30,12 @@ class RPAChecker @Inject constructor() { fun resolve(address: BluetoothAddress, irk: IdentityResolvingKey): AddressOrder? = try { val octets = address.parseOctets() when { - octets == null -> null + octets == null -> { + log(TAG, Logging.Priority.WARN) { + "Failed to resolve RPA, malformed address: ${address.redactedForLogs()}" + } + null + } matchesHash(octets, irk) -> AddressOrder.STANDARD else -> octets.reversedArray() .takeIf { it.isRpaShaped() && matchesHash(it, irk) } diff --git a/app/src/test/java/eu/darken/capod/monitor/core/RPACheckerTest.kt b/app/src/test/java/eu/darken/capod/monitor/core/RPACheckerTest.kt index 366c18fb..d49d3dc7 100644 --- a/app/src/test/java/eu/darken/capod/monitor/core/RPACheckerTest.kt +++ b/app/src/test/java/eu/darken/capod/monitor/core/RPACheckerTest.kt @@ -162,4 +162,32 @@ class RPACheckerTest : BaseTest() { captured.any { (_, message) -> message.contains(keyHex, ignoreCase = true) } shouldBe false captured.any { (_, message) -> message.contains(resolvingAddress) } shouldBe false } + + @Test + fun `a malformed address is logged as a warning`() { + val captured = mutableListOf>() + val capturingLogger = object : Logging.Logger { + override fun log( + priority: Logging.Priority, + tag: String, + message: String, + metaData: Map?, + ) { + captured.add(priority to message) + } + } + + Logging.clearAll() + Logging.install(capturingLogger) + try { + RPAChecker().verify(address = "123", irk = irkHex.fromHex()) shouldBe false + } finally { + Logging.clearAll() + Logging.install(JUnitLogger()) + } + + captured.any { (priority, message) -> + priority == Logging.Priority.WARN && message.contains("malformed") + } shouldBe true + } } \ No newline at end of file