Crash via allocator in modernc.org/sqlite.(*rows).Close
crow5k:modernsqlite $ cat go.mod
module play
go 1.16
require modernc.org/sqlite v1.10.4 // indirect
crow5k:modernsqlite $ go run repro.go
1
2
3
4
5
6
7
8
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x10 pc=0x10db2c5]
goroutine 1 [running]:
modernc.org/memory.(*Allocator).UintptrFree(0x1505380, 0x9000790, 0x0, 0x0)
/Users/bradfitz/pkg/mod/modernc.org/memory@v1.0.4/memory.go:289 +0x105
modernc.org/libc.Xfree(0xc0005aa0a0, 0x9000790)
/Users/bradfitz/pkg/mod/modernc.org/libc@v1.9.5/mem.go:85 +0x87
modernc.org/sqlite.(*conn).free(...)
/Users/bradfitz/pkg/mod/modernc.org/sqlite@v1.10.4/sqlite.go:1173
modernc.org/sqlite.(*rows).Close(0xc000060960, 0xc00008e500, 0x1504f00)
/Users/bradfitz/pkg/mod/modernc.org/sqlite@v1.10.4/sqlite.go:198 +0x69
database/sql.(*Rows).close.func1()
/Users/bradfitz/go/src/database/sql/sql.go:3178 +0x3c
database/sql.withLock(0x1359d10, 0xc0004c8000, 0xc000107e18)
/Users/bradfitz/go/src/database/sql/sql.go:3294 +0x69
database/sql.(*Rows).close(0xc00008e500, 0x0, 0x0, 0x0, 0x0)
/Users/bradfitz/go/src/database/sql/sql.go:3177 +0x114
database/sql.(*Rows).Close(...)
/Users/bradfitz/go/src/database/sql/sql.go:3161
database/sql.(*Row).Scan(0xc0005a60f0, 0xc000107f48, 0x1, 0x1, 0x0, 0x0)
/Users/bradfitz/go/src/database/sql/sql.go:3242 +0x18c
main.main()
/Users/bradfitz/hack/modernsqlite/repro.go:42 +0x46f
exit status 2
crow5k:modernsqlite $ cat repro.go
package main
import (
"database/sql"
"fmt"
"log"
"os"
_ "modernc.org/sqlite"
)
func main() {
os.Remove("x.sqlite")
db, err := sql.Open("sqlite", "x.sqlite")
if err != nil {
log.Fatal(err)
}
if _, err := db.Exec(`
CREATE TABLE IF NOT EXISTS loginst (
instid INTEGER PRIMARY KEY,
name VARCHAR UNIQUE
);
`); err != nil {
log.Fatal(err)
}
tx, err := db.Begin()
if err != nil {
log.Fatal(err)
}
for i := 0; i < 5000; i++ {
x := fmt.Sprint("foo%d", i)
var id int
if err := tx.QueryRow("INSERT OR IGNORE INTO loginst (name) VALUES (?); SELECT instid FROM loginst WHERE name = ?", x, x).Scan(&id); err != nil {
log.Fatal(err)
}
fmt.Println(id)
}
}
Edited by Brad Fitzpatrick