Skip to content

[BUG] Silent opcode offset truncation #97

@alnoki

Description

@alnoki

@deanmlittle @clairechingching @bidhan-a

2026-01-14 EDIT: Per #97 (comment), correct description offset type to i16, and add a section about LLVM

Snippet

    stxdw [r3 + 100000000000000000], r4

Description

This assembles, even though the SBPF spec stipulates u16 i16 offsets. The culprit appears to be silent truncation via the internal casting process, e.g. in this case the offset gets silently cast to 0x0

Why this is a problem

Once an instruction requires more than 6 3 accounts, hard-coded offsets relative to the start of the input buffer (r1) will exceed U16_MAX = 65535 I16_MAX = 32_767 even if all accounts have no data. This is due to the minimum 10240 bytes of account data reallocation padding.

If an sbpf user prepares .equ-style offsets using a Rust script or similar, they'll get no feedback about the offsets getting truncated, and will experience undefined behavior in the resultant program.

Regarding LLVM

If LLVM silently truncates, it is implementing a massive footgun that will lead to undefined behavior that can easily be prevented. Absent any strong argument to the contrary, I submit that with regard to silent offset truncation LLVM is itself broken and should be fixed. Assuming this, there is no merit to feature parity for the sake of feature parity if it means copying a broken implementation

Expected behavior

Some kind of error message that says offsets must fit in a u16 offsets must fit in an i16 and panics the assembler

Metadata

Metadata

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions