diff --git a/LayoutTests/media/media-fragments/TC0095-expected.txt b/LayoutTests/media/media-fragments/TC0095-expected.txt new file mode 100644 index 000000000000..7a022090005a --- /dev/null +++ b/LayoutTests/media/media-fragments/TC0095-expected.txt @@ -0,0 +1,12 @@ + + +Title: TC0095 +Fragment: 't=0:00:03,0:00:07' +Comment: The media is requested from a to b. +EVENT(canplaythrough) +EXPECTED (video.currentTime == '3') OK +RUN(video.play()) +EVENT(pause) +EXPECTED (video.currentTime - fragmentEndTime <= '0.75') OK +END OF TEST + diff --git a/LayoutTests/media/media-fragments/TC0095.html b/LayoutTests/media/media-fragments/TC0095.html new file mode 100644 index 000000000000..0fa98451aa03 --- /dev/null +++ b/LayoutTests/media/media-fragments/TC0095.html @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/LayoutTests/media/media-fragments/media-fragments.js b/LayoutTests/media/media-fragments/media-fragments.js index d7120a53363e..30624922b5d4 100644 --- a/LayoutTests/media/media-fragments/media-fragments.js +++ b/LayoutTests/media/media-fragments/media-fragments.js @@ -72,7 +72,8 @@ TC0091 : { start: 3, end: 7, valid: true, description: "Sprinkling &", fragment: "&t=3,7&", comment: "Sprinkling & is OK."}, TC0092 : { start: null, end: null, valid: false, description: "Incorrect percent encoding", fragment: "t%3d10", comment: "UA knows that this is an invalid media fragment, so it will play the entire media resource."}, TC0093 : { start: null, end: null, valid: false, description: "Incorrect percent encoding", fragment: "t=10%26", comment: "UA knows that this is an invalid media fragment, so it will play the entire media resource."}, - TC0094 : { start: null, end: null, valid: false, description: "Trailing comma", fragment: "t=3,7,", comment: "UA knows that this is an invalid media fragment, so it will play the entire media resource."} + TC0094 : { start: null, end: null, valid: false, description: "Trailing comma", fragment: "t=3,7,", comment: "UA knows that this is an invalid media fragment, so it will play the entire media resource."}, + TC0095 : { start: 3, end: 7, valid: true, description: "NPT HH:MM:SS format. Single digit npt-hh.", fragment: "t=0:00:03,0:00:07", comment: "The media is requested from a to b."} }; function pause() diff --git a/Source/WebCore/html/MediaFragmentURIParser.cpp b/Source/WebCore/html/MediaFragmentURIParser.cpp index bf3ef91eb152..a17af4bd0bc7 100644 --- a/Source/WebCore/html/MediaFragmentURIParser.cpp +++ b/Source/WebCore/html/MediaFragmentURIParser.cpp @@ -1,5 +1,6 @@ /* - * Copyright (C) 2011, 2012 Apple Inc. All rights reserved. + * Copyright (C) 2011-2024 Apple Inc. All rights reserved. + * Copyright (C) 2023 Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -275,10 +276,8 @@ bool MediaFragmentURIParser::parseNPTTime(std::span timeString, uns return true; } - if (digits1.length() < 2) + if (digits1.length() < 1) return false; - if (digits1.length() > 2) - mode = hours; // Collect the next sequence of 0-9 after ':' if (offset >= timeString.size() || timeString[offset++] != ':') @@ -291,6 +290,15 @@ bool MediaFragmentURIParser::parseNPTTime(std::span timeString, uns int value2 = parseInteger(digits2).value(); // Detect whether this timestamp includes hours. + if (offset < timeString.size() && timeString[offset] == ':') + mode = hours; + if (mode == minutes) { + if (digits1.length() != 2) + return false; + if (value1 > 59 || value2 > 59) + return false; + } + int value3; if (mode == hours || (offset < timeString.size() && timeString[offset] == ':')) { if (offset >= timeString.size() || timeString[offset++] != ':') @@ -301,6 +309,8 @@ bool MediaFragmentURIParser::parseNPTTime(std::span timeString, uns if (digits3.length() != 2) return false; value3 = parseInteger(digits3).value(); + if (value2 > 59 || value3 > 59) + return false; } else { value3 = value2; value2 = value1;