Expose bounded post-build Source Check failures to authors (#641)
This commit is contained in:
parent
6f5b5265b6
commit
94ddc8bedf
@@ -1,6 +1,13 @@
|
||||
import { constants } from "node:fs";
|
||||
import { open } from "node:fs/promises";
|
||||
|
||||
const admissionFailure = (
|
||||
code: string,
|
||||
kind: "file-bytes" | "total-bytes" | "owner-bytes" | "candidates",
|
||||
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. */
|
||||
@@ -27,7 +34,8 @@ export class CandidateMetadataBudget {
|
||||
}
|
||||
acquire(owner: string) {
|
||||
if (!owner || owner.length > 4096) throw Error("INVALID_CANDIDATE_METADATA_OWNER");
|
||||
if (this.scopes >= this.limits.candidates) throw Error("CANDIDATE_METADATA_LIMIT");
|
||||
if (this.scopes >= this.limits.candidates)
|
||||
throw admissionFailure("CANDIDATE_METADATA_LIMIT", "candidates", this.scopes + 1, this.limits.candidates);
|
||||
this.scopes++;
|
||||
let bytes = 0,
|
||||
closed = false;
|
||||
@@ -35,8 +43,10 @@ export class CandidateMetadataBudget {
|
||||
if (closed) throw Error("CANDIDATE_METADATA_CLOSED");
|
||||
if (!Number.isSafeInteger(amount) || amount < 0) throw Error("INVALID_CANDIDATE_METADATA_CHARGE");
|
||||
const owned = this.owners.get(owner) ?? 0;
|
||||
if (this.bytes + amount > this.limits.bytes || owned + amount > this.limits.ownerBytes)
|
||||
throw Error("CANDIDATE_METADATA_LIMIT");
|
||||
if (this.bytes + amount > this.limits.bytes)
|
||||
throw admissionFailure("CANDIDATE_METADATA_LIMIT", "total-bytes", this.bytes + amount, this.limits.bytes);
|
||||
if (owned + amount > this.limits.ownerBytes)
|
||||
throw admissionFailure("CANDIDATE_METADATA_LIMIT", "owner-bytes", owned + amount, this.limits.ownerBytes);
|
||||
bytes += amount;
|
||||
this.bytes += amount;
|
||||
this.owners.set(owner, owned + amount);
|
||||
@@ -116,8 +126,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);
|
||||
|
||||
Reference in New Issue
Block a user