gonum/netlib

blas: zero size matrix causes panic for Dgemv

Closed this issue · 0 comments

When the netlib CGO BLAS implementation is used gonum/matrix/mat64 TestInverse fails with an index out of range.

This suggests that the indexing used by the native LAPACK implementation is not properly conditioned/vetted by the cgo wrapping code for blas; the stack trace shows this happening for n == 0

This presumably is a problem throughout.

CGO BLAS and native LAPACK.

$ cat $GOPATH/src/gonum.org/v1/gonum/matrix/mat64/cblas_test.go
// Copyright ©2015 The gonum Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

//+build cblas

package mat64

import (
	"gonum.org/v1/gonum/blas/blas64"
	"gonum.org/v1/netlib/blas"
)

func init() {
	blas64.Use(blas.Implementation{})
}
$ CGO_LDFLAGS="-L/usr/local -lopenblas" go test -tags cblas -run TestInverse gonum.org/v1/gonum/matrix/mat64
--- FAIL: TestInverse (0.00s)
panic: runtime error: index out of range [recovered]
	panic: runtime error: index out of range

goroutine 6 [running]:
testing.tRunner.func1(0xc4200771e0)
	/home/daniel/go/src/testing/testing.go:622 +0x29d
panic(0x684e80, 0x9be090)
	/home/daniel/go/src/runtime/panic.go:489 +0x2cf
gonum.org/v1/netlib/blas.Implementation.Dgemv(0x6f, 0x3, 0x0, 0xbff0000000000000, 0xc420019288, 0x6, 0x6, 0x3, 0xc42001a600, 0x0, ...)
	/home/daniel/src/gonum.org/v1/netlib/blas/blas.go:1418 +0x1e9
gonum.org/v1/netlib/blas.(*Implementation).Dgemv(0x9f9268, 0x6f, 0x3, 0x0, 0xbff0000000000000, 0xc420019288, 0x6, 0x6, 0x3, 0xc42001a600, ...)
	<autogenerated>:55 +0x141
gonum.org/v1/gonum/lapack/native.Implementation.Dgetri(0x3, 0xc420019270, 0x9, 0x9, 0x3, 0xc42000cfc0, 0x3, 0x3, 0xc42001a600, 0xc0, ...)
	/home/daniel/src/gonum.org/v1/gonum/lapack/native/dgetri.go:66 +0x54f
gonum.org/v1/gonum/lapack/native.(*Implementation).Dgetri(0x9f9040, 0x3, 0xc420019270, 0x9, 0x9, 0x3, 0xc42000cfc0, 0x3, 0x3, 0xc42001a600, ...)
	<autogenerated>:22 +0xe5
gonum.org/v1/gonum/lapack/lapack64.Getri(0x3, 0x3, 0x3, 0xc420019270, 0x9, 0x9, 0xc42000cfc0, 0x3, 0x3, 0xc42001a600, ...)
	/home/daniel/src/gonum.org/v1/gonum/lapack/lapack64/lapack64.go:229 +0xd5
gonum.org/v1/gonum/matrix/mat64.(*Dense).Inverse(0xc4200e0540, 0x9cb560, 0xc4200e0000, 0x40, 0x40)
	/home/daniel/src/gonum.org/v1/gonum/matrix/mat64/dense_arithmetic.go:245 +0x32f
gonum.org/v1/gonum/matrix/mat64.TestInverse(0xc4200771e0)
	/home/daniel/src/gonum.org/v1/gonum/matrix/mat64/dense_test.go:1813 +0xdc0
testing.tRunner(0xc4200771e0, 0x6c9c90)
	/home/daniel/go/src/testing/testing.go:657 +0x96
created by testing.(*T).Run
	/home/daniel/go/src/testing/testing.go:697 +0x2ca
FAIL	gonum.org/v1/gonum/matrix/mat64	0.013s

The approach used in the lapacke CGO wrapping code is to conditionally take addresses. Alternatively, we can return early for n == 0 or m == 0. I think I prefer the lapacke approach since it is obviously correct for all sets of parameters.