Skip to content

Fix bitfields spanning nine storage bytes - #3490

Open
tamird wants to merge 1 commit into
rust-lang:mainfrom
tamird:fix-bitfield-nine-byte-access
Open

tamird wants to merge 1 commit into
rust-lang:mainfrom
tamird:fix-bitfield-nine-byte-access

Conversation

@tamird

@tamird tamird commented Sep 15, 2026

Copy link
Copy Markdown
Contributor

496817f replaced bit-at-a-time access with byte loops that assemble
the field in a u64. A valid 64-bit field starting one bit into storage
spans nine bytes, so get(1, 64) and set(1, 64, value) shift by 64 on the
last iteration. The setter also discards the high bit when aligning the
value. The existing full-word regression test covered aligned fields and
fields ending at bit 64, leaving this crossing case untested.

Handle the ninth byte separately, after shifting the first word on reads
and before shifting away the high bits on writes. Share the read and
write implementations across runtime, raw-pointer, and const-generic
accessors instead of maintaining separate usize and u64 algorithms. The
const-generic wrappers pass their constants into the inlineable helpers,
and the getters remain usable in constants.

Store byte-aligned 64-bit fields directly with write_unaligned. Such
fields use native byte order and need no read-modify-write. This keeps
AArch64 code generation to a single store instead of vectorizing eight
byte extractions into shifts, shuffles, and constant-pool loads.

Use byte pointers without creating references to the whole storage, so
raw access can leave neighboring bytes uninitialized. Check the field's
bounds before accessing storage, including in release builds, to
preserve the safe accessors' bounds checking and reject invalid writes
before modifying any bytes.

Replace comparisons between accessors sharing the same algorithm with
bit-at-a-time expected values. Cover narrow and full-width fields at
every intra-byte offset, preservation of neighboring bits, constant
evaluation, indirect storage, and bounds failures. Enable this coverage
on both endiannesses while retaining the older little-endian-specific
cases behind their existing condition.

496817f replaced bit-at-a-time access with byte loops that assemble
the field in a u64. A valid 64-bit field starting one bit into storage
spans nine bytes, so get(1, 64) and set(1, 64, value) shift by 64 on the
last iteration. The setter also discards the high bit when aligning the
value. The existing full-word regression test covered aligned fields and
fields ending at bit 64, leaving this crossing case untested.

Handle the ninth byte separately, after shifting the first word on reads
and before shifting away the high bits on writes. Share the read and
write implementations across runtime, raw-pointer, and const-generic
accessors instead of maintaining separate usize and u64 algorithms. The
const-generic wrappers pass their constants into the inlineable helpers,
and the getters remain usable in constants.

Store byte-aligned 64-bit fields directly with write_unaligned. Such
fields use native byte order and need no read-modify-write. This keeps
AArch64 code generation to a single store instead of vectorizing eight
byte extractions into shifts, shuffles, and constant-pool loads.

Use byte pointers without creating references to the whole storage, so
raw access can leave neighboring bytes uninitialized. Check the field's
bounds before accessing storage, including in release builds, to
preserve the safe accessors' bounds checking and reject invalid writes
before modifying any bytes.

Replace comparisons between accessors sharing the same algorithm with
bit-at-a-time expected values. Cover narrow and full-width fields at
every intra-byte offset, preservation of neighboring bits, constant
evaluation, indirect storage, and bounds failures. Enable this coverage
on both endiannesses while retaining the older little-endian-specific
cases behind their existing condition.
@tamird

tamird commented Sep 15, 2026

Copy link
Copy Markdown
Contributor Author

r? @jsgf @emilio

This was written by LLM and reviewed by me. The bug was also spotted by multiple LLMs in aya-rs/aya#1730.

@rustbot

rustbot commented Sep 15, 2026

Copy link
Copy Markdown
Collaborator

Error: Failed to set assignee to jsgf: invalid assignee

Note: Only org members with at least the repository "read" role, users with write permissions, or people who have commented on the PR may be assigned.

Please file an issue on GitHub at triagebot if there's a problem with this bot, or reach out on #triagebot on Zulip.

@tamird

tamird commented Sep 15, 2026

Copy link
Copy Markdown
Contributor Author

r? @emilio

@tamird

tamird commented Sep 15, 2026

Copy link
Copy Markdown
Contributor Author

Another note: this diff looks much cleaner with --diff-algorithm=histogram.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants