mirror of
https://github.com/yattee/yattee.git
synced 2026-08-26 08:52:32 +00:00
Fix deep link timestamp parsing accepting infinity as seek position (#965)
URLRouter.parseTimestampValue used TimeInterval(_:) for the plain-numeric
branch ("90", "90.5"). That initializer also accepts the special tokens
"inf"/"infinity" and "nan", and the value infinity compares as >= 0, so a
deep link or share URL carrying ?t=inf parsed to Double.infinity and was
forwarded to the player as a seek target. Seeking to infinity is undefined
and breaks playback startup for the affected link.
Reject non-finite values explicitly alongside the existing negative
check, so only finite non-negative seconds are accepted.
- Add isFinite guard to the plain-numeric branch of parseTimestampValue
- Cover inf/infinity/nan/negative rejection in URLRouterTests
This commit is contained in:
@@ -145,9 +145,11 @@ struct URLRouter: Sendable {
|
|||||||
let trimmed = raw.trimmingCharacters(in: .whitespaces)
|
let trimmed = raw.trimmingCharacters(in: .whitespaces)
|
||||||
guard !trimmed.isEmpty else { return nil }
|
guard !trimmed.isEmpty else { return nil }
|
||||||
|
|
||||||
// Plain numeric value (e.g. "90", "90.5")
|
// Plain numeric value (e.g. "90", "90.5"). Reject non-finite values
|
||||||
|
// ("inf"/"infinity"/"nan") that `TimeInterval(_:)` accepts — a `?t=inf`
|
||||||
|
// link would otherwise seek the player to `Double.infinity`.
|
||||||
if let value = TimeInterval(trimmed) {
|
if let value = TimeInterval(trimmed) {
|
||||||
return value >= 0 ? value : nil
|
return (value.isFinite && value >= 0) ? value : nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compound form like "1h2m3s", "2m30s", "90s"
|
// Compound form like "1h2m3s", "2m30s", "90s"
|
||||||
|
|||||||
@@ -123,6 +123,20 @@ struct URLRouterTests {
|
|||||||
#expect(URLRouter.parseTimestampValue("90.5") == 90.5)
|
#expect(URLRouter.parseTimestampValue("90.5") == 90.5)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test("Reject non-finite and negative plain timestamp values")
|
||||||
|
func rejectInvalidPlainTimestampValues() {
|
||||||
|
// Plain numeric values that are accepted by TimeInterval(_:) but are not
|
||||||
|
// valid seek targets must return nil rather than poisoning the player.
|
||||||
|
#expect(URLRouter.parseTimestampValue("inf") == nil)
|
||||||
|
#expect(URLRouter.parseTimestampValue("infinity") == nil)
|
||||||
|
#expect(URLRouter.parseTimestampValue("nan") == nil)
|
||||||
|
#expect(URLRouter.parseTimestampValue("-5") == nil)
|
||||||
|
// Valid plain seconds still parse.
|
||||||
|
#expect(URLRouter.parseTimestampValue("0") == 0)
|
||||||
|
#expect(URLRouter.parseTimestampValue("90") == 90)
|
||||||
|
#expect(URLRouter.parseTimestampValue("90.5") == 90.5)
|
||||||
|
}
|
||||||
|
|
||||||
// MARK: - Share Extension Wrapper Tests
|
// MARK: - Share Extension Wrapper Tests
|
||||||
|
|
||||||
@Test("Unwrap yattee://open wrapper to inner URL with timestamp")
|
@Test("Unwrap yattee://open wrapper to inner URL with timestamp")
|
||||||
|
|||||||
Reference in New Issue
Block a user