FA-77851 / Subtitle cue timing / Open access
SRT timestamp parsing: minute and second range · case 01
A malformed timestamp such as 00:60:00,000 is accepted and silently becomes one hour.
ROOT CAUSE
The sexagesimal range check uses a strict > 60 bound, admitting the value 60 itself.
VERIFIED REPAIR
Reject minutes or seconds equal to or above 60.
Unsuccessful approach: Fixing only the minute bound still lets a seconds field of exactly 60 roll into the next minute.
Case contract
Parse an SRT timestamp HH:MM:SS,mmm to integer milliseconds. Hours have 2 or more digits, minutes and seconds are below 60, the fraction has 1 to 3 digits and is right-padded (",5" means 500 ms), "." is accepted as the separator, surrounding whitespace (including a CR from CRLF files) is ignored; invalid text returns None.
Why this case matters
Subtitle timing defects shift, hide or overlap captions that viewers depend on for comprehension and accessibility.
1 / The failure
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(s):
s=s.strip()
parts=s.replace('.',',').split(',')
if len(parts)!=2: return None
hms,frac=parts
fields=hms.split(':')
if len(fields)!=3: return None
if not all(p.isdigit() for p in fields) or not frac.isdigit(): return None
if len(frac)>3: return None
h,mi,se=int(fields[0]),int(fields[1]),int(fields[2])
if mi>60 or se>60: return None
ms=int(frac.ljust(3,'0'))
return h*3600000+mi*60000+se*1000+ms
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: minute and second range', ['00:60:00,000'], None), ('regression variant: minute and second range', ['10:60:60,07 '], None), ('partial repair probe: minute and second range', ['00:00:60,07'], None), ('partial repair variant: minute and second range', ['02:00:60,12\r'], None), ('boundary control', ['00:00:00,000'], 0), ('boundary control', ['00:59:59,999\r'], 3599999), ('normal control', ['00:00:01,5'], 1500), ('normal control', ['100:00:00,000'], 360000000), ('normal control', ['00:61:00;5 \r'], None)], [('regression: minute and second range', ['123:60:59,5'], None), ('regression variant: minute and second range', ['00:00:60,07'], None), ('partial repair probe: minute and second range', [' 02:30:60.500 '], None), ('partial repair variant: minute and second range', ['01:05:60,999 '], None), ('boundary control', ['00:00:01,5'], 1500), ('boundary control', ['100:00:00,000'], 360000000), ('normal control', [' 10:60:42;50\r'], None), ('normal control', ['99:00:59,001 \r'], 356459001), ('normal control', ['00:00:60.1234 '], None)], [('regression: minute and second range', [' 00:30:60,500'], None), ('regression variant: minute and second range', [' 99:60:00.000'], None), ('partial repair probe: minute and second range', ['99:30:60.000'], None), ('partial repair variant: minute and second range', ['99:30:60,001 '], None), ('boundary control', ['01:02:03.004'], 3723004), ('boundary control', ['00:00:00,000'], 0), ('normal control', [' 10:00:61.001\r'], None), ('normal control', ['99:30:00,'], None), ('normal control', [' 00:61:42,000'], None)], [('regression: minute and second range', [' 00:00:60,12 '], None), ('regression variant: minute and second range', ['99:60:59,12 \r'], None), ('partial repair probe: minute and second range', [' 10:30:60,5\r'], None), ('partial repair variant: minute and second range', ['00:59:60,07 '], None), ('boundary control', ['00:59:59,999\r'], 3599999), ('boundary control', ['00:00:01,5'], 1500), ('normal control', [' 10:05:00.000'], 36300000), ('normal control', [' 00:05:00.5 '], 300500), ('normal control', ['123:05:01,001\t'], 443101001)], [('regression: minute and second range', ['123:60:42,999'], None), ('regression variant: minute and second range', ['100:60:60,999 '], None), ('partial repair probe: minute and second range', ['123:00:60.07\t'], None), ('partial repair variant: minute and second range', ['100:05:60,001\t'], None), ('boundary control', ['100:00:00,000'], 360000000), ('boundary control', ['01:02:03.004'], 3723004), ('normal control', ['123:00:61,001 \r'], None), ('normal control', ['100:59:42.001\r'], 363582001), ('normal control', [' 10:30:61;001 '], None)]]
for label, args, expected in fixtures[N-1]:
check(label, solve(*args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| regression: minute and second range | 3600000 | None | Failed |
| regression variant: minute and second range | 39660070 | None | Failed |
| partial repair probe: minute and second range | 60070 | None | Failed |
| partial repair variant: minute and second range | 7260120 | None | Failed |
| boundary control | 0 | 0 | Passed |
| boundary control | 3599999 | 3599999 | Passed |
| normal control | 1500 | 1500 | Passed |
| normal control | 360000000 | 360000000 | Passed |
| normal control | None | None | Passed |
SHA-256 / 11a09d9cd248dc289157ba5e0d20d22c8c60b0bb7cb3b91d00ec8256e0959cc3
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(s):
s=s.strip()
parts=s.replace('.',',').split(',')
if len(parts)!=2: return None
hms,frac=parts
fields=hms.split(':')
if len(fields)!=3: return None
if not all(p.isdigit() for p in fields) or not frac.isdigit(): return None
if len(frac)>3: return None
h,mi,se=int(fields[0]),int(fields[1]),int(fields[2])
if mi>=60 or se>60: return None
ms=int(frac.ljust(3,'0'))
return h*3600000+mi*60000+se*1000+ms
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: minute and second range', ['00:60:00,000'], None), ('regression variant: minute and second range', ['10:60:60,07 '], None), ('partial repair probe: minute and second range', ['00:00:60,07'], None), ('partial repair variant: minute and second range', ['02:00:60,12\r'], None), ('boundary control', ['00:00:00,000'], 0), ('boundary control', ['00:59:59,999\r'], 3599999), ('normal control', ['00:00:01,5'], 1500), ('normal control', ['100:00:00,000'], 360000000), ('normal control', ['00:61:00;5 \r'], None)], [('regression: minute and second range', ['123:60:59,5'], None), ('regression variant: minute and second range', ['00:00:60,07'], None), ('partial repair probe: minute and second range', [' 02:30:60.500 '], None), ('partial repair variant: minute and second range', ['01:05:60,999 '], None), ('boundary control', ['00:00:01,5'], 1500), ('boundary control', ['100:00:00,000'], 360000000), ('normal control', [' 10:60:42;50\r'], None), ('normal control', ['99:00:59,001 \r'], 356459001), ('normal control', ['00:00:60.1234 '], None)], [('regression: minute and second range', [' 00:30:60,500'], None), ('regression variant: minute and second range', [' 99:60:00.000'], None), ('partial repair probe: minute and second range', ['99:30:60.000'], None), ('partial repair variant: minute and second range', ['99:30:60,001 '], None), ('boundary control', ['01:02:03.004'], 3723004), ('boundary control', ['00:00:00,000'], 0), ('normal control', [' 10:00:61.001\r'], None), ('normal control', ['99:30:00,'], None), ('normal control', [' 00:61:42,000'], None)], [('regression: minute and second range', [' 00:00:60,12 '], None), ('regression variant: minute and second range', ['99:60:59,12 \r'], None), ('partial repair probe: minute and second range', [' 10:30:60,5\r'], None), ('partial repair variant: minute and second range', ['00:59:60,07 '], None), ('boundary control', ['00:59:59,999\r'], 3599999), ('boundary control', ['00:00:01,5'], 1500), ('normal control', [' 10:05:00.000'], 36300000), ('normal control', [' 00:05:00.5 '], 300500), ('normal control', ['123:05:01,001\t'], 443101001)], [('regression: minute and second range', ['123:60:42,999'], None), ('regression variant: minute and second range', ['100:60:60,999 '], None), ('partial repair probe: minute and second range', ['123:00:60.07\t'], None), ('partial repair variant: minute and second range', ['100:05:60,001\t'], None), ('boundary control', ['100:00:00,000'], 360000000), ('boundary control', ['01:02:03.004'], 3723004), ('normal control', ['123:00:61,001 \r'], None), ('normal control', ['100:59:42.001\r'], 363582001), ('normal control', [' 10:30:61;001 '], None)]]
for label, args, expected in fixtures[N-1]:
check(label, solve(*args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| regression: minute and second range | None | None | Passed |
| regression variant: minute and second range | None | None | Passed |
| partial repair probe: minute and second range | 60070 | None | Failed |
| partial repair variant: minute and second range | 7260120 | None | Failed |
| boundary control | 0 | 0 | Passed |
| boundary control | 3599999 | 3599999 | Passed |
| normal control | 1500 | 1500 | Passed |
| normal control | 360000000 | 360000000 | Passed |
| normal control | None | None | Passed |
SHA-256 / b568922ad63f04221173b08dae00d009d9cf522fb3c3fc0968eeef0a07507dce
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(s):
s=s.strip()
parts=s.replace('.',',').split(',')
if len(parts)!=2: return None
hms,frac=parts
fields=hms.split(':')
if len(fields)!=3: return None
if not all(p.isdigit() for p in fields) or not frac.isdigit(): return None
if len(frac)>3: return None
h,mi,se=int(fields[0]),int(fields[1]),int(fields[2])
if mi>=60 or se>=60: return None
ms=int(frac.ljust(3,'0'))
return h*3600000+mi*60000+se*1000+ms
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: minute and second range', ['00:60:00,000'], None), ('regression variant: minute and second range', ['10:60:60,07 '], None), ('partial repair probe: minute and second range', ['00:00:60,07'], None), ('partial repair variant: minute and second range', ['02:00:60,12\r'], None), ('boundary control', ['00:00:00,000'], 0), ('boundary control', ['00:59:59,999\r'], 3599999), ('normal control', ['00:00:01,5'], 1500), ('normal control', ['100:00:00,000'], 360000000), ('normal control', ['00:61:00;5 \r'], None)], [('regression: minute and second range', ['123:60:59,5'], None), ('regression variant: minute and second range', ['00:00:60,07'], None), ('partial repair probe: minute and second range', [' 02:30:60.500 '], None), ('partial repair variant: minute and second range', ['01:05:60,999 '], None), ('boundary control', ['00:00:01,5'], 1500), ('boundary control', ['100:00:00,000'], 360000000), ('normal control', [' 10:60:42;50\r'], None), ('normal control', ['99:00:59,001 \r'], 356459001), ('normal control', ['00:00:60.1234 '], None)], [('regression: minute and second range', [' 00:30:60,500'], None), ('regression variant: minute and second range', [' 99:60:00.000'], None), ('partial repair probe: minute and second range', ['99:30:60.000'], None), ('partial repair variant: minute and second range', ['99:30:60,001 '], None), ('boundary control', ['01:02:03.004'], 3723004), ('boundary control', ['00:00:00,000'], 0), ('normal control', [' 10:00:61.001\r'], None), ('normal control', ['99:30:00,'], None), ('normal control', [' 00:61:42,000'], None)], [('regression: minute and second range', [' 00:00:60,12 '], None), ('regression variant: minute and second range', ['99:60:59,12 \r'], None), ('partial repair probe: minute and second range', [' 10:30:60,5\r'], None), ('partial repair variant: minute and second range', ['00:59:60,07 '], None), ('boundary control', ['00:59:59,999\r'], 3599999), ('boundary control', ['00:00:01,5'], 1500), ('normal control', [' 10:05:00.000'], 36300000), ('normal control', [' 00:05:00.5 '], 300500), ('normal control', ['123:05:01,001\t'], 443101001)], [('regression: minute and second range', ['123:60:42,999'], None), ('regression variant: minute and second range', ['100:60:60,999 '], None), ('partial repair probe: minute and second range', ['123:00:60.07\t'], None), ('partial repair variant: minute and second range', ['100:05:60,001\t'], None), ('boundary control', ['100:00:00,000'], 360000000), ('boundary control', ['01:02:03.004'], 3723004), ('normal control', ['123:00:61,001 \r'], None), ('normal control', ['100:59:42.001\r'], 363582001), ('normal control', [' 10:30:61;001 '], None)]]
for label, args, expected in fixtures[N-1]:
check(label, solve(*args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| regression: minute and second range | None | None | Passed |
| regression variant: minute and second range | None | None | Passed |
| partial repair probe: minute and second range | None | None | Passed |
| partial repair variant: minute and second range | None | None | Passed |
| boundary control | 0 | 0 | Passed |
| boundary control | 3599999 | 3599999 | Passed |
| normal control | 1500 | 1500 | Passed |
| normal control | 360000000 | 360000000 | Passed |
| normal control | None | None | Passed |
SHA-256 / b320c3ddf333d2d4b97233ac5121c4d0406a4aef4db3b9d6c696d4603f9474ab
Verification & scope
A deterministic bounded teaching model with a stipulated toy contract; it does not claim conformance to any subtitle standard. This reproducer isolates one failure mechanism. Results cover the supplied fixtures. Variants within a family share a test contract and should remain grouped when constructing evaluation splits. Related mechanisms with a shared evaluation_group must also remain together; these controlled models are not independent production incidents.
Observations recorded using Python 3.12.14 at 2026-09-29T14:49:29.792053+00:00.
Case digest / b43fecf033de21ccb49de3e3d87834413a65984dc5e8ea447c8df912ad167af3