Skip to content

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