fix(artifacts): verify MFT source before publishing metadata

Co-authored-by: gensokyo-dev <342580529+gensokyo-dev@users.noreply.github.com>
This commit is contained in:
N0zoM1z0andgensokyo-dev authored and gensokyo-dev committed 2026-11-11 10:03:35 +08:00
1 parent ebb480ba22
commit fbe09f84df
2 files changed
+27 -2

No files matched your search

+26 -1
View File
@@ -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();
}
});
+1 -1
View File
@@ -93,9 +93,9 @@ export class NtfsMftArtifactReader implements ArtifactReader {
async #prepare(signal?: AbortSignal): Promise<void> {
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<MftImage> {