[GH-ISSUE #6517] [Bug] BEAM inspection rejects nonzero chunk-alignment bytes accepted by Erlang #3910

Closed
opened 2026-10-31 00:45:10 +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/6517

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

Source-only finding: inspect-erlang-beam rejects an otherwise in-range FOR1/BEAM container when any byte between a chunk's declared payload end and the next four-byte boundary is nonzero. The parser throws BEAM chunk padding is non-zero. before returning chunk or atom facts. The provider maps this to a path / invalid_format input error.

This rejects alignment bytes that Erlang's own chunk readers skip without interpreting. No runtime reproduction was performed.

Reproduction

Proposed, not run. This small structural fixture has one AtU8 chunk containing the atom m. Both variants have identical declared sizes, payload, and chunk boundary; only the two alignment bytes at offsets 26 and 27 differ. It is an inspection fixture, not a complete executable module.

from pathlib import Path
prefix = bytes.fromhex(
    '464f5231 00000014 4245414d'  # FOR1, 20-byte form, BEAM
    '41745538 00000006'           # AtU8, six payload bytes
    '00000001 01 6d'              # one atom, one byte, m
)
Path('padding-zero.beam').write_bytes(prefix + b'\x00\x00')
Path('padding-nonzero.beam').write_bytes(prefix + b'\x7f\x01')

Proposed CLI comparison:

rea inspect-erlang-beam padding-zero.beam --json
rea inspect-erlang-beam padding-nonzero.beam --json

The source predicts that the first produces one atom named m, while the second takes the explicit nonzero-padding failure branch. To exercise a compiler-produced module instead, change only existing alignment bytes in a copy of a BEAM file; do not change its chunk headers or payloads. Neither comparison was executed. Frequency in real artifacts: NOT_ENOUGH_INFO; no artifact corpus was measured.

Expected behavior

Inspect the same declared chunk payloads regardless of alignment-byte values, while continuing to reject missing alignment bytes or ranges outside the form.

REA documents structural chunk and atom inspection and payload hashes and table facts. In the published OTP 29 implementation, the loader advances over storage alignment without examining those bytes. The independent beam_lib scanner also computes the next aligned position and reads only the declared payload. These source contracts support keeping the padding outside payload validation; no Erlang runtime was invoked.

Impact and scope

A bounded compatibility failure prevents all structural results for a file containing any nonzero chunk-alignment byte. Payloads, hashes, and table facts remain readable under the format owner's scanning rules. The affected input class is source-derived; prevalence, actual user failures, and other platforms are NOT_ENOUGH_INFO. Provisional P2. Normalizing alignment bytes in a separate artifact copy is a possible workaround, but it was not tested and changes the artifact digest.

REA version

Source revision 49c9c9d4a14cc7d5509ec28a304dab48f85cb045 (main; package.json says 6.7.0). The parser file is absent from the supplied published-release commit 27dc42d10249f0410904a75c0997842eb03b931c (tag rea-agents-6.7.0). This report does not claim that the published package is affected.

Runtime and platform

NOT_ENOUGH_INFO: no REA or Erlang runtime was executed for this source-only finding; runtime/platform-specific behavior was not tested. No provider integration or target execution is required for the proposed structural check.

Target and artifact context

A 28-byte synthetic FOR1/BEAM form with one six-byte, pre-OTP-28-style AtU8 payload and two alignment bytes. The defect applies at generic chunk framing, before compact atom-length decoding.

Interface

CLI

Earliest failure stage

Native analysis or reconstruction

Relevant output or evidence

No runtime output is available. Direct source inspection established:

Evidence provenance: source-derived. Local verification: source inspection only. Reproduction completeness: proposed input and commands supplied, not run. Installed-release behavior and corpus frequency remain unknown.

Additional context

Open and closed issue searches found no matching report. Related open #6503 concerns extended compact atom-length decoding; this report uses ordinary short atom names and concerns a separate chunk-framing rule.

Triage assessment

  • Impact level: P2
  • Assessment status: provisional
  • Impact basis: The source has an unconditional whole-inspection refusal for a bounded alignment-byte representation that OTP's published chunk scanners ignore; no runtime reproduction or affected real-world artifact was observed.
  • Workaround status: unverified
  • Workaround basis: A separate copy with only alignment bytes normalized should preserve chunk payloads, but that procedure was not run and it changes the selected artifact's digest.
Originally created by @coygeek on GitHub (Oct 23, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/6517 ### 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 Source-only finding: `inspect-erlang-beam` rejects an otherwise in-range `FOR1`/`BEAM` container when any byte between a chunk's declared payload end and the next four-byte boundary is nonzero. The parser throws `BEAM chunk padding is non-zero.` before returning chunk or atom facts. The provider maps this to a `path` / `invalid_format` input error. This rejects alignment bytes that Erlang's own chunk readers skip without interpreting. No runtime reproduction was performed. ### Reproduction Proposed, not run. This small structural fixture has one `AtU8` chunk containing the atom `m`. Both variants have identical declared sizes, payload, and chunk boundary; only the two alignment bytes at offsets 26 and 27 differ. It is an inspection fixture, not a complete executable module. ```python from pathlib import Path prefix = bytes.fromhex( '464f5231 00000014 4245414d' # FOR1, 20-byte form, BEAM '41745538 00000006' # AtU8, six payload bytes '00000001 01 6d' # one atom, one byte, m ) Path('padding-zero.beam').write_bytes(prefix + b'\x00\x00') Path('padding-nonzero.beam').write_bytes(prefix + b'\x7f\x01') ``` Proposed CLI comparison: ```sh rea inspect-erlang-beam padding-zero.beam --json rea inspect-erlang-beam padding-nonzero.beam --json ``` The source predicts that the first produces one atom named `m`, while the second takes the explicit nonzero-padding failure branch. To exercise a compiler-produced module instead, change only existing alignment bytes in a copy of a BEAM file; do not change its chunk headers or payloads. Neither comparison was executed. Frequency in real artifacts: `NOT_ENOUGH_INFO`; no artifact corpus was measured. ### Expected behavior Inspect the same declared chunk payloads regardless of alignment-byte values, while continuing to reject missing alignment bytes or ranges outside the form. REA documents [structural chunk and atom inspection](https://github.com/morluto/rea/blob/49c9c9d4a14cc7d5509ec28a304dab48f85cb045/docs/erlang-beam.md#L3-L7) and [payload hashes and table facts](https://github.com/morluto/rea/blob/49c9c9d4a14cc7d5509ec28a304dab48f85cb045/docs/erlang-beam.md#L23-L36). In the published OTP 29 implementation, [the loader advances over storage alignment without examining those bytes](https://github.com/erlang/otp/blob/550d7b7898706c7822362c42e7b93120c1d1f29a/erts/emulator/beam/beam_file.c#L1447-L1460). The independent [`beam_lib` scanner also computes the next aligned position and reads only the declared payload](https://github.com/erlang/otp/blob/550d7b7898706c7822362c42e7b93120c1d1f29a/lib/stdlib/src/beam_lib.erl#L901-L919). These source contracts support keeping the padding outside payload validation; no Erlang runtime was invoked. ### Impact and scope A bounded compatibility failure prevents all structural results for a file containing any nonzero chunk-alignment byte. Payloads, hashes, and table facts remain readable under the format owner's scanning rules. The affected input class is source-derived; prevalence, actual user failures, and other platforms are `NOT_ENOUGH_INFO`. Provisional P2. Normalizing alignment bytes in a separate artifact copy is a possible workaround, but it was not tested and changes the artifact digest. ### REA version Source revision `49c9c9d4a14cc7d5509ec28a304dab48f85cb045` (`main`; package.json says 6.7.0). The parser file is absent from the supplied published-release commit `27dc42d10249f0410904a75c0997842eb03b931c` (tag `rea-agents-6.7.0`). This report does not claim that the published package is affected. ### Runtime and platform `NOT_ENOUGH_INFO`: no REA or Erlang runtime was executed for this source-only finding; runtime/platform-specific behavior was not tested. No provider integration or target execution is required for the proposed structural check. ### Target and artifact context A 28-byte synthetic `FOR1`/`BEAM` form with one six-byte, pre-OTP-28-style `AtU8` payload and two alignment bytes. The defect applies at generic chunk framing, before compact atom-length decoding. ### Interface CLI ### Earliest failure stage Native analysis or reconstruction ### Relevant output or evidence No runtime output is available. Direct source inspection established: - [The range/alignment branch](https://github.com/morluto/rea/blob/49c9c9d4a14cc7d5509ec28a304dab48f85cb045/src/erlang/BeamParser.ts#L189-L198) first validates that padding fits, then independently rejects its values: ```ts const padding = bytes.subarray(payloadOffset + size, padded); if (padding.some((byte) => byte !== 0)) fail("BEAM chunk padding is non-zero."); ``` - [The production provider invokes this parser](https://github.com/morluto/rea/blob/49c9c9d4a14cc7d5509ec28a304dab48f85cb045/src/erlang/BeamProvider.ts#L64-L83), and [maps a format failure to an invalid-format input error](https://github.com/morluto/rea/blob/49c9c9d4a14cc7d5509ec28a304dab48f85cb045/src/erlang/BeamProvider.ts#L152-L159). Evidence provenance: source-derived. Local verification: source inspection only. Reproduction completeness: proposed input and commands supplied, not run. Installed-release behavior and corpus frequency remain unknown. ### Additional context Open and closed issue searches found no matching report. Related open [#6503](https://github.com/morluto/rea/issues/6503) concerns extended compact atom-length decoding; this report uses ordinary short atom names and concerns a separate chunk-framing rule. ## Triage assessment - Impact level: P2 - Assessment status: provisional - Impact basis: The source has an unconditional whole-inspection refusal for a bounded alignment-byte representation that OTP's published chunk scanners ignore; no runtime reproduction or affected real-world artifact was observed. - Workaround status: unverified - Workaround basis: A separate copy with only alignment bytes normalized should preserve chunk payloads, but that procedure was not run and it changes the selected artifact's digest.
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#3910
No description provided.