Skip to content

Keep Miri off the decoder's tables rather than off Stacked Borrows - #147

Merged
glslang merged 1 commit into
mainfrom
fix/miri-and-the-decoder
Sep 10, 2026
Merged

Keep Miri off the decoder's tables rather than off Stacked Borrows#147
glslang merged 1 commit into
mainfrom
fix/miri-and-the-decoder

Conversation

@glslang

@glslang glslang commented Sep 10, 2026

Copy link
Copy Markdown
Owner

main is red for the first time in this job's life, from the merge that added iced-x86 (#145).

The failure is inside that crate. Its byte reader casts an integer to a pointer — mk_read_xx, an unsafe { ptr::read_unaligned(data_ptr as *const _) } — so the pointer carries no provenance and Stacked Borrows refuses to retag it, in the decoder's own handler tables, on every decode.

Measured, not reasoned about

One test, three flag sets, on nightly:

MIRIFLAGS result
the workflow's (Stacked Borrows) fail
… plus -Zmiri-permissive-provenance fail
… with -Zmiri-tree-borrows instead pass

An aliasing-model disagreement about a dependency's internals, then, rather than a defect here — and permissive provenance alone does not reach it, which is worth knowing because the integer-to-pointer cast is what Miri warns about and is not what it refuses.

Why exclude the tests instead of switching the model

Moving the whole job to Tree Borrows was the alternative. This job exists for this crate's unsafe code — miri.yml names dbgeng.rs and pool/**, "decoding raw kernel structures out of byte slices, which is the most UB-prone code here" — and relaxing the model for all of that, in order to cover a dependency's tables we cannot change either way, is a bad trade.

Nothing on the excluded path is an unsafe block of ours: decode_operation is safe Rust calling a safe API. So the exclusion costs no coverage of this crate, and if iced-x86 ever needs Miri coverage the answer is a second job with -Zmiri-tree-borrows, not a weaker first one.

A new decoding test that forgets the attribute turns main red, which is how this one was found. Self-correcting, not silent.

Verification

Locally over the whole suite, not just the four tests CI reached before it fail-fasted:

  • Miri: 148 passed, 0 failed, 18 ignored
  • ordinary runner: 210 passed, 0 failed

I have also dispatched this workflow against this branch, so the box below is a real run rather than my word for it.

One doc change

miri.yml said "It has never failed: 92 successes … across the last hundred", which is no longer true. It now records what happened, including that this is precisely the cost that comment predicted when Miri moved off pull requests, and that workflow_dispatch is what a change like this one should have used.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Ayv1beKpAVkmDJDLfYqoyf

`main` is red for the first time in this job's life, from the merge that added
`iced-x86`. The failure is inside that crate: its byte reader casts an integer
to a pointer (`mk_read_xx`, `ptr::read_unaligned(data_ptr as *const _)`), so
the pointer carries no provenance and Stacked Borrows refuses to retag it --
in the decoder's own handler tables, on every decode.

Measured on nightly rather than reasoned about, one test each:

  the workflow's flags (Stacked Borrows)      fail
  ... plus -Zmiri-permissive-provenance       fail
  ... with -Zmiri-tree-borrows instead        pass

So it is an aliasing-model disagreement about a dependency's internals, not a
defect here, and permissive provenance alone does not reach it.

The eighteen tests that decode are excluded from Miri; the job keeps Stacked
Borrows. Moving the whole job to Tree Borrows was the alternative and is worse
value: this job exists for *this* crate's unsafe code -- `dbgeng.rs` and
`pool/**` decoding raw kernel structures out of byte slices, as `miri.yml`
says -- and relaxing the model for all of that to cover a dependency's tables
we cannot change either way is a bad trade. Nothing on the excluded path is an
`unsafe` block of ours: `decode_operation` is safe Rust calling a safe API, so
the exclusion costs no coverage of this crate.

Verified locally over the whole suite, not just the four tests CI reached
before it fail-fasted: 148 passed, 0 failed, 18 ignored under Miri, and 210
passed under the ordinary runner.

The workflow's own "it has never failed" is no longer true, so it now says
what happened instead -- including that this is exactly the cost it predicted
when Miri moved off pull requests, and that `workflow_dispatch` is what a
change like this one should have used.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ayv1beKpAVkmDJDLfYqoyf
@coderabbitai

coderabbitai Bot commented Sep 10, 2026

Copy link
Copy Markdown

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Advanced

Run ID: c8b2ea0e-4f0e-41bc-8343-b77a7af05ce9


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 10, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-10T15:27:24.435661Z c016ea9 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c016ea95ae

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/dbgeng.rs
Comment on lines +8496 to +8499
#[cfg_attr(
miri,
ignore = "decodes through iced-x86; see MIRI AND THE DECODER above"
)]

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep non-decoding parser tests enabled under Miri

For every input in this test, split_instruction produces an empty byte slice, so decode_operation returns from its bytes.is_empty() branch before constructing an iced-x86 decoder. The same is true of test_an_unreadable_rendering_is_not_walked_through, while test_an_unread_instruction_set_reports_no_operands_and_no_flow returns on InstructionSet::Other; therefore these three ignores unnecessarily remove Miri coverage from paths that cannot trigger the dependency failure this change is isolating.

Useful? React with 👍 / 👎.

@glslang
glslang merged commit 81c1806 into main Sep 10, 2026
8 checks passed
@glslang
glslang deleted the fix/miri-and-the-decoder branch September 10, 2026 16:32
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.

1 participant