Fix LAPACKE_?lacpy_work row-major triangular copy corrupting the untouched triangle (#729)#1318
Open
meng004 wants to merge 1 commit into
Open
Conversation
The row-major branch transposed the full m-by-n matrix through temporaries and copied the never-written complementary region of the destination temporary back over B, corrupting the triangle uplo requires to be preserved and reading uninitialized memory. Call the Fortran kernel directly with uplo swapped (U<->L) and m/n swapped, exactly as the correct column-major path does. Applies identically to s/d/c/z.
mgates3
reviewed
Jul 6, 2026
mgates3
left a comment
Collaborator
There was a problem hiding this comment.
Other than perhaps shortening the comments, this looks good. Nice that it greatly simplified the code and eliminated malloc and copy! (Though I didn't personally validate the code, and LAPACKE unfortunately lacks testers. LAPACK++ tests only column-major.)
| * matrix through temporary buffers, which (a) read the uninitialized | ||
| * complementary region of the destination temporary and (b) wrote it | ||
| * back over the part of B that `uplo` requires to stay untouched, | ||
| * corrupting the caller's data and reading uninitialized memory. A |
Collaborator
There was a problem hiding this comment.
I would put comments like this in the PR description, not in the code itself. It clutters up the code -- years from now, the old behavior is irrelevant.
Same comment in other precisions.
Contributor
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
LAPACKE_?lacpy_work(s/d/c/z) withmatrix_layout == LAPACK_ROW_MAJORand a triangular
uplo('U'/'L') corrupts the part of the destinationBthat the operation is supposed to leave untouched, and reads uninitialized heap
memory in the process. As reported in #729, only the requested triangle of
Bshould change; instead the complementary region of
Bis overwritten withgarbage. The column-major path is correct.
Root cause
LAPACKE/src/lapacke_slacpy_work.c(and thed/c/zsiblings) implement therow-major branch by transposing through temporaries:
The kernel
LAPACK_?lacpywith a triangularuplowrites only the requestedtriangle of
b_t, so the complementary region ofb_tstays uninitialized. Thefinal
LAPACKE_?ge_transthen transposes the entirem-by-nb_tbackinto the caller's
B— including that never-written region — overwriting thebytes of
Bthatuplorequires to be preserved with uninitialized heapcontents. (In the file as shipped this is
LAPACKE/src/lapacke_slacpy_work.c:76, the "Transpose output matrices" call.)Fix
A row-major
m-by-nmatrix with leading dimensionldais bit-identical to acolumn-major
n-by-mmatrix — its mathematical transpose. Copying triangleuploof the row-major matrix is therefore exactly copying the oppositetriangle (
U↔L) of that transpose, with them/nextents swapped. So therow-major branch can call the Fortran kernel directly on
a/bwithuploflipped and
m/nswapped:Like the already-correct column-major path, the kernel now writes exactly the
requested triangle of
Band never touches the complementary region. This isminimal and, in fact, net-negative in size: it removes the two
LAPACKE_mallocs,the two
LAPACKE_?ge_transcalls, and the error-exit ladder rather than addingspecial cases. The existing row-major leading-dimension checks (
lda < n→-6,ldb < n→-8) are preserved verbatim, the column-major andinvalid-layout branches are untouched, the public signatures/headers are
unchanged, and
uplovalues other than'U'/'L'(e.g.'A', a full copy)are layout-agnostic and pass straight through.
Test evidence
Validated with a two-arm build in which both arms share the identical
liblapack/libblas; only the four LAPACKE*lacpy_workobjects differ(pristine vs. patched). The oracle copies triangle
uploof the same logicalmatrix
Ainto a sentinel-filledBonce inLAPACK_COL_MAJOR(ground truth)and once in
LAPACK_ROW_MAJOR; the two logical results must be identical.uplo='U'uplo='L'Auplo='A'(row vs col)uplo='U'/'L'The copied-triangle content was already correct before the fix; the sole defect
is the complementary region, which the fix restores to being preserved. The
uplo='A'full-copy control and the column-major reference are identical on botharms, confirming the change does not perturb the paths it should not.
How to reproduce
Minimal C reproducer (double precision; the same holds for
s/c/z):Build with
-llapacke -llapack -lblas. Before the fix it prints mismatches inthe complementary (strictly-lower) triangle; after the fix it prints nothing.