Validate ARC timestamps and reject bad responses

Add strict validation and error handling for ARC timestamps: require exactly 8 bytes and raise a ValueError for out-of-range timestamps (wraps OverflowError/OSError/ValueError from datetime). parse_arc_response now catches timestamp decode failures and returns an empty list for invalid ARC responses. Added a unit test that injects invalid timestamp noise to ensure the parser rejects such responses.
This commit is contained in:
Golumpa 2026-06-12 10:32:17 +01:00
parent 0c9026284c
commit 1144e33a57
2 changed files with 20 additions and 2 deletions

View file

@ -50,9 +50,14 @@ def decode_arc_key(raw: bytes) -> str | None:
def decode_arc_timestamp(raw8: bytes) -> tuple[int, float, str]:
if len(raw8) != 8:
raise ValueError("arc timestamps must be exactly 8 bytes")
ticks = struct.unpack("<Q", raw8)[0]
unix_seconds = ticks / ARC_TIMESTAMP_TICKS_PER_SECOND - DOTNET_UNIX_EPOCH_SECONDS
decoded = datetime.fromtimestamp(unix_seconds, timezone.utc).strftime("%Y-%m-%d %H:%M:%S")
try:
decoded = datetime.fromtimestamp(unix_seconds, timezone.utc).strftime("%Y-%m-%d %H:%M:%S")
except (OverflowError, OSError, ValueError) as exc:
raise ValueError("arc timestamp is out of range") from exc
return ticks, unix_seconds, decoded
@ -85,7 +90,10 @@ def parse_arc_response(response: bytes) -> list[dict[str, Any]]:
pos += 8
arc_id = decode_arc_key(name_raw) or name_raw.hex()
meta = ARC_META.get(arc_id, {})
ticks, unix_seconds, timestamp_decoded = decode_arc_timestamp(timestamp_raw)
try:
ticks, unix_seconds, timestamp_decoded = decode_arc_timestamp(timestamp_raw)
except ValueError:
return []
records.append(
{
"record_start": start,