Pin three untested guards: download timer, URL fragment, short APP1 (closes #89)
check / check (push) Successful in 24s

The download idle deadline's timer is unref'd so it never holds the
process open, and a test checks no timer is left after a download
completes or fails. A test covers the rejection of "#" in a request
path. The EXIF scan accepts an APP1 segment only when its length is at
least 8, since a shorter one cannot hold the six-byte Exif header;
tests cover lengths 7 and 8.

Model: opus-5-5
This commit was merged in pull request #91.
This commit is contained in:
2026-09-23 03:44:45 +02:00
parent 28a2beeab8
commit c75c4f987c
5 changed files with 83 additions and 3 deletions
+3 -2
View File
@@ -49,8 +49,8 @@ export interface StreamOptions {
// An abort signal that fires once `ms` pass without a call to `restart`. It
// aborts with a `TimeoutError`, the same reason `AbortSignal.timeout()` gives,
// so the retry classifier treats an idle download exactly as it treats any
// other deadline. `stop` must be called when the download ends, or the timer
// keeps the process alive until it fires.
// other deadline. `stop` must be called when the download ends. The timer is
// unref'd, so even one left running never keeps the process alive.
const idleDeadline = (ms: number) => {
const controller = new AbortController();
let timer: ReturnType<typeof setTimeout> | undefined;
@@ -65,6 +65,7 @@ const idleDeadline = (ms: number) => {
),
);
}, ms);
timer.unref();
};
restart();
return { signal: controller.signal, restart, stop };
+4 -1
View File
@@ -45,8 +45,11 @@ export const extractExifFromJpeg = (
error: `segment length ${len} at byte ${offset} runs past the end of the file`,
};
if (marker === 0xe1) {
// APP1 — check for "Exif\0\0" header
// APP1 — check for "Exif\0\0" header. A length under 8 cannot hold
// the six-byte header, so the segment is not EXIF; below 6 the
// bytes compared would also lie past the segment.
if (
len >= 8 &&
buf[offset + 4] === 0x45 &&
buf[offset + 5] === 0x78 &&
buf[offset + 6] === 0x69 &&