diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 62b4913a68..33f1165450 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -67,6 +67,8 @@ ([#56](https://github.com/androidx/media/pull/56)). * Fix RTSP basic authorization header. ([#9544](https://github.com/google/ExoPlayer/issues/9544)). + * Throw checked exception when parsing RTSP timing + ([#10165](https://github.com/google/ExoPlayer/issues/10165)). * Session: * Fix NPE in MediaControllerImplLegacy ([#59](https://github.com/androidx/media/pull/59)) diff --git a/libraries/exoplayer_rtsp/src/main/java/androidx/media3/exoplayer/rtsp/RtspMessageUtil.java b/libraries/exoplayer_rtsp/src/main/java/androidx/media3/exoplayer/rtsp/RtspMessageUtil.java index db1e4116ea..16e5dd7c19 100644 --- a/libraries/exoplayer_rtsp/src/main/java/androidx/media3/exoplayer/rtsp/RtspMessageUtil.java +++ b/libraries/exoplayer_rtsp/src/main/java/androidx/media3/exoplayer/rtsp/RtspMessageUtil.java @@ -459,6 +459,21 @@ import java.util.regex.Pattern; "Invalid WWW-Authenticate header " + headerValue, /* cause= */ null); } + /** + * Throws {@link ParserException#createForMalformedManifest ParserException} if {@code expression} + * evaluates to false. + * + * @param expression The expression to evaluate. + * @param message The error message. + * @throws ParserException If {@code expression} is false. + */ + public static void checkManifestExpression(boolean expression, @Nullable String message) + throws ParserException { + if (!expression) { + throw ParserException.createForMalformedManifest(message, /* cause= */ null); + } + } + private static String getRtspStatusReasonPhrase(int statusCode) { switch (statusCode) { case 200: diff --git a/libraries/exoplayer_rtsp/src/main/java/androidx/media3/exoplayer/rtsp/RtspSessionTiming.java b/libraries/exoplayer_rtsp/src/main/java/androidx/media3/exoplayer/rtsp/RtspSessionTiming.java index a3493e9525..c637bb5ae3 100644 --- a/libraries/exoplayer_rtsp/src/main/java/androidx/media3/exoplayer/rtsp/RtspSessionTiming.java +++ b/libraries/exoplayer_rtsp/src/main/java/androidx/media3/exoplayer/rtsp/RtspSessionTiming.java @@ -15,8 +15,8 @@ */ package androidx.media3.exoplayer.rtsp; -import static androidx.media3.common.util.Assertions.checkArgument; -import static androidx.media3.common.util.Assertions.checkNotNull; +import static androidx.media3.common.util.Util.castNonNull; +import static androidx.media3.exoplayer.rtsp.RtspMessageUtil.checkManifestExpression; import androidx.annotation.Nullable; import androidx.media3.common.C; @@ -50,10 +50,11 @@ import java.util.regex.Pattern; long startTimeMs; long stopTimeMs; Matcher matcher = NPT_RANGE_PATTERN.matcher(sdpRangeAttribute); - checkArgument(matcher.matches()); + checkManifestExpression(matcher.matches(), /* message= */ sdpRangeAttribute); - String startTimeString = checkNotNull(matcher.group(1)); - if (startTimeString.equals("now")) { + @Nullable String startTimeString = matcher.group(1); + checkManifestExpression(startTimeString != null, /* message= */ sdpRangeAttribute); + if (castNonNull(startTimeString).equals("now")) { startTimeMs = LIVE_START_TIME; } else { startTimeMs = (long) (Float.parseFloat(startTimeString) * C.MILLIS_PER_SECOND); @@ -66,7 +67,7 @@ import java.util.regex.Pattern; } catch (NumberFormatException e) { throw ParserException.createForMalformedManifest(stopTimeString, e); } - checkArgument(stopTimeMs > startTimeMs); + checkManifestExpression(stopTimeMs >= startTimeMs, /* message= */ sdpRangeAttribute); } else { stopTimeMs = C.TIME_UNSET; } diff --git a/libraries/exoplayer_rtsp/src/test/java/androidx/media3/exoplayer/rtsp/RtspSessionTimingTest.java b/libraries/exoplayer_rtsp/src/test/java/androidx/media3/exoplayer/rtsp/RtspSessionTimingTest.java index e9ac8cf287..8a67035e7e 100644 --- a/libraries/exoplayer_rtsp/src/test/java/androidx/media3/exoplayer/rtsp/RtspSessionTimingTest.java +++ b/libraries/exoplayer_rtsp/src/test/java/androidx/media3/exoplayer/rtsp/RtspSessionTimingTest.java @@ -19,6 +19,7 @@ import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertThrows; import androidx.media3.common.C; +import androidx.media3.common.ParserException; import androidx.test.ext.junit.runners.AndroidJUnit4; import org.junit.Test; import org.junit.runner.RunWith; @@ -62,8 +63,7 @@ public class RtspSessionTimingTest { } @Test - public void parseTiming_withInvalidRangeTiming_throwsIllegalArgumentException() { - assertThrows( - IllegalArgumentException.class, () -> RtspSessionTiming.parseTiming("npt=10.000-2.054")); + public void parseTiming_withInvalidRangeTiming_throwsParserException() { + assertThrows(ParserException.class, () -> RtspSessionTiming.parseTiming("npt=10.000-2.054")); } }