[GH-ISSUE #7352] [Bug] Rust inspection describes the inflate ratio using stored section size #4371

Closed
opened 2026-10-31 00:49:17 +00:00 by bsakaguchi · 0 comments
Owner

Originally created by @coygeek on GitHub (Oct 27, 2026).
Original GitHub issue: https://github.com/morluto/rea/issues/7352

Before submitting

  • I searched the open and closed issues for a related report.
  • I removed credentials, tokens, private paths, and sensitive target data.

Area

Evidence, artifacts, or reconstruction

Observed behavior

A successful inspect-rust-binary --json report says inflated JSON is limited to “64 times the section size.” For the supported padded PE case below, the report records section_bytes: 512 and compressed_bytes: 83, while the documented and implemented ratio uses the compressed stream length. The wording identifies 32768 bytes as the ratio-derived ceiling instead of 5312 bytes. The package records are returned successfully; this report concerns the limitation sentence only.

Reproduction

Run the following from the baseline checkout with its built CLI and pinned Node runtime available. It creates two inert PE32+ fixtures and invokes the public CLI without executing either image. Both cases were run once with this script; both exited 0.

set -eu
repo_dir="$PWD"
work_dir="$(mktemp -d)"
mkdir -p "$work_dir/home" "$work_dir/config" "$work_dir/cache" "$work_dir/temp"
cat > "$work_dir/repro.mjs" <<'JS'
import {deflateSync} from 'node:zlib';
import {writeFileSync} from 'node:fs';
import {join} from 'node:path';
import {spawnSync} from 'node:child_process';
const [work,repo]=process.argv.slice(2);
const document=JSON.stringify({format:1,packages:[{name:'sample',version:'1',source:'local',root:true}]});
const payload=deflateSync(Buffer.from(document));
const image=Buffer.alloc(1024);
const u16=(p,v)=>image.writeUInt16LE(v,p),u32=(p,v)=>image.writeUInt32LE(v,p);
image.write('MZ');u32(60,128);image.write('PE\0\0',128);
u16(132,0x8664);u16(134,1);u16(148,112);u16(150,0x22);u16(152,0x20b);
image.writeBigUInt64LE(0x140000000n,176);
u32(184,4096);u32(188,512);u32(208,8192);u32(212,512);u16(220,3);
image.write('.dep-v0',264);u32(276,4096);u32(280,512);u32(284,512);u32(300,0x40000040);
payload.copy(image,512);
const env={PATH:process.env.PATH,HOME:join(work,'home'),XDG_CONFIG_HOME:join(work,'config'),XDG_CACHE_HOME:join(work,'cache'),TMPDIR:join(work,'temp'),REA_LOG_LEVEL:'silent'};
for(const [name,virtualSize] of [['padded',0],['exact',payload.length]]) {
 u32(272,virtualSize);
 const path=join(work,name+'.exe');writeFileSync(path,image);
 const result=spawnSync(process.execPath,[join(repo,'scripts/rea.mjs'),'inspect-rust-binary',path,'--json'],{env,cwd:work,encoding:'utf8',timeout:30000});
 if(result.error) throw result.error;
 const report=JSON.parse(result.stdout).normalized_result,metadata=report.auditable_metadata;
 console.log(JSON.stringify({name,exit:result.status,section_bytes:metadata.section_bytes,compressed_bytes:metadata.compressed_bytes,uncompressed_bytes:metadata.uncompressed_bytes,guard:report.limitations.find(x=>x.startsWith('Resource guards'))}));
}
JS
node "$work_dir/repro.mjs" "$work_dir" "$repo_dir"

The padded case prints section_bytes: 512, compressed_bytes: 83, and uncompressed_bytes: 86. The exact-size control prints section_bytes: 83 with the same compressed and uncompressed sizes. Both print the same sentence containing “64 times the section size.”

Expected behavior

The successful report should describe the inflated-JSON ratio using the consumed compressed stream length, consistently with the documented meaning of compressed_bytes and the reader's post-decode check. Accepted PE alignment bytes are part of section_bytes and are excluded from that ratio. The existing acceptance and refusal bounds should remain unchanged.

Impact and scope

P3 wording defect: successful Evidence misdescribes the ratio basis when accepted PE padding makes stored section size differ from compressed stream size. The tested padded input returns correct package records and sizes. No consequential caller behavior, data loss, or incorrect admission was observed. Users can read compressed_bytes with the documented ratio to identify the applicable ceiling. Real-producer frequency and other interfaces were not measured.

REA version

Source revision ace4dbf36e8c8f36a0e192aff9a11484ed428358; prepared built source CLI.

Runtime and platform

Node.js v24.22.1; Darwin 27.0.0 arm64. No Rust toolchain or external analysis engine was used.

Target and artifact context

Two self-authored 1024-byte PE32+ x86-64 images, each with one .dep-v0 section containing an 83-byte zlib stream for an 86-byte JSON document. FileAlignment and SizeOfRawData are 512. The fixtures differ only in VirtualSize: zero selects the supported raw-size fallback; 83 selects the exact stream range. The images are read as files and never executed.

Interface

CLI

Earliest failure stage

Transport or result projection

Relevant output or evidence

  • Expected source: docs/rust-binaries.md:96-100 distinguishes the stored section range from the zlib stream length used for the ratio; docs/rust-binaries.md:136-146 specifies the compressed-stream ratio and accepted PE padding. src/rust/RustAuditableReader.ts:175-186 applies the post-decode bound to consumed compressed bytes.
  • Failure source: Executed public CLI output for the padded case records section_bytes: 512 and compressed_bytes: 83 alongside the limitation “inflated JSON to the smaller of 8 MiB and 64 times the section size.” src/rust/RustBinaryProvider.ts:174 produces that sentence; the exact-size control returns identical wording when both sizes are 83.
  • Evidence provenance: observed CLI output; the stated ratio implementation is source-derived.
  • Local verification: reproduced using the complete inline script on the stated runtime. Both fixtures exited 0, with the sizes and limitation described above.
  • Reproduction completeness: complete for the successful-report wording defect on these synthetic inputs.

Additional context

Restoration check (proposed, unexecuted): repeat the inline reproduction and confirm that the padded successful report describes the 83-byte compressed stream as the ratio basis, while both fixtures continue to return their current package records and accurate section and compressed sizes. Preserve the existing resource bounds.

The supplied open and closed issue inventory and matching full bodies contained no report of this successful limitation sentence. Closed #6793 concerns rejection of PE alignment padding, and closed #5556 concerns fixed-budget recovery advice; neither has this failure signal or restoration criterion. NOT_ENOUGH_INFO: no last-known-good release was runtime-tested, and occurrence in compiler-produced artifacts was not measured.

Triage assessment

  • Impact level: P3
  • Assessment status: supported
  • Impact basis: The successful report names stored section size as the ratio basis even though accepted padding is excluded by the reader. The reproduced issue changes wording only; correct metadata and successful inspection were observed.
  • Workaround status: available
  • Workaround basis: The same successful report provides compressed_bytes: 83; using the documented 64-times-stream rule gives 5312 bytes. No artifact modification or guard change is needed to interpret the limit correctly.
Originally created by @coygeek on GitHub (Oct 27, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/7352 ## Before submitting - [x] I searched the open and closed issues for a related report. - [x] I removed credentials, tokens, private paths, and sensitive target data. ## Area Evidence, artifacts, or reconstruction ## Observed behavior A successful `inspect-rust-binary --json` report says inflated JSON is limited to “64 times the section size.” For the supported padded PE case below, the report records `section_bytes: 512` and `compressed_bytes: 83`, while the documented and implemented ratio uses the compressed stream length. The wording identifies 32768 bytes as the ratio-derived ceiling instead of 5312 bytes. The package records are returned successfully; this report concerns the limitation sentence only. ## Reproduction Run the following from the baseline checkout with its built CLI and pinned Node runtime available. It creates two inert PE32+ fixtures and invokes the public CLI without executing either image. Both cases were run once with this script; both exited 0. ```sh set -eu repo_dir="$PWD" work_dir="$(mktemp -d)" mkdir -p "$work_dir/home" "$work_dir/config" "$work_dir/cache" "$work_dir/temp" cat > "$work_dir/repro.mjs" <<'JS' import {deflateSync} from 'node:zlib'; import {writeFileSync} from 'node:fs'; import {join} from 'node:path'; import {spawnSync} from 'node:child_process'; const [work,repo]=process.argv.slice(2); const document=JSON.stringify({format:1,packages:[{name:'sample',version:'1',source:'local',root:true}]}); const payload=deflateSync(Buffer.from(document)); const image=Buffer.alloc(1024); const u16=(p,v)=>image.writeUInt16LE(v,p),u32=(p,v)=>image.writeUInt32LE(v,p); image.write('MZ');u32(60,128);image.write('PE\0\0',128); u16(132,0x8664);u16(134,1);u16(148,112);u16(150,0x22);u16(152,0x20b); image.writeBigUInt64LE(0x140000000n,176); u32(184,4096);u32(188,512);u32(208,8192);u32(212,512);u16(220,3); image.write('.dep-v0',264);u32(276,4096);u32(280,512);u32(284,512);u32(300,0x40000040); payload.copy(image,512); const env={PATH:process.env.PATH,HOME:join(work,'home'),XDG_CONFIG_HOME:join(work,'config'),XDG_CACHE_HOME:join(work,'cache'),TMPDIR:join(work,'temp'),REA_LOG_LEVEL:'silent'}; for(const [name,virtualSize] of [['padded',0],['exact',payload.length]]) { u32(272,virtualSize); const path=join(work,name+'.exe');writeFileSync(path,image); const result=spawnSync(process.execPath,[join(repo,'scripts/rea.mjs'),'inspect-rust-binary',path,'--json'],{env,cwd:work,encoding:'utf8',timeout:30000}); if(result.error) throw result.error; const report=JSON.parse(result.stdout).normalized_result,metadata=report.auditable_metadata; console.log(JSON.stringify({name,exit:result.status,section_bytes:metadata.section_bytes,compressed_bytes:metadata.compressed_bytes,uncompressed_bytes:metadata.uncompressed_bytes,guard:report.limitations.find(x=>x.startsWith('Resource guards'))})); } JS node "$work_dir/repro.mjs" "$work_dir" "$repo_dir" ``` The padded case prints `section_bytes: 512`, `compressed_bytes: 83`, and `uncompressed_bytes: 86`. The exact-size control prints `section_bytes: 83` with the same compressed and uncompressed sizes. Both print the same sentence containing “64 times the section size.” ## Expected behavior The successful report should describe the inflated-JSON ratio using the consumed compressed stream length, consistently with the documented meaning of `compressed_bytes` and the reader's post-decode check. Accepted PE alignment bytes are part of `section_bytes` and are excluded from that ratio. The existing acceptance and refusal bounds should remain unchanged. ## Impact and scope P3 wording defect: successful Evidence misdescribes the ratio basis when accepted PE padding makes stored section size differ from compressed stream size. The tested padded input returns correct package records and sizes. No consequential caller behavior, data loss, or incorrect admission was observed. Users can read `compressed_bytes` with the documented ratio to identify the applicable ceiling. Real-producer frequency and other interfaces were not measured. ## REA version Source revision `ace4dbf36e8c8f36a0e192aff9a11484ed428358`; prepared built source CLI. ## Runtime and platform Node.js v24.22.1; Darwin 27.0.0 arm64. No Rust toolchain or external analysis engine was used. ## Target and artifact context Two self-authored 1024-byte PE32+ x86-64 images, each with one `.dep-v0` section containing an 83-byte zlib stream for an 86-byte JSON document. `FileAlignment` and `SizeOfRawData` are 512. The fixtures differ only in `VirtualSize`: zero selects the supported raw-size fallback; 83 selects the exact stream range. The images are read as files and never executed. ## Interface CLI ## Earliest failure stage Transport or result projection ## Relevant output or evidence - Expected source: `docs/rust-binaries.md:96-100` distinguishes the stored section range from the zlib stream length used for the ratio; `docs/rust-binaries.md:136-146` specifies the compressed-stream ratio and accepted PE padding. `src/rust/RustAuditableReader.ts:175-186` applies the post-decode bound to consumed compressed bytes. - Failure source: Executed public CLI output for the padded case records `section_bytes: 512` and `compressed_bytes: 83` alongside the limitation “inflated JSON to the smaller of 8 MiB and 64 times the section size.” `src/rust/RustBinaryProvider.ts:174` produces that sentence; the exact-size control returns identical wording when both sizes are 83. - Evidence provenance: observed CLI output; the stated ratio implementation is source-derived. - Local verification: reproduced using the complete inline script on the stated runtime. Both fixtures exited 0, with the sizes and limitation described above. - Reproduction completeness: complete for the successful-report wording defect on these synthetic inputs. ## Additional context Restoration check (proposed, unexecuted): repeat the inline reproduction and confirm that the padded successful report describes the 83-byte compressed stream as the ratio basis, while both fixtures continue to return their current package records and accurate section and compressed sizes. Preserve the existing resource bounds. The supplied open and closed issue inventory and matching full bodies contained no report of this successful limitation sentence. Closed #6793 concerns rejection of PE alignment padding, and closed #5556 concerns fixed-budget recovery advice; neither has this failure signal or restoration criterion. NOT_ENOUGH_INFO: no last-known-good release was runtime-tested, and occurrence in compiler-produced artifacts was not measured. ## Triage assessment - Impact level: P3 - Assessment status: supported - Impact basis: The successful report names stored section size as the ratio basis even though accepted padding is excluded by the reader. The reproduced issue changes wording only; correct metadata and successful inspection were observed. - Workaround status: available - Workaround basis: The same successful report provides `compressed_bytes: 83`; using the documented 64-times-stream rule gives 5312 bytes. No artifact modification or guard change is needed to interpret the limit correctly.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
morluto/rea#4371
No description provided.