[GH-ISSUE #6763] [Bug] ELF Go build metadata below the 1 MiB string limit is rejected as truncated #4120

Closed
opened 2026-10-31 00:46:58 +00:00 by bsakaguchi · 0 comments
Owner

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

Before submitting

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

Area

Native analysis or decompilation

Observed behavior

The production GoBinaryService(new GoBinaryProvider()) rejects a complete authored ELF buildinfo fixture containing 1,048,573 bytes of embedded string contents with invalid_request, reason invalid_format, and Go build-info string range is truncated. All bytes exist within the file, its load mapping, and its named .go.buildinfo section. The advertised aggregate allowance is 1,048,576 bytes. A 1,048,572-byte control succeeds, while the exact-limit 1,048,576-byte fixture also fails. Go's standard reader recognizes the version, main module and setting in each fixture.

This is an executed production service/provider reproduction with authored ELF buildinfo fixtures, not compiler-built executable programs. CLI/MCP execution and an unmodified compiler-produced trigger were not established.

Reproduction

From the checkout root with locked dependencies and Go available, save the following as /tmp/rea-go-budget-repro.mjs, then run node --import tsx /tmp/rea-go-budget-repro.mjs. It generates benign local metadata fixtures, invokes go version -m without executing them, and calls the production shared service. The inline reproducer ran once with the results below; earlier equivalent boundary probes were consistent. Its temporary directory can be removed afterward.

import { writeFile } from 'node:fs/promises';
import { join,resolve } from 'node:path';
import { pathToFileURL } from 'node:url';
import { mkdtempSync } from 'node:fs';
import { execFileSync } from 'node:child_process';
const { GoBinaryProvider } = await import(pathToFileURL(resolve('src/go/GoBinaryProvider.ts')).href);
const { GoBinaryService } = await import(pathToFileURL(resolve('src/application/go/GoBinaryService.ts')).href);
const { projectAnalysisError } = await import(pathToFileURL(resolve('src/domain/analysisErrorProjection.ts')).href);
const root=process.env.REA_REPRO_DIR ?? mkdtempSync('/tmp/rea-go-budget-'), limit=1048576;
function uvarint(n) { const a=[]; while(n>=128) {a.push((n&127)|128);n=Math.floor(n/128);}a.push(n);return Buffer.from(a); }
function elf(total) {
  const version=Buffer.from('go1.26.0');
  const prefix=Buffer.from('path\tapp\nmod\tapp\t(devel)\t\nbuild\tflag=');
  const module=Buffer.concat([Buffer.from('3077af0c9274080241e1c107e6d618e6','hex'),prefix,Buffer.alloc(total-version.length-prefix.length-33,120),Buffer.from('\n'),Buffer.from('f932433186182072008242104116d8f2','hex')]);
  const payload=Buffer.concat([uvarint(version.length),version,uvarint(module.length),module]);
  const b=Buffer.alloc(544+payload.length); b.set([127,69,76,70,2,1,1]);
  b.writeUInt16LE(2,16); b.writeUInt16LE(62,18); b.writeUInt32LE(1,20); b.writeBigUInt64LE(64n,32); b.writeUInt16LE(64,52); b.writeUInt16LE(56,54); b.writeUInt16LE(1,56); b.writeBigUInt64LE(128n,40); b.writeUInt16LE(64,58); b.writeUInt16LE(3,60); b.writeUInt16LE(1,62);
  const names=Buffer.from('\0.shstrtab\0.go.buildinfo\0'); names.copy(b,320); b.writeUInt32LE(1,192); b.writeUInt32LE(3,196); b.writeBigUInt64LE(320n,216); b.writeBigUInt64LE(BigInt(names.length),224); b.writeUInt32LE(11,256); b.writeUInt32LE(1,260); b.writeBigUInt64LE(3n,264); b.writeBigUInt64LE(0x400200n,272); b.writeBigUInt64LE(512n,280); b.writeBigUInt64LE(BigInt(32+payload.length),288); b.writeBigUInt64LE(16n,304);
  b.writeUInt32LE(1,64); b.writeUInt32LE(6,68);b.writeBigUInt64LE(0x400000n,80);b.writeBigUInt64LE(BigInt(b.length),96); b.writeBigUInt64LE(BigInt(b.length),104);b.writeBigUInt64LE(4096n,112);
  Buffer.from('ff20476f206275696c64696e663a','hex').copy(b,512);b[526]=8;b[527]=2;payload.copy(b,544);
  return {b,moduleBytes:module.length,prefixBytes:payload.length-total};
}
for(const total of [limit-4,limit-3,limit,limit+1]) {
 const {b,moduleBytes,prefixBytes}=elf(total),path=join(root,`budget-${total}.elf`);await writeFile(path,b);
 const reference=execFileSync('go',['version','-m',path],{encoding:'utf8',maxBuffer:2*1048576});
 const referenceRecognized=reference.split('\n')[0].endsWith(': go1.26.0') && reference.includes('\tmod\tapp\t(devel)');
 const service=new GoBinaryService(new GoBinaryProvider());
 try {const r=await service.inspect({path});if(r.ok){const n=r.value.normalized_result;console.log(JSON.stringify({total,prefixBytes,referenceRecognized,fileBytes:b.length,ok:true,moduleBytes,complete:n.build_info.module.complete,valueBytes:n.build_info.module.settings[0].value.length}));}else{const e=projectAnalysisError(r.error);console.log(JSON.stringify({total,prefixBytes,referenceRecognized,fileBytes:b.length,ok:false,code:e.code,issue:{reason:e.details.issues[0].reason,message:e.details.issues[0].message.replace(path,'fixture.elf')}}));}}
 finally{await service.close();}
}

Expected behavior

Admit valid embedded version and framed module string contents whose aggregate size is at or below 1 MiB, while retaining the allowance and rejecting oversized metadata with its typed resource failure. docs/go-binaries.md:164-169 and src/contracts/go/goToolContracts.ts:17 describe an aggregate embedded-string allowance. The explicit comparison at src/go/GoBinaryImage.ts:137-143 counts version.location.bytes + module.location.bytes; it excludes the varint prefixes. The passing control and standard-reader comparison distinguish present valid bytes from a genuinely truncated artifact.

Impact and scope

Supported ELF metadata near the documented boundary is rejected and incorrectly labeled malformed, so this inspection produces no Evidence. The reproduced failing in-budget totals are 1,048,573 and 1,048,576 bytes; this fixture uses four bytes of varint prefixes. No user incident, prevalence, compiler-built trigger, or broader-format failure was demonstrated. The Go command recovers the metadata, but an equivalent workaround yielding REA Evidence for the unchanged artifact was not verified.

REA version

Source manifest 6.7.0, commit source revision. The checkout source was tested; the published npm artifact was not executed.

Runtime and platform

Node v26.12.1; Linux 7.2.8-9-omarchy, x86_64; locked dependencies and tsx; reference command reports go version go1.27.3 linux/amd64. The embedded go1.26.0 string is authored fixture content, not attribution to that compiler.

Target and artifact context

Authored ELF64 little-endian buildinfo fixtures with a writable file-backed PT_LOAD, a 16-byte-aligned inline header, valid Go module framing, and a named .go.buildinfo section fully enclosing the header and strings. The failing 1,048,573-byte case is a 1,049,121-byte file. The large build\tflag=... record is fabricated to exercise the supported byte allowance. No target code runs.

Interface

Other

Earliest failure stage

Native analysis or reconstruction

Relevant output or evidence

Actual final inline-reproducer output:

{"total":1048572,"prefixBytes":4,"referenceRecognized":true,"fileBytes":1049120,"ok":true,"moduleBytes":1048564,"complete":true,"valueBytes":1048494}
{"total":1048573,"prefixBytes":4,"referenceRecognized":true,"fileBytes":1049121,"ok":false,"code":"invalid_request","issue":{"reason":"invalid_format","message":"Selected artifact fixture.elf: Go build-info string range is truncated"}}
{"total":1048576,"prefixBytes":4,"referenceRecognized":true,"fileBytes":1049124,"ok":false,"code":"invalid_request","issue":{"reason":"invalid_format","message":"Selected artifact fixture.elf: Go build-info string range is truncated"}}
{"total":1048577,"prefixBytes":4,"referenceRecognized":true,"fileBytes":1049125,"ok":false,"code":"invalid_request","issue":{"reason":"invalid_format","message":"Selected artifact fixture.elf: Go build-info string range is truncated"}}

referenceRecognized: true means go version -m exited successfully and reported the authored compiler version and main module. The reference pass also recovered the full setting value: 1,048,494 bytes for the passing control, 1,048,495 for the first failing case, and 1,048,498 at the exact allowance. The final reproduction's reference command is inline, and the generated files remain available for independent inspection.

Evidence provenance: observed. Local verification: reproduced. Reproduction completeness: complete at the production shared service/provider boundary. Public transport and unmodified compiler-produced reachability remain unverified. Source tracing shows the public CLI invokes the same service at src/cli/goCommands.ts:35-49; this is applicability evidence, not an executed CLI claim.

Typed outcome or recovery expected

The 1,048,572-byte control, 1,048,573-byte case and exact-limit case should produce parsed metadata while preserving their full source bytes. The 1,048,577-byte case is over budget and should receive the existing build-info resource refusal rather than success or a false truncation diagnosis. These are proposed restoration checks; no fix was attempted.

Analysis or suspected cause

Source-derived: inlineDataEnd at src/go/GoBinaryImage.ts:183-201 caps ELF inline source coverage at header + 32 + MAX_BUILD_INFO_BYTES, while readInlineString at lines 244-276 consumes varint prefixes in that coverage. The actual string-content allowance is checked separately at lines 137-143. Four prefix bytes therefore consume part of the advertised content allowance, and the preliminary cap turns an artificial boundary into an invalid_format failure before the aggregate check can run.

Additional context

The open-title corpus was consulted first. Open and closed searches included repo:morluto/rea is:issue in:title Go, repo:morluto/rea is:issue "Go" "varint", repo:morluto/rea is:issue "Go" "aggregate", and repo:morluto/rea is:issue "Go" "1 MiB". Closed #6716 concerns strings extending beyond the named discovery section; this fixture's section fully encloses all strings, so that independent byte-cap failure remains after the section-boundary correction. NOT_ENOUGH_INFO: introducing revision, real-world frequency, unmodified compiler-produced reproduction, and public CLI/MCP execution.

Triage assessment

  • Impact level: P2
  • Assessment status: supported
  • Impact basis: Valid authored metadata below the documented allowance is rejected at the production service boundary; the observed consequence is a bounded inspection failure and false malformed-input classification, without a demonstrated severe downstream incident.
  • Workaround status: unverified
  • Workaround basis: Go's standard reader recovered the same metadata, but no practical route producing equivalent REA Evidence from the unchanged artifact was verified.
Originally created by @coygeek on GitHub (Oct 23, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/6763 ## 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 Native analysis or decompilation ## Observed behavior The production `GoBinaryService(new GoBinaryProvider())` rejects a complete authored ELF buildinfo fixture containing 1,048,573 bytes of embedded string contents with `invalid_request`, reason `invalid_format`, and `Go build-info string range is truncated`. All bytes exist within the file, its load mapping, and its named `.go.buildinfo` section. The advertised aggregate allowance is 1,048,576 bytes. A 1,048,572-byte control succeeds, while the exact-limit 1,048,576-byte fixture also fails. Go's standard reader recognizes the version, main module and setting in each fixture. This is an executed production service/provider reproduction with authored ELF buildinfo fixtures, not compiler-built executable programs. CLI/MCP execution and an unmodified compiler-produced trigger were not established. ## Reproduction From the checkout root with locked dependencies and Go available, save the following as `/tmp/rea-go-budget-repro.mjs`, then run `node --import tsx /tmp/rea-go-budget-repro.mjs`. It generates benign local metadata fixtures, invokes `go version -m` without executing them, and calls the production shared service. The inline reproducer ran once with the results below; earlier equivalent boundary probes were consistent. Its temporary directory can be removed afterward. ```js import { writeFile } from 'node:fs/promises'; import { join,resolve } from 'node:path'; import { pathToFileURL } from 'node:url'; import { mkdtempSync } from 'node:fs'; import { execFileSync } from 'node:child_process'; const { GoBinaryProvider } = await import(pathToFileURL(resolve('src/go/GoBinaryProvider.ts')).href); const { GoBinaryService } = await import(pathToFileURL(resolve('src/application/go/GoBinaryService.ts')).href); const { projectAnalysisError } = await import(pathToFileURL(resolve('src/domain/analysisErrorProjection.ts')).href); const root=process.env.REA_REPRO_DIR ?? mkdtempSync('/tmp/rea-go-budget-'), limit=1048576; function uvarint(n) { const a=[]; while(n>=128) {a.push((n&127)|128);n=Math.floor(n/128);}a.push(n);return Buffer.from(a); } function elf(total) { const version=Buffer.from('go1.26.0'); const prefix=Buffer.from('path\tapp\nmod\tapp\t(devel)\t\nbuild\tflag='); const module=Buffer.concat([Buffer.from('3077af0c9274080241e1c107e6d618e6','hex'),prefix,Buffer.alloc(total-version.length-prefix.length-33,120),Buffer.from('\n'),Buffer.from('f932433186182072008242104116d8f2','hex')]); const payload=Buffer.concat([uvarint(version.length),version,uvarint(module.length),module]); const b=Buffer.alloc(544+payload.length); b.set([127,69,76,70,2,1,1]); b.writeUInt16LE(2,16); b.writeUInt16LE(62,18); b.writeUInt32LE(1,20); b.writeBigUInt64LE(64n,32); b.writeUInt16LE(64,52); b.writeUInt16LE(56,54); b.writeUInt16LE(1,56); b.writeBigUInt64LE(128n,40); b.writeUInt16LE(64,58); b.writeUInt16LE(3,60); b.writeUInt16LE(1,62); const names=Buffer.from('\0.shstrtab\0.go.buildinfo\0'); names.copy(b,320); b.writeUInt32LE(1,192); b.writeUInt32LE(3,196); b.writeBigUInt64LE(320n,216); b.writeBigUInt64LE(BigInt(names.length),224); b.writeUInt32LE(11,256); b.writeUInt32LE(1,260); b.writeBigUInt64LE(3n,264); b.writeBigUInt64LE(0x400200n,272); b.writeBigUInt64LE(512n,280); b.writeBigUInt64LE(BigInt(32+payload.length),288); b.writeBigUInt64LE(16n,304); b.writeUInt32LE(1,64); b.writeUInt32LE(6,68);b.writeBigUInt64LE(0x400000n,80);b.writeBigUInt64LE(BigInt(b.length),96); b.writeBigUInt64LE(BigInt(b.length),104);b.writeBigUInt64LE(4096n,112); Buffer.from('ff20476f206275696c64696e663a','hex').copy(b,512);b[526]=8;b[527]=2;payload.copy(b,544); return {b,moduleBytes:module.length,prefixBytes:payload.length-total}; } for(const total of [limit-4,limit-3,limit,limit+1]) { const {b,moduleBytes,prefixBytes}=elf(total),path=join(root,`budget-${total}.elf`);await writeFile(path,b); const reference=execFileSync('go',['version','-m',path],{encoding:'utf8',maxBuffer:2*1048576}); const referenceRecognized=reference.split('\n')[0].endsWith(': go1.26.0') && reference.includes('\tmod\tapp\t(devel)'); const service=new GoBinaryService(new GoBinaryProvider()); try {const r=await service.inspect({path});if(r.ok){const n=r.value.normalized_result;console.log(JSON.stringify({total,prefixBytes,referenceRecognized,fileBytes:b.length,ok:true,moduleBytes,complete:n.build_info.module.complete,valueBytes:n.build_info.module.settings[0].value.length}));}else{const e=projectAnalysisError(r.error);console.log(JSON.stringify({total,prefixBytes,referenceRecognized,fileBytes:b.length,ok:false,code:e.code,issue:{reason:e.details.issues[0].reason,message:e.details.issues[0].message.replace(path,'fixture.elf')}}));}} finally{await service.close();} } ``` ## Expected behavior Admit valid embedded version and framed module string contents whose aggregate size is at or below 1 MiB, while retaining the allowance and rejecting oversized metadata with its typed resource failure. `docs/go-binaries.md:164-169` and `src/contracts/go/goToolContracts.ts:17` describe an aggregate embedded-string allowance. The explicit comparison at `src/go/GoBinaryImage.ts:137-143` counts `version.location.bytes + module.location.bytes`; it excludes the varint prefixes. The passing control and standard-reader comparison distinguish present valid bytes from a genuinely truncated artifact. ## Impact and scope Supported ELF metadata near the documented boundary is rejected and incorrectly labeled malformed, so this inspection produces no Evidence. The reproduced failing in-budget totals are 1,048,573 and 1,048,576 bytes; this fixture uses four bytes of varint prefixes. No user incident, prevalence, compiler-built trigger, or broader-format failure was demonstrated. The Go command recovers the metadata, but an equivalent workaround yielding REA Evidence for the unchanged artifact was not verified. ## REA version Source manifest `6.7.0`, commit [source revision](https://github.com/morluto/rea/commit/2bcd7e6d13f0a8118d6619718254255e84f75d86). The checkout source was tested; the published npm artifact was not executed. ## Runtime and platform Node `v26.12.1`; Linux `7.2.8-9-omarchy`, x86_64; locked dependencies and `tsx`; reference command reports `go version go1.27.3 linux/amd64`. The embedded `go1.26.0` string is authored fixture content, not attribution to that compiler. ## Target and artifact context Authored ELF64 little-endian buildinfo fixtures with a writable file-backed `PT_LOAD`, a 16-byte-aligned inline header, valid Go module framing, and a named `.go.buildinfo` section fully enclosing the header and strings. The failing 1,048,573-byte case is a 1,049,121-byte file. The large `build\tflag=...` record is fabricated to exercise the supported byte allowance. No target code runs. ## Interface Other ## Earliest failure stage Native analysis or reconstruction ## Relevant output or evidence Actual final inline-reproducer output: ```jsonl {"total":1048572,"prefixBytes":4,"referenceRecognized":true,"fileBytes":1049120,"ok":true,"moduleBytes":1048564,"complete":true,"valueBytes":1048494} {"total":1048573,"prefixBytes":4,"referenceRecognized":true,"fileBytes":1049121,"ok":false,"code":"invalid_request","issue":{"reason":"invalid_format","message":"Selected artifact fixture.elf: Go build-info string range is truncated"}} {"total":1048576,"prefixBytes":4,"referenceRecognized":true,"fileBytes":1049124,"ok":false,"code":"invalid_request","issue":{"reason":"invalid_format","message":"Selected artifact fixture.elf: Go build-info string range is truncated"}} {"total":1048577,"prefixBytes":4,"referenceRecognized":true,"fileBytes":1049125,"ok":false,"code":"invalid_request","issue":{"reason":"invalid_format","message":"Selected artifact fixture.elf: Go build-info string range is truncated"}} ``` `referenceRecognized: true` means `go version -m` exited successfully and reported the authored compiler version and main module. The reference pass also recovered the full setting value: 1,048,494 bytes for the passing control, 1,048,495 for the first failing case, and 1,048,498 at the exact allowance. The final reproduction's reference command is inline, and the generated files remain available for independent inspection. Evidence provenance: observed. Local verification: reproduced. Reproduction completeness: complete at the production shared service/provider boundary. Public transport and unmodified compiler-produced reachability remain unverified. Source tracing shows the public CLI invokes the same service at `src/cli/goCommands.ts:35-49`; this is applicability evidence, not an executed CLI claim. ## Typed outcome or recovery expected The 1,048,572-byte control, 1,048,573-byte case and exact-limit case should produce parsed metadata while preserving their full source bytes. The 1,048,577-byte case is over budget and should receive the existing build-info resource refusal rather than success or a false truncation diagnosis. These are proposed restoration checks; no fix was attempted. ## Analysis or suspected cause Source-derived: `inlineDataEnd` at `src/go/GoBinaryImage.ts:183-201` caps ELF inline source coverage at `header + 32 + MAX_BUILD_INFO_BYTES`, while `readInlineString` at lines 244-276 consumes varint prefixes in that coverage. The actual string-content allowance is checked separately at lines 137-143. Four prefix bytes therefore consume part of the advertised content allowance, and the preliminary cap turns an artificial boundary into an `invalid_format` failure before the aggregate check can run. ## Additional context The open-title corpus was consulted first. Open and closed searches included `repo:morluto/rea is:issue in:title Go`, `repo:morluto/rea is:issue "Go" "varint"`, `repo:morluto/rea is:issue "Go" "aggregate"`, and `repo:morluto/rea is:issue "Go" "1 MiB"`. Closed [#6716](https://github.com/morluto/rea/issues/6716) concerns strings extending beyond the named discovery section; this fixture's section fully encloses all strings, so that independent byte-cap failure remains after the section-boundary correction. NOT_ENOUGH_INFO: introducing revision, real-world frequency, unmodified compiler-produced reproduction, and public CLI/MCP execution. ## Triage assessment - Impact level: P2 - Assessment status: supported - Impact basis: Valid authored metadata below the documented allowance is rejected at the production service boundary; the observed consequence is a bounded inspection failure and false malformed-input classification, without a demonstrated severe downstream incident. - Workaround status: unverified - Workaround basis: Go's standard reader recovered the same metadata, but no practical route producing equivalent REA Evidence from the unchanged artifact was verified.
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#4120
No description provided.