diff --git a/src/artifacts/NtfsMftArtifactReader.test.ts b/src/artifacts/NtfsMftArtifactReader.test.ts index 4f53a31e0c..ba08231d99 100644 --- a/src/artifacts/NtfsMftArtifactReader.test.ts +++ b/src/artifacts/NtfsMftArtifactReader.test.ts @@ -1,7 +1,10 @@ import { writeFile } from "node:fs/promises"; import { join } from "node:path"; -import { expect, it } from "vitest"; +import { expect, it, vi } from "vitest"; + +import { ArtifactFileSource } from "./ArtifactFileSource.js"; +import { NtfsMftArtifactReader } from "./NtfsMftArtifactReader.js"; import { MFT_DEFAULT_RECORD_BYTES } from "../domain/windows/ntfsMft.js"; import { createTestTempDirectory } from "../../tests/fixtures/temporaryDirectory.js"; @@ -98,3 +101,25 @@ it("reports incomplete coverage when FILE extents contradict the record slots", fixup_unverified_record_count: 0, }); }); + +it("does not publish metadata when final source verification fails", async () => { + const reader = new NtfsMftArtifactReader( + await writeMft("$MFT", recordBytes({})), + ); + const read = ArtifactFileSource.prototype.read; + const spy = vi + .spyOn(ArtifactFileSource.prototype, "read") + .mockImplementationOnce(function (this: ArtifactFileSource, signal) { + return read.call(this, signal); + }) + .mockRejectedValueOnce(new Error("final source verification failed")); + try { + await expect(reader.entries().next()).rejects.toThrow( + "final source verification failed", + ); + expect(reader.formatMetadata()).toBeUndefined(); + } finally { + spy.mockRestore(); + await reader.close(); + } +}); diff --git a/src/artifacts/NtfsMftArtifactReader.ts b/src/artifacts/NtfsMftArtifactReader.ts index d69df419ec..3b4bf97a82 100644 --- a/src/artifacts/NtfsMftArtifactReader.ts +++ b/src/artifacts/NtfsMftArtifactReader.ts @@ -93,9 +93,9 @@ export class NtfsMftArtifactReader implements ArtifactReader { async #prepare(signal?: AbortSignal): Promise { const image = await this.#decode(signal); + await this.#source.read(signal); this.#metadata = image.metadata; this.#limitations = image.limitations; - await this.#source.read(signal); } async #decode(signal?: AbortSignal): Promise {