mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-10 01:56:16 -08:00
fix(stalker): reject out-of-range calendar components in expiry dates
The multi-argument Date constructor normalizes invalid components
('2026-00-00' becomes Nov 30, 2025), fabricating an expiry and countdown
from a placeholder. Round-trip the parsed year/month/day and reject any
date that does not survive unchanged.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
153b17f6ad
commit
1fffa7f3fb
2 files changed
+25
-8
No files matched your search
@@ -299,6 +299,14 @@ describe('parseStalkerDate', () => {
|
||||
expect(parseStalkerDate('not a date')).toBeUndefined();
|
||||
});
|
||||
|
||||
it('rejects out-of-range calendar components instead of normalizing them', () => {
|
||||
// new Date(2026, -1, 0) silently becomes Nov 30, 2025 — a
|
||||
// placeholder must not fabricate an expiry.
|
||||
expect(parseStalkerDate('2026-00-00')).toBeUndefined();
|
||||
expect(parseStalkerDate('2026-02-30')).toBeUndefined();
|
||||
expect(parseStalkerDate('2026-13-01')).toBeUndefined();
|
||||
});
|
||||
|
||||
it('rejects negative unlimited-expiry sentinels instead of parsing them as dates', () => {
|
||||
// V8 reads Date.parse('-1') as January 1, 2001 — an unlimited
|
||||
// account must not render as expired.
|
||||
|
||||
@@ -238,14 +238,23 @@ export function parseStalkerDate(
|
||||
// UTC and moves the days-left boundary. Build it in local time instead.
|
||||
const dateOnly = /^(\d{4})-(\d{2})-(\d{2})$/.exec(text);
|
||||
if (dateOnly) {
|
||||
const [, year, month, day] = dateOnly;
|
||||
const local = new Date(
|
||||
Number(year),
|
||||
Number(month) - 1,
|
||||
Number(day)
|
||||
).getTime();
|
||||
return Number.isFinite(local) && local > 0
|
||||
? Math.round(local / 1000)
|
||||
const year = Number(dateOnly[1]);
|
||||
const month = Number(dateOnly[2]);
|
||||
const day = Number(dateOnly[3]);
|
||||
const local = new Date(year, month - 1, day);
|
||||
// Round-trip check: the multi-argument constructor normalizes
|
||||
// out-of-range components ('2026-00-00' → Nov 30, 2025), which
|
||||
// would fabricate an expiry from a placeholder.
|
||||
if (
|
||||
local.getFullYear() !== year ||
|
||||
local.getMonth() !== month - 1 ||
|
||||
local.getDate() !== day
|
||||
) {
|
||||
return undefined;
|
||||
}
|
||||
const timestamp = local.getTime();
|
||||
return Number.isFinite(timestamp) && timestamp > 0
|
||||
? Math.round(timestamp / 1000)
|
||||
: undefined;
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user