Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions packages/tar-xz/src/node/extract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ function makeTarEntryWithData(
const buf = new Uint8Array(entry.size);
let offset = 0;
for await (const c of dataGen) {
/* v8 ignore start: defensive overflow guard — parseTar clips chunks at bytesRemaining (declared entry.size), so this branch can only fire if a custom dataPull generator over-delivers; unreachable via the public extract() API */
if (offset + c.byteLength > entry.size) {
// Malformed archive: chunk would write past the declared entry size.
// Truncate at entry.size to avoid out-of-bounds writes and throw so
Expand All @@ -87,6 +88,7 @@ function makeTarEntryWithData(
{ code: 'TAR_PARSER_INVARIANT' }
);
}
/* v8 ignore stop */
buf.set(c, offset);
offset += c.byteLength;
}
Expand Down Expand Up @@ -162,9 +164,11 @@ async function drainSkippedEntry(
} catch (err) {
// Decode/IO error during skipped data — swallow per D-2.
// TAR_PARSER_INVARIANT always re-throws per D-5.
/* v8 ignore start: race-window — drainEntryChunks() would need to throw TAR_PARSER_INVARIANT during skipped-entry drain, which requires a corrupt parser state that is unreachable via public API */
if ((err as { code?: string }).code === 'TAR_PARSER_INVARIANT') {
throw err;
}
/* v8 ignore stop */
// Swallow other errors from skipped data per D-2.
}
}
Expand Down Expand Up @@ -198,11 +202,13 @@ function createEntryDataPull(
// `code: 'TAR_PARSER_INVARIANT'` attribute matches the convention used
// by other invariant errors in this module (e.g. stray-chunk in extract,
// size-mismatch in bytes()) and keeps downstream filters consistent.
/* v8 ignore start: internal state machine invariant — makeTarEntryWithData() calls dataPull() exactly once per entry and never exposes makeDataGen to consumers; concurrent-iteration path is unreachable via public API */
const err = new Error('concurrent entry.data iteration is not supported') as Error & {
code?: string;
};
err.code = 'TAR_PARSER_INVARIANT';
throw err;
/* v8 ignore stop */
}
dataGenInFlight = true;
return (async function* () {
Expand Down Expand Up @@ -290,9 +296,11 @@ export async function* extract(
if (ev.kind === 'end') break;
if (ev.kind === 'chunk') {
// Stray chunk at outer-loop level is a parser invariant violation (D-5).
/* v8 ignore start: state machine invariant — parseTar never emits 'chunk' before 'entry'; this branch guards against a hypothetical parser bug that cannot be triggered via the public API */
const err = new Error('parser invariant: chunk emitted before entry');
(err as Error & { code: string }).code = 'TAR_PARSER_INVARIANT';
throw err;
/* v8 ignore stop */
}

// ev.kind === 'entry'
Expand Down
2 changes: 2 additions & 0 deletions packages/tar-xz/src/node/file.ts
Original file line number Diff line number Diff line change
Expand Up @@ -340,7 +340,9 @@ async function openFileExclusive(
);
}
/* v8 ignore stop */
/* v8 ignore start: Win32 TOCTOU retry path — rethrow non-EEXIST errors from retry-open; reachable only if the second open() fails with an unexpected errno (e.g., EACCES from a sudden permission change between unlink and re-open) */
throw retryErr;
/* v8 ignore stop */
}
}
}
Expand Down
Loading
Loading