diff --git a/src/sparsematrix.jl b/src/sparsematrix.jl index 51ff5caf..3ba28bba 100644 --- a/src/sparsematrix.jl +++ b/src/sparsematrix.jl @@ -4128,9 +4128,10 @@ function is_hermsym(A::AbstractSparseMatrixCSC, check::Function) offset = tracker[row] - # If the matrix is unsymmetric, there might not exist - # a rowval[offset] - if offset > length(rowval) + # If the matrix is unsymmetric, the tracker may have moved + # past the last stored entry of column `row`, meaning the + # partner entry A[col, row] does not exist + if offset > colptr[row+1] - 1 return false end @@ -4145,8 +4146,13 @@ function is_hermsym(A::AbstractSparseMatrixCSC, check::Function) return false end offset += 1 - row2 = rowval[offset] tracker[row] += 1 + # Column `row` ran out of stored entries before + # reaching row `col`, so A[col, row] does not exist + if offset > colptr[row+1] - 1 + return false + end + row2 = rowval[offset] end # Non zero A[i,j] exists but A[j,i] does not exist diff --git a/test/linalg.jl b/test/linalg.jl index 758ed3cb..290a4ea4 100644 --- a/test/linalg.jl +++ b/test/linalg.jl @@ -520,6 +520,15 @@ end nonzeros(A)[end - 3] = 2.0 @test issymmetric(A) == false + # stored zeros must not cause out-of-bounds access when the + # partner column runs out of stored entries + A = sparse([3, 1], [2, 3], [1.0, 0.0], 3, 3) + @test issymmetric(A) == false + @test ishermitian(A) == false + A = sparse([1, 2], [2, 1], [0.0, 0.0], 2, 2) + @test issymmetric(A) == true + @test ishermitian(A) == true + # 16521 @test issymmetric(sparse([0 0; 1 0])) == false @test issymmetric(sparse([0 1; 0 0])) == false