Description
Twelve double-complex (z*) routines store the optimal RWORK size via RWORK(1) = REAL(LROPT). The Fortran REAL() intrinsic returns a float32, but RWORK is declared DOUBLE PRECISION. The f32 intermediate silently truncates integers above 2^24 = 16,777,216 to the nearest representable value, so callers that trust the workspace query allocate too little memory, leading to out-of-bounds writes and segfaults.
Looks like this issue was introduced by ee213a3ed.
Repro:
import ctypes, numpy as np
# Against LAPACK built from current HEAD
lapack = ctypes.CDLL("liblapack.so")
N = 3000
n = ctypes.c_int(N)
jobz = ctypes.c_char(b'V')
uplo = ctypes.c_char(b'U')
lda = ctypes.c_int(N)
info = ctypes.c_int(0)
a = np.zeros((N, N), dtype=np.complex128, order='F')
w = np.zeros(N, dtype=np.float64)
work = np.zeros(1, dtype=np.complex128)
rwork = np.zeros(1, dtype=np.float64)
iwork = np.zeros(1, dtype=np.int32)
lwork = ctypes.c_int(-1)
lrwork = ctypes.c_int(-1)
liwork = ctypes.c_int(-1)
lapack.zheevd_(ctypes.byref(jobz), ctypes.byref(uplo), ctypes.byref(n),
a.ctypes.data_as(ctypes.c_void_p), ctypes.byref(lda),
w.ctypes.data_as(ctypes.c_void_p),
work.ctypes.data_as(ctypes.c_void_p), ctypes.byref(lwork),
rwork.ctypes.data_as(ctypes.c_void_p), ctypes.byref(lrwork),
iwork.ctypes.data_as(ctypes.c_void_p), ctypes.byref(liwork),
ctypes.byref(info))
expected = 1 + 5*N + 2*N**2 # 18,015,001
got = int(rwork[0]) # 18,015,000 (off by 1)
Results at various N:
N=1000: expected=2005001, got=2005001, diff=0 ✓
N=2896: expected=16791393, got=16791392, diff=1 ✗
N=3000: expected=18015001, got=18015000, diff=1 ✗
N=5000: expected=50025001, got=50024998, diff=3 ✗
Allocating RWORK with the reported (too-small) size and calling ZHEEVD on actual data produces a segfault due to out-of-bounds writes.
Checklist
- [ x] I've included a minimal example to reproduce the issue
- [x ] I'd be willing to make a PR to solve this issue
Description
Twelve double-complex (
z*) routines store the optimal RWORK size viaRWORK(1) = REAL(LROPT). The FortranREAL()intrinsic returns a float32, but RWORK is declaredDOUBLE PRECISION. The f32 intermediate silently truncates integers above 2^24 = 16,777,216 to the nearest representable value, so callers that trust the workspace query allocate too little memory, leading to out-of-bounds writes and segfaults.Looks like this issue was introduced by ee213a3ed.
Repro:
Results at various N:
Allocating RWORK with the reported (too-small) size and calling ZHEEVD on actual data produces a segfault due to out-of-bounds writes.
Checklist