fix: do not mistake a name beginning with 127 for the phone itself

A server called something like 127.books.home is a name, not an
address, and it was being read as the phone talking to itself — which
is the one case the permission check deliberately lets through. A
reader with such a server would have got the timeout rather than the
prompt. All four parts of an address now have to be numbers before it
is treated as one.
This commit is contained in:
Chmouel Boudjnah 2026-09-11 07:47:25 +02:00
parent c658abd656
commit 302b91b9e7
2 changed files with 19 additions and 1 deletions

View file

@ -178,7 +178,7 @@ object LocalNetworkAddress {
}
private fun isV4Loopback(host: String): Boolean =
host.split('.').let { it.size == 4 && it.first().toIntOrNull() == 127 }
isLiteral(host) && ':' !in host && host.substringBefore('.').toInt() == 127
private fun isLiteral(host: String): Boolean =
':' in host || host.split('.').let { parts ->

View file

@ -90,6 +90,24 @@ class LocalNetworkAddressTest {
* trailing dot as part of it would send an mDNS address off to be
* resolved by mDNS, which is what the permission is blocking.
*/
/**
* A name is not an address because it starts with a number. Reading
* `127.books.home.local` as loopback would exempt a server on the
* reader's own network from the one check that gets them prompted.
*/
@Test
fun `a name that begins with 127 is still a name`() = runTest {
assertTrue(
LocalNetworkAddress.isLocal("http://127.books.home.local:8083", resolver = refusing),
)
assertTrue(
LocalNetworkAddress.isLocal(
"http://127.books.example.com:8083",
resolver = { listOf("192.168.1.20") },
),
)
}
@Test
fun `a name written out to the root label is the same name`() = runTest {
assertTrue(LocalNetworkAddress.isLocal("http://books.local.:8083", resolver = refusing))