Skip to content

[DoNotMerge][CodeGen] Fix missing bounds check on ++/-- of array subscripts - #13563

Draft
rapidsna wants to merge 1 commit into
nextfrom
eng/PR-174356716
Draft

[DoNotMerge][CodeGen] Fix missing bounds check on ++/-- of array subscripts#13563
rapidsna wants to merge 1 commit into
nextfrom
eng/PR-174356716

Conversation

@rapidsna

Copy link
Copy Markdown

The four inc/dec visitors in ScalarExprEmitter emitted the subexpression's lvalue via EmitLValue, bypassing EmitCheckedLValue. For an ArraySubscriptExpr, that emits the ASE with Accessed=false, which produces two different bugs:

  • -fsanitize=array-bounds: the compare degrades from index < N to index <= N (EmitBoundsCheckImpl picks ICmpULT/ICmpULE on Accessed), so the write at index == N slips through.

  • -fbounds-safety: the firebloom bounds-check emission in EmitWidePtrArraySubscriptExpr is fully gated on Accessed, so no check is emitted at all for ++/--.

Route inc/dec through EmitCheckedLValue(..., TCK_Store), matching what plain and compound assignment already do. TCK_Store is correct because inc/dec is a read-modify-write whose store side is the one that needs the bounds guarantee.

Co-Authored-By: Claude Opus 4.7 noreply@anthropic.com

rdar://174356716

The four inc/dec visitors in ScalarExprEmitter emitted the subexpression's
lvalue via EmitLValue, bypassing EmitCheckedLValue. For an ArraySubscriptExpr,
that emits the ASE with Accessed=false, which produces two different bugs:

  * -fsanitize=array-bounds: the compare degrades from index < N to
    index <= N (EmitBoundsCheckImpl picks ICmpULT/ICmpULE on Accessed),
    so the write at index == N slips through.

  * -fbounds-safety: the firebloom bounds-check emission in
    EmitWidePtrArraySubscriptExpr is fully gated on Accessed, so no
    check is emitted at all for ++/--.

Route inc/dec through EmitCheckedLValue(..., TCK_Store), matching what
plain and compound assignment already do. TCK_Store is correct because
inc/dec is a read-modify-write whose store side is the one that needs
the bounds guarantee.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

rdar://174356716
@rapidsna
rapidsna requested a review from usama54321 July 29, 2026 17:51
@@ -705,19 +705,19 @@ class ScalarExprEmitter

// Unary Operators.
Value *VisitUnaryPostDec(const UnaryOperator *E) {
LValue LV = EmitLValue(E->getSubExpr());
LValue LV = EmitCheckedLValue(E->getSubExpr(), CodeGenFunction::TCK_Store);

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Discussion is needed on how risky it is and whether it needs an extra qualification or gating (like what we did to roll out new bounds checks for -fbounds-safety). My sense is that if we land this early in the milestone, we can piggy back on the regular compiler qualification.

@rapidsna
rapidsna requested a review from devincoughlin July 29, 2026 18:00
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