Sitelet https://github.com/starkware-libs/cairo/pull/10009
Skip to content

bugfix: Fixed off-by one boundary in non-allowed qm31 libfunc. - #10009

Merged
orizi merged 1 commit into
mainfrom
orizi/05-31-bugfix_fixed_off-by_one_boundary_in_non-allowed_qm31_libfunc
May 31, 2026
Merged

orizi merged 1 commit into
mainfrom
orizi/05-31-bugfix_fixed_off-by_one_boundary_in_non-allowed_qm31_libfunc

Conversation

@orizi

@orizi orizi commented May 31, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Replaces the use of u128::MAX with u128_bound() when computing the fixer constant in build_qm31_unpack. This corrects an off-by-one error: u128::MAX is 2^128 - 1, but the intended bound is 2^128 (i.e., u128_bound()), shifting the fixer value by 1 and producing the correct range-check constant 340282366920938463463374607363048734720 instead of 340282366920938463463374607363048734719.


Type of change

Please check one:

  • Bug fix (fixes incorrect behavior)
  • New feature
  • Performance improvement
  • Documentation change with concrete technical impact
  • Style, wording, formatting, or typo-only change

Why is this change needed?

The fixer constant in build_qm31_unpack was computed using u128::MAX (2^128 - 1) instead of 2^128. The intent is to validate that sum lies within [0, 2^36) by checking that sum + fixer fits in a u128 range check cell, where fixer = 2^128 - PART_UPPER_BOUND. Using u128::MAX instead of 2^128 shifts the fixer by 1, making the range check boundary incorrect.


What was the behavior or documentation before?

The fixer was u128::MAX - PART_UPPER_BOUND, producing a constant of 340282366920938463463374607363048734719.


What is the behavior or documentation after?

The fixer is u128_bound() - PART_UPPER_BOUND, producing the correct constant of 340282366920938463463374607363048734720, properly enforcing that sum is within [0, 2^36).


Related issue or discussion (if any)

N/A


Additional context

The e2e test data for the qm31 libfunc is updated to reflect the corrected constant value.

SIERRA_UPDATE_NO_CHANGE_TAG=Changes to non-allowed libfunc.

orizi commented May 31, 2026

Copy link
Copy Markdown
Collaborator Author

This stack of pull requests is managed by Graphite. Learn more about stacking.

@reviewable-StarkWare

Copy link
Copy Markdown

This change is Reviewable

@orizi
orizi marked this pull request as ready for review May 31, 2026 07:47
@cursor

cursor Bot commented May 31, 2026 •

Copy link
Copy Markdown

PR Summary

Medium Risk
Wrong fixer could weaken unpack soundness for qm31; change is tiny but affects proof constraints in generated CASM.

Overview
Fixes an off-by-one in qm31_unpack range-check lowering: the fixer constant is now u128_bound() - PART_UPPER_BOUND (i.e. 2^128 − 2^36) instead of u128::MAX - PART_UPPER_BOUND, so the proof correctly enforces that the packed limb sum lies in [0, 2^36).

The qm31_unpack e2e CASM expectation is updated by +1 on the immediate (…734719 → …734720).

Reviewed by Cursor Bugbot for commit 891c35c. Bugbot is set up for automated code reviews on this repo. Configure here.

@TomerStarkware TomerStarkware left a comment

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.

:lgtm:

@TomerStarkware reviewed 2 files and all commit messages, and made 1 comment.
Reviewable status: :shipit: complete! all files reviewed, all discussions resolved (waiting on gilbens-starkware).

@orizi
orizi added this pull request to the merge queue May 31, 2026
Merged via the queue into main with commit ccfad0c May 31, 2026
54 checks passed
@orizi
orizi deleted the orizi/05-31-bugfix_fixed_off-by_one_boundary_in_non-allowed_qm31_libfunc branch May 31, 2026 08:42
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