From 069a0f7f19953c0b8f049268c5f1e740fafa0d34 Mon Sep 17 00:00:00 2001 From: austinried <4966622+austinried@users.noreply.github.com> Date: Thu, 15 Oct 2026 06:47:21 +0000 Subject: [PATCH] sync: drop non-finite replay gain values at the parse boundary `toFloatOrNull` accepts `"Infinity"`, `"NaN"` and overflowing literals like `"1e40"`, so a server (or a corrupt tag it read) could put a non-finite gain or peak into the library. An infinite peak later caps the applied gain at negative infinity, i.e. silence; an infinite gain clips every sample to full scale. Nothing consumes these columns yet, so this is only about not storing values that cannot mean anything. --- .../data/source/subsonic/SubsonicXml.kt | 2 +- .../data/source/subsonic/SubsonicXmlTest.kt | 27 +++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/app/src/main/kotlin/com/subtracks/data/source/subsonic/SubsonicXml.kt b/app/src/main/kotlin/com/subtracks/data/source/subsonic/SubsonicXml.kt index b05441d9..ede024ca 100644 --- a/app/src/main/kotlin/com/subtracks/data/source/subsonic/SubsonicXml.kt +++ b/app/src/main/kotlin/com/subtracks/data/source/subsonic/SubsonicXml.kt @@ -245,7 +245,7 @@ internal fun Attributes.attr(name: String): String = getValue(name) ?: "" internal fun Attributes.longAttr(name: String): Long? = attr(name).takeIf { it.isNotEmpty() }?.toLongOrNull() -internal fun Attributes.floatAttr(name: String): Float? = attr(name).takeIf { it.isNotEmpty() }?.toFloatOrNull() +internal fun Attributes.floatAttr(name: String): Float? = attr(name).takeIf { it.isNotEmpty() }?.toFloatOrNull()?.takeIf { it.isFinite() } internal fun Attributes.dateAttr(name: String): Long? = attr(name).takeIf { it.isNotEmpty() }?.let(IsoDate::parse) diff --git a/app/src/test/kotlin/com/subtracks/data/source/subsonic/SubsonicXmlTest.kt b/app/src/test/kotlin/com/subtracks/data/source/subsonic/SubsonicXmlTest.kt index 116e4cec..db26724b 100644 --- a/app/src/test/kotlin/com/subtracks/data/source/subsonic/SubsonicXmlTest.kt +++ b/app/src/test/kotlin/com/subtracks/data/source/subsonic/SubsonicXmlTest.kt @@ -231,6 +231,33 @@ class SubsonicXmlTest { assertEquals(null, songs[1].albumPeak) } + @Test + fun ignoresNonFiniteReplayGainValues() { + val songs = + songs( + """ + + + + + + + + + + + """.trimIndent(), + ) + + assertEquals(null, songs[0].trackGain) + assertEquals(null, songs[0].albumGain) + assertEquals(null, songs[0].trackPeak) + assertEquals(null, songs[0].albumPeak) + assertEquals(-3.2f, songs[1].trackGain) + assertEquals(null, songs[1].albumGain) + assertEquals(0.98f, songs[1].trackPeak) + } + @Test fun ignoresSongGenresThatAreNotDirectChildren() { val songs =