diff --git a/src/rust/RustAuditableReader.test.ts b/src/rust/RustAuditableReader.test.ts index a76ef2e45b..40d42691c2 100644 --- a/src/rust/RustAuditableReader.test.ts +++ b/src/rust/RustAuditableReader.test.ts @@ -283,6 +283,30 @@ it("names the padded-storage basis when a padded section overflows inflate alloc ); }); +it("names the fixed cap when it bounds a large padded section's inflate allocation", () => { + // Storage above 128 KiB derives more than the fixed 8 MiB cap, so the cap, + // not the padded storage size, is the enforced bound. + const compressed = deflateSync(Buffer.alloc(9 * 1024 * 1024, 0x20)); + const fileAlignment = 512; + const stored = Buffer.alloc(132 * 1024); + compressed.copy(stored); + let failure: unknown; + try { + readAuditableSection(".dep-v0", 0, stored, { + peFileAlignment: fileAlignment, + }); + } catch (cause: unknown) { + failure = cause; + } + expect(failure).toMatchObject({ + constraint: { + resource: "memory", + reported_limits: { maximum_bytes: 8 * 1024 * 1024 }, + }, + }); + expect((failure as Error).message).not.toContain("storage size"); +}); + it.each([0, 8])("reads documented cargo-auditable revision %i", (format) => { const parsed = section({ format, diff --git a/src/rust/RustAuditableReader.ts b/src/rust/RustAuditableReader.ts index 0fd2e21395..0d77238df4 100644 --- a/src/rust/RustAuditableReader.ts +++ b/src/rust/RustAuditableReader.ts @@ -148,10 +148,14 @@ const inflateSection = ( }), ); } catch (cause) { + // Only a padded section whose storage-derived allowance is below the fixed + // cap is bounded by its storage size; otherwise the fixed cap applies. throw inflateFailure( cause, allocationMaximum, - peFileAlignment !== undefined && peFileAlignment > 0, + peFileAlignment !== undefined && + peFileAlignment > 0 && + allocationMaximum < RUST_UNCOMPRESSED_BYTES, ); } const compressedBytes = result.consumedBytes; @@ -196,7 +200,7 @@ const inflateSection = ( const inflateFailure = ( cause: unknown, maximum: number, - paddedStorage: boolean, + storageBounded: boolean, ): Error => { const code = cause instanceof Error && "code" in cause ? String(cause.code) : ""; @@ -206,7 +210,7 @@ const inflateFailure = ( // The stream length is unknown until inflate finishes, so a padded PE // section is bounded by its storage size; say so instead of implying the // smaller limit derived from the consumed stream. - paddedStorage + storageBounded ? `Inflated dependency JSON exceeds the ${String(maximum)}-byte allowance derived from the padded section's storage size; the zlib stream length is unknown until it inflates, so the smaller stream-based limit could not be applied first` : "Inflated dependency JSON exceeds the size limit", );