[GH-ISSUE #5718] [Bug] inspect-binary-layout allocates the declared BSS and fails on a small valid ELF #3466

Closed
opened 2026-10-31 00:40:47 +00:00 by bsakaguchi · 2 comments
Owner

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

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

inspect-binary-layout exits 1 with a memory resource_constraint on a valid 15,992-byte ELF64 x86-64 PIE that reserves slightly more than 3 GiB of BSS. It returns no layout Evidence. The executable runs successfully, and GNU readelf, objdump and nm read it successfully. A small-BSS control succeeds in REA.

An independent baseline reproduction and direct adapter traceback establish an attempted zero-fill allocation during pwntools' automatic kernel-configuration search. The resource error correctly describes the resulting allocation failure; the defect is the avoidable allocation during offline metadata inspection.

Reproduction

On Linux x64, use the built source checkout and its documented pinned Python provider profile. Set REA_PWNTOOLS_PYTHON to that environment's absolute Python executable, then run from the checkout root:

work_dir="$(mktemp -d)"
pwntools_python="${REA_PWNTOOLS_PYTHON:?Set the absolute pinned Python executable}"
mkdir -p "$work_dir/home" "$work_dir/cfg" "$work_dir/data" \
  "$work_dir/cache" "$work_dir/state" "$work_dir/tmp"
cat > "$work_dir/large_bss.c" <<'C'
#include <stdio.h>
#ifndef GIB
#define GIB 3UL
#endif
char big[GIB * 1024 * 1024 * 1024 + 1];
int main(void) {
    big[0] = 1;
    big[sizeof(big) - 1] = 2;
    printf("%d\n", big[0] + big[sizeof(big) - 1]);
    return 0;
}
C
gcc -O1 "$work_dir/large_bss.c" -o "$work_dir/large_bss"
"$work_dir/large_bss"
readelf -lW "$work_dir/large_bss"
env -i PATH="$PATH" HOME="$work_dir/home" XDG_CONFIG_HOME="$work_dir/cfg" \
  XDG_DATA_HOME="$work_dir/data" XDG_CACHE_HOME="$work_dir/cache" \
  XDG_STATE_HOME="$work_dir/state" TMPDIR="$work_dir/tmp" \
  REA_LOG_LEVEL=silent REA_PWNTOOLS_PYTHON="$pwntools_python" \
  node scripts/rea.mjs inspect-binary-layout "$work_dir/large_bss" --json

The executable prints 3; the final command exits 1. The independently executed controls used -DGIB=2UL and -DGIB=0UL. Both large variants failed; the small control returned complete layout Evidence. Each size had one CLI attempt. All three files were 15,992 bytes, ran successfully, and passed readelf -aW, objdump -h -x and nm. The small control prints 4 because both writes address the same byte.

Expected behavior

Return the supported ELF's section and segment metadata under the existing worker bounds without allocating its declared zero-filled runtime memory. docs/binary-diagnostics.md, Initial profile and Interpreting results, covers ELF64 x86-64 EXEC/DYN/REL and NOBITS sections without file bytes. src/contracts/native/binaryDiagnosticsToolContracts.ts exposes inspect_binary_layout. The repository's Tool and Test Changes guidance requires accounting for representation expansion before allocation.

This expectation concerns avoiding unnecessary allocation. It does not require arbitrary ELF inspection to succeed regardless of documented resource limits.

Impact and scope

P2. A bounded offline-inspection failure affects a specific valid ELF input class despite its small file size. GNU readelf, objdump and nm provide a verified fallback for raw metadata, but do not produce REA Evidence envelopes. No data mutation or security-boundary violation was observed. Other sizes, timing, peak RSS and population failure rates were not measured.

REA version

rea-agents 6.7.0; independently verified source baseline 9d8e7803326a382cbbb3ffdb900f5e93e5442d68. Verified at baseline; main source-checked only. Fetched origin/main at 84c89d1107cda017509bc3cd851573d073f9906d; no intervening changes in the cited layout implementation, decoder runtime, public contract or contract documentation. No current-main runtime reproduction is claimed.

Runtime and platform

Verified runtime: Linux amd64 container, Node.js v24.22.0, gcc 12.2.0, pwntools 4.15.0, pyelftools 0.33 and Unicorn 2.1.2. The documented pinned provider packages were preserved. Submission host: Node.js v26.12.0, macOS 27.0.1, arm64; the failing provider was not run natively on that host.

Target and artifact context

Self-built valid ELF64 x86-64 little-endian PIE, 15,992 bytes. In the 3-GiB-plus-one fixture, the writable LOAD has virtual address 0x3dd0, file size 0x248, memory size 0xc0000278, and RW permissions. Its .bss is NOBITS with size 0xc0000028.

Interface

CLI

Earliest failure stage

Native analysis or reconstruction

Relevant output or evidence

Both large fixtures exit 1 with this relevant JSON subset:

{
  "code": "resource_constraint",
  "category": "resource_constraint",
  "details": {
    "operation": "inspect_binary_layout",
    "resource": "memory",
    "reason": "pwntools memory allocation failed under the effective resource limits; the exact allocation cause is unknown.",
    "reported_limits": {
      "address_space_bytes": 3221225472,
      "cpu_seconds": 30,
      "file_size_bytes": 67108864
    },
    "captured_output": {"stdout": "", "stderr": "", "truncated": false}
  }
}

A separate direct call to the unchanged inspect_elf with the same address-space bound produced this traceback, with environment-specific path prefixes omitted:

bridge/pwntools/layout_impl.py:170, in inspect_elf
    image = LayoutELF(str(path), checksec=False)
pwnlib/elf/elf.py:302, in __init__
    for start in self.search(IKCFG_ST):
pwnlib/elf/elf.py:1287, in search
    data += b'\x00' * zeroed
MemoryError

The independent verifier matched source hashes for the layout implementation, decoder runtime and public contract between the Linux image and baseline checkout. The image lacked Git metadata, so its HEAD was not asserted. Evidence provenance is observed, with independent baseline reproduction; main was checked through source history only.

Typed outcome or recovery expected

Return complete layout Evidence for the unchanged large fixtures, including their declared memory sizes and NOBITS sections with no file backing. Preserve the small-BSS control and genuine allocation-failure classification. Raising the worker memory bound, dropping layout facts or relabeling the actual MemoryError would not establish restoration.

Analysis or suspected cause

Source-derived reasoning, supported by the direct traceback: bridge/pwntools/layout_impl.py:170 constructs LayoutELF before extracting metadata. The allocation occurs inside the bundled provider dependency Gallopsled/pwntools, whose ELF initializer automatically searches for IKCFG_ST. Its search implementation materializes the segment's zero-fill gap. This kernel-config search is unnecessary for returning section and segment sizes. bridge/pwntools/decoder_runtime.py:44 correctly maps the resulting MemoryError to the bounded resource failure.

Additional context

Prepared with AI assistance and an independent verifier. No earlier known-good version or successful restoration has been established. Related #2446 and merged #2486 concern large file-input admission; open #2676 proposes another configurable input limit. This fixture is already well below the default input bound, and its failure occurs during provider initialization.

Related #5715 concerns an unterminated IKCFG_ST marker raising StopIteration. This large-BSS fixture needs no marker bytes and fails during zero-gap allocation. Catching the marker exception would not restore this case; avoiding zero-gap allocation would not by itself handle an unterminated marker.

Originally created by @coygeek on GitHub (Oct 20, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/5718 ### 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 `inspect-binary-layout` exits 1 with a memory `resource_constraint` on a valid 15,992-byte ELF64 x86-64 PIE that reserves slightly more than 3 GiB of BSS. It returns no layout Evidence. The executable runs successfully, and GNU readelf, objdump and nm read it successfully. A small-BSS control succeeds in REA. An independent baseline reproduction and direct adapter traceback establish an attempted zero-fill allocation during pwntools' automatic kernel-configuration search. The resource error correctly describes the resulting allocation failure; the defect is the avoidable allocation during offline metadata inspection. ### Reproduction On Linux x64, use the built source checkout and its documented pinned Python provider profile. Set `REA_PWNTOOLS_PYTHON` to that environment's absolute Python executable, then run from the checkout root: ```sh work_dir="$(mktemp -d)" pwntools_python="${REA_PWNTOOLS_PYTHON:?Set the absolute pinned Python executable}" mkdir -p "$work_dir/home" "$work_dir/cfg" "$work_dir/data" \ "$work_dir/cache" "$work_dir/state" "$work_dir/tmp" cat > "$work_dir/large_bss.c" <<'C' #include <stdio.h> #ifndef GIB #define GIB 3UL #endif char big[GIB * 1024 * 1024 * 1024 + 1]; int main(void) { big[0] = 1; big[sizeof(big) - 1] = 2; printf("%d\n", big[0] + big[sizeof(big) - 1]); return 0; } C gcc -O1 "$work_dir/large_bss.c" -o "$work_dir/large_bss" "$work_dir/large_bss" readelf -lW "$work_dir/large_bss" env -i PATH="$PATH" HOME="$work_dir/home" XDG_CONFIG_HOME="$work_dir/cfg" \ XDG_DATA_HOME="$work_dir/data" XDG_CACHE_HOME="$work_dir/cache" \ XDG_STATE_HOME="$work_dir/state" TMPDIR="$work_dir/tmp" \ REA_LOG_LEVEL=silent REA_PWNTOOLS_PYTHON="$pwntools_python" \ node scripts/rea.mjs inspect-binary-layout "$work_dir/large_bss" --json ``` The executable prints `3`; the final command exits 1. The independently executed controls used `-DGIB=2UL` and `-DGIB=0UL`. Both large variants failed; the small control returned complete layout Evidence. Each size had one CLI attempt. All three files were 15,992 bytes, ran successfully, and passed `readelf -aW`, `objdump -h -x` and `nm`. The small control prints `4` because both writes address the same byte. ### Expected behavior Return the supported ELF's section and segment metadata under the existing worker bounds without allocating its declared zero-filled runtime memory. `docs/binary-diagnostics.md`, Initial profile and Interpreting results, covers ELF64 x86-64 EXEC/DYN/REL and NOBITS sections without file bytes. `src/contracts/native/binaryDiagnosticsToolContracts.ts` exposes `inspect_binary_layout`. The repository's Tool and Test Changes guidance requires accounting for representation expansion before allocation. This expectation concerns avoiding unnecessary allocation. It does not require arbitrary ELF inspection to succeed regardless of documented resource limits. ### Impact and scope P2. A bounded offline-inspection failure affects a specific valid ELF input class despite its small file size. GNU readelf, objdump and nm provide a verified fallback for raw metadata, but do not produce REA Evidence envelopes. No data mutation or security-boundary violation was observed. Other sizes, timing, peak RSS and population failure rates were not measured. ### REA version `rea-agents` 6.7.0; independently verified source baseline `9d8e7803326a382cbbb3ffdb900f5e93e5442d68`. Verified at baseline; main source-checked only. Fetched `origin/main` at `84c89d1107cda017509bc3cd851573d073f9906d`; no intervening changes in the cited layout implementation, decoder runtime, public contract or contract documentation. No current-main runtime reproduction is claimed. ### Runtime and platform Verified runtime: Linux amd64 container, Node.js v24.22.0, gcc 12.2.0, pwntools 4.15.0, pyelftools 0.33 and Unicorn 2.1.2. The documented pinned provider packages were preserved. Submission host: Node.js v26.12.0, macOS 27.0.1, arm64; the failing provider was not run natively on that host. ### Target and artifact context Self-built valid ELF64 x86-64 little-endian PIE, 15,992 bytes. In the 3-GiB-plus-one fixture, the writable LOAD has virtual address `0x3dd0`, file size `0x248`, memory size `0xc0000278`, and RW permissions. Its `.bss` is NOBITS with size `0xc0000028`. ### Interface CLI ### Earliest failure stage Native analysis or reconstruction ### Relevant output or evidence Both large fixtures exit 1 with this relevant JSON subset: ```json { "code": "resource_constraint", "category": "resource_constraint", "details": { "operation": "inspect_binary_layout", "resource": "memory", "reason": "pwntools memory allocation failed under the effective resource limits; the exact allocation cause is unknown.", "reported_limits": { "address_space_bytes": 3221225472, "cpu_seconds": 30, "file_size_bytes": 67108864 }, "captured_output": {"stdout": "", "stderr": "", "truncated": false} } } ``` A separate direct call to the unchanged `inspect_elf` with the same address-space bound produced this traceback, with environment-specific path prefixes omitted: ```text bridge/pwntools/layout_impl.py:170, in inspect_elf image = LayoutELF(str(path), checksec=False) pwnlib/elf/elf.py:302, in __init__ for start in self.search(IKCFG_ST): pwnlib/elf/elf.py:1287, in search data += b'\x00' * zeroed MemoryError ``` The independent verifier matched source hashes for the layout implementation, decoder runtime and public contract between the Linux image and baseline checkout. The image lacked Git metadata, so its HEAD was not asserted. Evidence provenance is observed, with independent baseline reproduction; main was checked through source history only. ### Typed outcome or recovery expected Return complete layout Evidence for the unchanged large fixtures, including their declared memory sizes and NOBITS sections with no file backing. Preserve the small-BSS control and genuine allocation-failure classification. Raising the worker memory bound, dropping layout facts or relabeling the actual MemoryError would not establish restoration. ### Analysis or suspected cause Source-derived reasoning, supported by the direct traceback: `bridge/pwntools/layout_impl.py:170` constructs `LayoutELF` before extracting metadata. The allocation occurs inside the bundled provider dependency [Gallopsled/pwntools](https://github.com/Gallopsled/pwntools), whose ELF initializer automatically searches for `IKCFG_ST`. Its search implementation materializes the segment's zero-fill gap. This kernel-config search is unnecessary for returning section and segment sizes. `bridge/pwntools/decoder_runtime.py:44` correctly maps the resulting MemoryError to the bounded resource failure. ### Additional context Prepared with AI assistance and an independent verifier. No earlier known-good version or successful restoration has been established. Related #2446 and merged #2486 concern large file-input admission; open #2676 proposes another configurable input limit. This fixture is already well below the default input bound, and its failure occurs during provider initialization. Related #5715 concerns an unterminated `IKCFG_ST` marker raising StopIteration. This large-BSS fixture needs no marker bytes and fails during zero-gap allocation. Catching the marker exception would not restore this case; avoiding zero-gap allocation would not by itself handle an unterminated marker.
Author
Owner

@matbrgz commented on GitHub (Oct 21, 2026):

Cross-referencing with canonical issue #5715 (inspect-binary-layout fails on a valid ELF containing IKCFG_ST) and sibling ELF binary layout reports #5716, #5717.

Consolidated under Cluster CC (ELF Binary Layout Inspection & Section Allocation Bounds) in tracker #4330.

<!-- gh-comment-id:6304919453 --> @matbrgz commented on GitHub (Oct 21, 2026): Cross-referencing with canonical issue #5715 (`inspect-binary-layout fails on a valid ELF containing IKCFG_ST`) and sibling ELF binary layout reports #5716, #5717. Consolidated under **Cluster CC (ELF Binary Layout Inspection & Section Allocation Bounds)** in tracker #4330.
Author
Owner

@coygeek commented on GitHub (Oct 24, 2026):

Verified resolved on main at d87e73f2db.

The existing verifier's large virtual zero-tail fixture and its control both succeed through the public CLI and production Python decoder on Linux x64 under a 96 MiB address-space allowance. The original large-BSS fixture and small-BSS control also succeed under that allowance. The 16,000-byte large-BSS input retains its declared .bss size 0xc0000028 and file_backing: "none"; structural facts and input digests remain intact. The structural adapter now suppresses unrelated pwntools virtual-memory searches. No fixture was executed, and this check did not use MCP.

The checks used pinned Node 24.22.1 and pwntools 4.15.0. Relevant implementation: layout_impl.py, layout_impl.py.

Closing as completed on main.

<!-- gh-comment-id:6380786698 --> @coygeek commented on GitHub (Oct 24, 2026): Verified resolved on `main` at d87e73f2db50be72d33a4b3c7199af35518b441c. The existing verifier's large virtual zero-tail fixture and its control both succeed through the public CLI and production Python decoder on Linux x64 under a 96 MiB address-space allowance. The original large-BSS fixture and small-BSS control also succeed under that allowance. The 16,000-byte large-BSS input retains its declared `.bss` size `0xc0000028` and `file_backing: "none"`; structural facts and input digests remain intact. The structural adapter now suppresses unrelated pwntools virtual-memory searches. No fixture was executed, and this check did not use MCP. The checks used pinned Node 24.22.1 and pwntools 4.15.0. Relevant implementation: [layout_impl.py](https://github.com/morluto/rea/blob/d87e73f2db50be72d33a4b3c7199af35518b441c/bridge/pwntools/layout_impl.py#L157), [layout_impl.py](https://github.com/morluto/rea/blob/d87e73f2db50be72d33a4b3c7199af35518b441c/bridge/pwntools/layout_impl.py#L199). Closing as completed on main.
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#3466
No description provided.