diff --git a/src/sources/live/aircraft.js b/src/sources/live/aircraft.js index 0c7614021..6b05ac528 100644 --- a/src/sources/live/aircraft.js +++ b/src/sources/live/aircraft.js @@ -141,7 +141,8 @@ export function normalizeAircraftTrack( const latitude = finite(row[1]), longitude = finite(row[2]); const offset = finite(row[0]); - const observedAtMs = offset == null ? null : baseTimeMs + offset * 1000; + const observedAtMs = + offset == null ? null : epoch(baseTimeMs + offset * 1000); if ( !coordinates(latitude, longitude) || observedAtMs == null || diff --git a/src/sources/live/contract.js b/src/sources/live/contract.js index a1169f1f2..2415ff43c 100644 --- a/src/sources/live/contract.js +++ b/src/sources/live/contract.js @@ -32,7 +32,12 @@ export function finite(value) { export function epoch(value, scale = 1) { const number = finite(value); - return number != null && number > 0 ? number * scale : null; + const milliseconds = number == null ? null : number * scale; + return milliseconds != null && + milliseconds > 0 && + milliseconds <= 8640000000000000 + ? milliseconds + : null; } export function cleanText(value) { diff --git a/src/sources/live/contract.test.mjs b/src/sources/live/contract.test.mjs index 6ddf51a5d..76cbae24c 100644 --- a/src/sources/live/contract.test.mjs +++ b/src/sources/live/contract.test.mjs @@ -261,3 +261,13 @@ test('a malformed vessel row cannot prevent admission of valid positions', async assert.equal(snapshot.rejectedCount, 1); assert.equal(snapshot.complete, false); }); + +test('out-of-range source epochs do not reach Date or globe time constructors', () => { + const row = [...aircraft]; + row[3] = 1e100; + row[4] = 1e100; + const snapshot = openSkySnapshot({ time: 1e100, states: [row] }); + assert.equal(snapshot.observedAtMs, null); + assert.equal(snapshot.records[0].positionTimeMs, null); + assert.equal(snapshot.records[0].contactTimeMs, null); +});