Skip to content

fix(parallel): align stack word max index bound#3014

Open
mk0walsk wants to merge 5 commits into0xMiden:nextfrom
mk0walsk:fix-parallel-stack-word-max-index-bound02
Open

fix(parallel): align stack word max index bound#3014
mk0walsk wants to merge 5 commits into0xMiden:nextfrom
mk0walsk:fix-parallel-stack-word-max-index-bound02

Conversation

@mk0walsk
Copy link
Copy Markdown

@mk0walsk mk0walsk commented Apr 17, 2026

• ## Describe your changes

This PR fixes a boundary-contract mismatch in parallel stack word access.

  • Updated ReplayProcessor::get_word and ReplayProcessor::set_word to allow start_idx == MIN_STACK_DEPTH - WORD_SIZE (i.e. max valid index 12), matching StackInterface and fast-path behavior.
  • Added regression test stack_set_word_allows_max_start_idx to ensure max-index writes/reads remain valid.
  • Related: Apply code quality fixes and tests #2802

Checklist before requesting a review

  • Repo forked and branch created from next according to naming convention.
  • Commit messages and codestyle follow conventions.
  • Commits are signed.
  • Relevant issues are linked in the PR description.
  • Tests added for new functionality.
  • Documentation/comments updated according to changes.
  • Updated CHANGELOG.md.

@github-actions
Copy link
Copy Markdown

Automated check (CONTRIBUTING.md)

Findings:

Recommendations:

  • Consider adding a Test plan or clear review steps.

Next steps:

  • Link a relevant issue (e.g., "Fixes Implement SHA256 in Miden Assembly #123") and ensure it is assigned to you.
  • See CONTRIBUTING.md for expectations.
  • If this is a false positive, comment: /quality-review.

Copy link
Copy Markdown
Collaborator

@huitseeker huitseeker left a comment

Choose a reason for hiding this comment

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

We could introduce a helper, Something like:

#[inline(always)]
fn word_start_idx(stack_len: usize, start_idx: usize) -> usize {
    stack_len - start_idx - WORD_SIZE
}

Then both replay and fast paths become obviously the same calculation.


fn set_word(&mut self, start_idx: usize, word: &Word) {
debug_assert!(start_idx < MIN_STACK_DEPTH - 4);
debug_assert!(start_idx <= MIN_STACK_DEPTH - WORD_SIZE);
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Related to this bound, would it help to switch the next line to MIN_STACK_DEPTH - start_idx - WORD_SIZE instead of - 4? Using WORD_SIZE in both places makes the offset formula much easier to audit.


fn get_word(&self, start_idx: usize) -> Word {
debug_assert!(start_idx < MIN_STACK_DEPTH - 4);
debug_assert!(start_idx <= MIN_STACK_DEPTH - WORD_SIZE);
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Would it be clearer to write this as debug_assert!(start_idx + WORD_SIZE <= MIN_STACK_DEPTH)? That states the full-word-fit invariant directly, which makes the later offset math easier to check at a glance.

fn stack_set_word_allows_max_start_idx() {
let mut processor = build_replay_processor();
let start_idx = MIN_STACK_DEPTH - WORD_SIZE;
let word = [Felt::new(1), Felt::new(2), Felt::new(3), Felt::new(4)].into();
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Since this test is about the WORD_SIZE boundary, would it make sense to build the sample word from WORD_SIZE too instead of a 4-element literal? That keeps the test aligned with the same constant the implementation is checking.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants