diff --git a/.quixos-subtree-source.json b/.quixos-subtree-source.json index 96a6f76..7b8f75e 100644 --- a/.quixos-subtree-source.json +++ b/.quixos-subtree-source.json @@ -1,7 +1,7 @@ { "version": 1, "sourceRepo": "https://gitea.internal.quixos.org/quixos/quixos.git", - "sourceCommit": "e8df5e3396060619b33ab3cf9458231ef220ccc7", + "sourceCommit": "473886a58fdacf15f2c873b77da96faf3be7fa65", "sourcePath": "quixos-protocol", "exportName": "quixos-protocol", "mirrorRemote": "https://repos.quixos.org/quixos-toolchain/quixos-protocol.git" diff --git a/src/execution-world/metadata.ts b/src/execution-world/metadata.ts index a06e35c..547d99e 100644 --- a/src/execution-world/metadata.ts +++ b/src/execution-world/metadata.ts @@ -1,6 +1,9 @@ import { constants } from "node:fs"; import { open } from "node:fs/promises"; +const admissionFailure = (code: string, kind: "file-bytes", measured: number, limit: number) => + Object.assign(Error(code), { metadataAdmission: { kind, measured, limit } }); + /** Admission estimates, not a hard V8 heap limit. A process/cgroup ceiling is * still required. Charge input, parse trees and derived indexes before reading * or parsing. Each live candidate retains its reservation until explicit close. */ @@ -116,8 +119,8 @@ export async function readCandidateMetadata( let releaseInput: (() => void) | undefined; try { const stat = await handle.stat(); - if (!stat.isFile() || !Number.isSafeInteger(stat.size) || stat.size > limit) - throw Error("CANDIDATE_METADATA_FILE_LIMIT"); + if (!stat.isFile() || !Number.isSafeInteger(stat.size)) throw Error("CANDIDATE_METADATA_FILE_LIMIT"); + if (stat.size > limit) throw admissionFailure("CANDIDATE_METADATA_FILE_LIMIT", "file-bytes", stat.size, limit); // Reserve the input buffer and UTF-16 decoding before allocating either. releaseInput = scope.reserve((stat.size + 1) * 3); const bytes = Buffer.alloc(stat.size + 1);