Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

BUG: sparse/arpack: fix an out-of-bounds memory write bug in ARPACK

For small matrices, ARPACK's S/DNAUP2 could crash for some starting
vectors, when its stagnation avoidance heuristics would make NEV too
large.

Apparently, it was forgotten in the heuristics that a call to S/DNGETS
following the NEV adjustment could in some rare cases increase NEV by 1,
leading to out-of-bounds memory write in the next iteration.
  • Loading branch information...
commit 1857a29d2b313cfe2b18e191eb1fef49273719cc 1 parent 266a36f
@pv pv authored
View
12 scipy/sparse/linalg/eigen/arpack/ARPACK/SRC/dnaup2.f
@@ -664,6 +664,18 @@ subroutine dnaup2
else if (nev .eq. 1 .and. kplusp .gt. 3) then
nev = 2
end if
+c
+c %---- Scipy fix ------------------------------------------------
+c | We must keep nev below this value, as otherwise we can get
+c | np == 0 (note that dngets below can bump nev by 1). If np == 0,
+c | the next call to `dnaitr` will write out-of-bounds.
+c |
+ if (nev .gt. kplusp - 2) then
+ nev = kplusp - 2
+ end if
+c |
+c %---- Scipy fix end --------------------------------------------
+c
np = kplusp - nev
c
c %---------------------------------------%
View
12 scipy/sparse/linalg/eigen/arpack/ARPACK/SRC/snaup2.f
@@ -664,6 +664,18 @@ subroutine snaup2
else if (nev .eq. 1 .and. kplusp .gt. 3) then
nev = 2
end if
+c
+c %---- Scipy fix ------------------------------------------------
+c | We must keep nev below this value, as otherwise we can get
+c | np == 0 (note that sngets below can bump nev by 1). If np == 0,
+c | the next call to `snaitr` will write out-of-bounds.
+c |
+ if (nev .gt. kplusp - 2) then
+ nev = kplusp - 2
+ end if
+c |
+c %---- Scipy fix end --------------------------------------------
+c
np = kplusp - nev
c
c %---------------------------------------%
View
17 scipy/sparse/linalg/eigen/arpack/tests/test_arpack.py
@@ -359,6 +359,23 @@ def test_eigen_bad_kwargs():
A = csc_matrix(np.zeros((2,2)))
assert_raises(ValueError, eigs, A, which='XX')
+def test_ticket_1459_arpack_crash():
+ for dtype in [np.float32, np.float64]:
+ # XXX: this test does not seem to catch the issue for float32,
+ # but we made the same fix there, just to be sure
+
+ N = 6
+ k = 2
+
+ np.random.seed(2301)
+ A = np.random.random((N, N)).astype(dtype)
+ v0 = np.array([-0.71063568258907849895, -0.83185111795729227424,
+ -0.34365925382227402451, 0.46122533684552280420,
+ -0.58001341115969040629, -0.78844877570084292984e-01],
+ dtype=dtype)
+
+ # Should not crash:
+ evals, evecs = eigs(A, k, v0=v0)
def test_eigs_operator():
# Check inferring LinearOperator dtype
Please sign in to comment.
Something went wrong with that request. Please try again.