Skip to content

Fix out-of-bounds access in is_hermsym for stored zeros - #741

Open
KristofferC wants to merge 1 commit into
mainfrom
fix-hermsym-oob
Open

Fix out-of-bounds access in is_hermsym for stored zeros#741
KristofferC wants to merge 1 commit into
mainfrom
fix-hermsym-oob

Conversation

@KristofferC

Copy link
Copy Markdown
Member

When old sins come back to haunt you.... (I am responsible for this bug 11 years ago)... I made Claude do some archaeology:


History of the is_hermsym out-of-bounds bug

The specific crashing loop is from JuliaLang/julia#15504, but the bug lineage starts at JuliaLang/julia#11371 — a version of this out-of-bounds hole has existed continuously since May 2015. Here is what an empirical run of each historical version of the algorithm shows:

Case #11371 (2015) #15504 (2016) #16526 (2016) truth
Today's crasher (stored zero, partner column runs out) wrong answer: true BoundsError BoundsError false
Exhausted partner column, no stored zeros BoundsError BoundsError false false
#15504 matrix wrong answer: false true true true
Issue #16521 matrix BoundsError BoundsError false false

The history reads like a game of whack-a-mole:

  1. JuliaLang/julia#11371 ("Improve performance of issym and ishermitian", May 2015) introduced is_hermsym with an unguarded rowval[tracker[row]] read — already out-of-bounds-capable (reported as JuliaLang/julia#16521), and it returned a silently wrong true on today's test matrix.
  2. JuliaLang/julia#15504 ("fix bug when zeros are stored", March 2016) fixed the stored-zeros wrong answers by adding the catch-up loop — and that loop's unguarded offset += 1; row2 = rowval[offset] is exactly the line that throws in today's crasher. So the precise bug fixed here was born there.
  3. JuliaLang/julia#16526 ("fix bug in sparse is_hermsym", May 2016, fixing JuliaLang/julia#16521) added the offset > length(rowval) guard — but only before the first read, and with the wrong bound (end of rowval instead of end of the column). It fixed the no-stored-zeros case and left the stored-zeros hole open for another decade.
  4. #661 (2023) re-added @inbounds, quietly upgrading the remaining BoundsError to undefined behavior.

So if you want a single answer: JuliaLang/julia#15504 wrote the line that crashes, but it was replacing a JuliaLang/julia#11371 line that gave a wrong answer on the same input. This fix is the third patch to the same ten-line region, all chasing the original 2015 tracker design.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@KristofferC KristofferC added backport 1.8 backport 1.9 backport 1.10 backport 1.11 backport 1.12 Change should be backported to release-1.12 backport 1.13 Change should be backported to release-1.13 labels Jul 23, 2026
@codecov

codecov Bot commented Jul 23, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 84.35%. Comparing base (c50786b) to head (e39e2ee).

Additional details and impacted files
@@           Coverage Diff           @@
##             main     #741   +/-   ##
=======================================
  Coverage   84.34%   84.35%           
=======================================
  Files          13       13           
  Lines        9373     9375    +2     
=======================================
+ Hits         7906     7908    +2     
  Misses       1467     1467           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@dkarrasch

Copy link
Copy Markdown
Member

Apparently, we need to backport to all the way to v0.4!

@KristofferC

Copy link
Copy Markdown
Member Author

I ran out of labels!

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

Labels

backport 1.8 backport 1.9 backport 1.10 backport 1.11 backport 1.12 Change should be backported to release-1.12 backport 1.13 Change should be backported to release-1.13

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants