Skip to content

Fix integer overflow in LAPACKE nancheck helpers for large matrices#1294

Merged
langou merged 1 commit into
Reference-LAPACK:masterfrom
changangela:fix-lapacke-nancheck-overflow
Jun 12, 2026
Merged

Fix integer overflow in LAPACKE nancheck helpers for large matrices#1294
langou merged 1 commit into
Reference-LAPACK:masterfrom
changangela:fix-lapacke-nancheck-overflow

Conversation

@changangela

Copy link
Copy Markdown
Contributor

Hit this while running Cholesky on a 47000x47000 matrix through OpenBLAS: LAPACKE_dpotrf segfaults in LAPACKE_dtr_nancheck before the factorization even starts, because j*lda overflows 32-bit lapack_int once n = lda >= 46341.

The ge/gb/tp/tf helpers already cast to size_t, but a few others were missed:

  • ?tr_nancheck: a[i+j*lda] (this is the potrf path, also used by the po/sy/he checks)
  • ?_nancheck: the n*inc loop bound overflows when called with a large stride (e.g. from the hs/tf checks)
  • ?sp/?pp/?pf/?hp/?tp/?tf: len = n*(n+1)/2 overflows, the check then silently passes NaNs through
  • ?tz_nancheck: the part offsets overflow, widened to int64_t to keep the -1 sentinel

This bug also affects OpenBLAS (it vendors these files) - identical fix in OpenMathLib/OpenBLAS#5835.

Tested with UBSan at n = 47000: the old code reports signed integer overflow and either segfaults (tr, tz) or misses a planted NaN (vector, packed); the fixed code finds the NaN in all cases. Old and new give identical results on a sweep of small sizes covering all layouts/uplo/diag/shapes with a NaN at every position.

Offset computations like j*lda overflow 32-bit lapack_int once
n = lda >= 46341, e.g. LAPACKE_dpotrf crashes in its NaN check before
the factorization runs. Cast to size_t (or int64_t for the tz offsets)
the same way ge/gb/tp/tf already do.

@langou langou left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This looks good to me.

for( j = st; j < n; j++ ) {
for( i = 0; i < MIN( j+1-st, lda ); i++ ) {
if( LAPACK_CISNAN( a[i+j*lda] ) )
if( LAPACK_CISNAN( a[i+(size_t)j*lda] ) )

@langou langou Jun 12, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The use of size_t here is certainly going to have a significant impact. Thanks!


/* Initial offsets and sizes of triangular and rectangular parts */
lapack_int tri_offset = 0;
int64_t tri_offset = 0;

@langou langou Jun 12, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

And then using int64_t instead of size_t because we need to be signed (as opposed to unsigned) for this variable sounds good to me. Great work.

@langou langou merged commit f534070 into Reference-LAPACK:master Jun 12, 2026
12 checks passed
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