mattn / mattn/go-sqlite3

SIGSEGV when create a table

Open
#1,199 3 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
C
Stars
9.2k
Forks
1.2k
Avg merge
19m
Merged PRs (30d)
4

Description

What version of Go are you using (go version)?
$ go version
go version go1.21.3 linux/386
What operating system and processor architecture are you using (go env)?
go env Output
$ go env
GO111MODULE='on'
GOARCH='386'
GOBIN=''
GOCACHE='/home/xxx/.cache/go-build'
GOENV='/home/xxx/.config/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFLAGS='-insecure'
GOHOSTARCH='386'
GOHOSTOS='linux'
GOINSECURE=''
GOMODCACHE='/media/sf_go/pkg/mod'
GONOPROXY=''
GONOSUMDB=''
GOOS='linux'
GOPATH='/media/sf_go'
GOPRIVATE=''
GOPROXY='direct'
GOROOT='/usr/local/go'
GOSUMDB='off'
GOTMPDIR=''
GOTOOLCHAIN='auto'
GOTOOLDIR='/usr/local/go/pkg/tool/linux_386'
GOVCS=''
GOVERSION='go1.21.3'
GCCGO='/home/xxx/GCC-4.6.0/bin/gccgo'
GO386='sse2'
AR='ar'
CC='/home/xxx/GCC-4.6.0/bin/gcc'
CXX='/home/xxx/GCC-4.6.0/bin/g++'
CGO_ENABLED='1'
GOMOD='/media/sf_go/src/tmp/go.mod'
GOWORK=''
CGO_CFLAGS='-O2 -g'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
PKG_CONFIG='pkg-config'
GOGCCFLAGS='-fPIC -m32 -pthread -Wl,--no-gc-sections -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build3046687627=/tmp/go-build'
What did you do?

go.mod

module tmp

go 1.21

require (
  github.com/mattn/go-sqlite3 v1.14.16
)

main.go

package main

import (
    "database/sql"
    "fmt"
    "os"

    _ "github.com/mattn/go-sqlite3"
)

const DB_FILENAME = "tmp.db"

func main() {
    db := createDatabase(DB_FILENAME)
    defer db.Close()

    res, err := db.Exec(`CREATE TABLE "my_table" ("mt_id"   INTEGER NOT NULL, "my_table_id" TEXT NOT NULL, "my_table_ja"    TEXT, "my_table_en" TEXT, PRIMARY KEY("mt_id" AUTOINCREMENT));`)
    if err != nil {
        fmt.Printf("db.Exec() error: %v\n", err)
    }
    fmt.Printf("db.Exec() result: %v\n", res)
}

func createDatabase(path string) *sql.DB {
    if pathExists(path) {
        removePath(path)
    }

    db, err := sql.Open("sqlite3", DB_FILENAME)
    if err != nil {
        fmt.Printf("sql.Open() error: %v\n", err)
    }

    return db
}

func pathExists(path string) bool {
    _, err := os.Stat(path)
    return !os.IsNotExist(err)
}

func removePath(path string) {
    if err := os.Remove(path); err != nil {
        fmt.Printf("os.Remove() error: %v\n", err)
    }
}

shell

$ go build
$ ./tmp
What did you expect to see?

Created table without crashing with SIGSEGV.

What did you see instead?
SIGSEGV: segmentation violation
PC=0x81ea110 m=0 sigcode=1
signal arrived during cgo execution

goroutine 1 [syscall]:
runtime.cgocall(0x815de10, 0xa059a6c)
        /usr/local/go/src/runtime/cgocall.go:157 +0x61 fp=0xa059a58 sp=0xa059a40 pc=0x8055131
github.com/mattn/go-sqlite3._Cfunc__sqlite3_step_row_internal(0x9e0f778, 0xa0143a8, 0xa0143b0)
        _cgo_gotypes.go:378 +0x3b fp=0xa059a6c sp=0xa059a58 pc=0x8146a5b
github.com/mattn/go-sqlite3.(*SQLiteStmt).execSync.func3(0xa06c200, 0xa0143a8, 0xa0143b0)
        /media/sf_go/pkg/mod/github.com/mattn/go-sqlite3@v1.14.16/sqlite3.go:2084 +0x62 fp=0xa059a84 sp=0xa059a6c pc=0x81589f2
github.com/mattn/go-sqlite3.(*SQLiteStmt).execSync(0xa06c200, {0x83966e0, 0x0, 0x0})
        /media/sf_go/pkg/mod/github.com/mattn/go-sqlite3@v1.14.16/sqlite3.go:2084 +0x8d fp=0xa059ab4 sp=0xa059a84 pc=0x815878d
github.com/mattn/go-sqlite3.(*SQLiteStmt).exec(0xa06c200, {0x828b3d0, 0x83966e0}, {0x83966e0, 0x0, 0x0})
        /media/sf_go/pkg/mod/github.com/mattn/go-sqlite3@v1.14.16/sqlite3.go:2046 +0x34b fp=0xa059b54 sp=0xa059ab4 pc=0x81585ab
github.com/mattn/go-sqlite3.(*SQLiteConn).exec(0xa070060, {0x828b3d0, 0x83966e0}, {0x82643eb, 0x9c}, {0x83966e0, 0x0, 0x0})
        /media/sf_go/pkg/mod/github.com/mattn/go-sqlite3@v1.14.16/sqlite3.go:877 +0x24d fp=0xa059c0c sp=0xa059b54 pc=0x814fccd
github.com/mattn/go-sqlite3.(*SQLiteConn).ExecContext(0xa070060, {0x828b3d0, 0x83966e0}, {0x82643eb, 0x9c}, {0x83966e0, 0x0, 0x0})
        /media/sf_go/pkg/mod/github.com/mattn/go-sqlite3@v1.14.16/sqlite3_go18.go:41 +0xe7 fp=0xa059c64 sp=0xa059c0c pc=0x8145f87
database/sql.ctxDriverExec({0x828b3d0, 0x83966e0}, {0xec75c010, 0xa070060}, {0x0, 0x0}, {0x82643eb, 0x9c}, {0x83966e0, 0x0, ...})
        /usr/local/go/src/database/sql/ctxutil.go:31 +0x8f fp=0xa059cb8 sp=0xa059c64 pc=0x812aedf
database/sql.(*DB).execDC.func2()
        /usr/local/go/src/database/sql/sql.go:1675 +0x150 fp=0xa059d24 sp=0xa059cb8 pc=0x8131cb0
database/sql.withLock({0x828b29c, 0xa000060}, 0xa059df8)
        /usr/local/go/src/database/sql/sql.go:3502 +0x84 fp=0xa059d40 sp=0xa059d24 pc=0x8139294
database/sql.(*DB).execDC(0xa07e120, {0x828b3d0, 0x83966e0}, 0xa000060, 0xa059e7c, {0x82643eb, 0x9c}, {0x0, 0x0, 0x0})
        /usr/local/go/src/database/sql/sql.go:1670 +0x24c fp=0xa059e44 sp=0xa059d40 pc=0x813173c
database/sql.(*DB).exec(0xa07e120, {0x828b3d0, 0x83966e0}, {0x82643eb, 0x9c}, {0x0, 0x0, 0x0}, 0x1)
        /usr/local/go/src/database/sql/sql.go:1655 +0xdc fp=0xa059e88 sp=0xa059e44 pc=0x81314bc
database/sql.(*DB).ExecContext.func1(0x1)
        /usr/local/go/src/database/sql/sql.go:1634 +0x7c fp=0xa059ed0 sp=0xa059e88 pc=0x81312dc
database/sql.(*DB).retry(0xa07e120, 0xa059f18)
        /usr/local/go/src/database/sql/sql.go:1538 +0x5f fp=0xa059ef8 sp=0xa059ed0 pc=0x81309cf
database/sql.(*DB).ExecContext(0xa07e120, {0x828b3d0, 0x83966e0}, {0x82643eb, 0x9c}, {0x0, 0x0, 0x0})
        /usr/local/go/src/database/sql/sql.go:1633 +0xae fp=0xa059f48 sp=0xa059ef8 pc=0x813121e
database/sql.(*DB).Exec(...)
        /usr/local/go/src/database/sql/sql.go:1647
main.main()
        /media/sf_go/src/tmp/main.go:17 +0xb3 fp=0xa059fa4 sp=0xa059f48 pc=0x815cb13
runtime.main()
        /usr/local/go/src/runtime/proc.go:267 +0x2dd fp=0xa059ff0 sp=0xa059fa4 pc=0x808a99d
runtime.goexit()
        /usr/local/go/src/runtime/asm_386.s:1363 +0x1 fp=0xa059ff4 sp=0xa059ff0 pc=0x80b7821

goroutine 2 [force gc (idle)]:
runtime.gopark(0x8264920, 0x8383ce8, 0x11, 0x14, 0x1)
        /usr/local/go/src/runtime/proc.go:398 +0x10c fp=0xa046fdc sp=0xa046fc8 pc=0x808ae4c
runtime.goparkunlock(...)
        /usr/local/go/src/runtime/proc.go:404
runtime.forcegchelper()
        /usr/local/go/src/runtime/proc.go:322 +0xd3 fp=0xa046ff0 sp=0xa046fdc pc=0x808ac93
runtime.goexit()
        /usr/local/go/src/runtime/asm_386.s:1363 +0x1 fp=0xa046ff4 sp=0xa046ff0 pc=0x80b7821
created by runtime.init.5 in goroutine 1
        /usr/local/go/src/runtime/proc.go:310 +0x23

goroutine 3 [GC sweep wait]:
runtime.gopark(0x8264920, 0x8383e90, 0xc, 0x14, 0x1)
        /usr/local/go/src/runtime/proc.go:398 +0x10c fp=0xa0477cc sp=0xa0477b8 pc=0x808ae4c
runtime.goparkunlock(...)
        /usr/local/go/src/runtime/proc.go:404
runtime.bgsweep(0xa020500)
        /usr/local/go/src/runtime/mgcsweep.go:280 +0x9b fp=0xa0477e8 sp=0xa0477cc pc=0x8075ddb
runtime.gcenable.func1()
        /usr/local/go/src/runtime/mgc.go:200 +0x27 fp=0xa0477f0 sp=0xa0477e8 pc=0x8067bd7
runtime.goexit()
        /usr/local/go/src/runtime/asm_386.s:1363 +0x1 fp=0xa0477f4 sp=0xa0477f0 pc=0x80b7821
created by runtime.gcenable in goroutine 1
        /usr/local/go/src/runtime/mgc.go:200 +0x77

goroutine 4 [GC scavenge wait]:
runtime.gopark(0x8264920, 0x8383f00, 0xd, 0x14, 0x2)
        /usr/local/go/src/runtime/proc.go:398 +0x10c fp=0xa047fb8 sp=0xa047fa4 pc=0x808ae4c
runtime.goparkunlock(...)
        /usr/local/go/src/runtime/proc.go:404
runtime.(*scavengerState).park(0x8383f00)
        /usr/local/go/src/runtime/mgcscavenge.go:425 +0x60 fp=0xa047fcc sp=0xa047fb8 pc=0x8073130
runtime.bgscavenge(0xa020500)
        /usr/local/go/src/runtime/mgcscavenge.go:653 +0x4b fp=0xa047fe8 sp=0xa047fcc pc=0x80737ab
runtime.gcenable.func2()
        /usr/local/go/src/runtime/mgc.go:201 +0x27 fp=0xa047ff0 sp=0xa047fe8 pc=0x8067b97
runtime.goexit()
        /usr/local/go/src/runtime/asm_386.s:1363 +0x1 fp=0xa047ff4 sp=0xa047ff0 pc=0x80b7821
created by runtime.gcenable in goroutine 1
        /usr/local/go/src/runtime/mgc.go:201 +0xb7

goroutine 5 [finalizer wait]:
runtime.gopark(0x8264898, 0x83967fc, 0x10, 0x14, 0x1)
        /usr/local/go/src/runtime/proc.go:398 +0x10c fp=0xa048798 sp=0xa048784 pc=0x808ae4c
runtime.runfinq()
        /usr/local/go/src/runtime/mfinal.go:193 +0xfc fp=0xa0487f0 sp=0xa048798 pc=0x8066d1c
runtime.goexit()
        /usr/local/go/src/runtime/asm_386.s:1363 +0x1 fp=0xa0487f4 sp=0xa0487f0 pc=0x80b7821
created by runtime.createfing in goroutine 1
        /usr/local/go/src/runtime/mfinal.go:163 +0x60

goroutine 6 [select]:
runtime.gopark(0x8264950, 0x0, 0x9, 0x18, 0x1)
        /usr/local/go/src/runtime/proc.go:398 +0x10c fp=0xa048ec4 sp=0xa048eb0 pc=0x808ae4c
runtime.selectgo(0xa048fcc, 0xa048fc4, 0x0, 0x0, 0x2, 0x1)
        /usr/local/go/src/runtime/select.go:327 +0xaca fp=0xa048fa4 sp=0xa048ec4 pc=0x809b7ea
database/sql.(*DB).connectionOpener(0xa07e120, {0x828b470, 0xa070030})
        /usr/local/go/src/database/sql/sql.go:1218 +0xab fp=0xa048fe0 sp=0xa048fa4 pc=0x812f1db
database/sql.OpenDB.func1()
        /usr/local/go/src/database/sql/sql.go:791 +0x35 fp=0xa048ff0 sp=0xa048fe0 pc=0x812d7b5
runtime.goexit()
        /usr/local/go/src/runtime/asm_386.s:1363 +0x1 fp=0xa048ff4 sp=0xa048ff0 pc=0x80b7821
created by database/sql.OpenDB in goroutine 1
        /usr/local/go/src/database/sql/sql.go:791 +0x15c

eax    0x0
ebx    0x8376d28
ecx    0x0
edx    0x1
edi    0x81ea0f0
esi    0x0
ebp    0x2
esp    0xffe05c60
eip    0x81ea110
eflags 0x10206
cs     0x23
fs     0x0
gs     0x63

Additional info

Behavior depending on different queries to Db.Exec()

(empty query)
db.Exec() result: {0xa4b0000 0xa4aa050}

CREATE TABLE 
db.Exec() error: incomplete input
db.Exec() result: <nil>

CREATE TABLE "my_table" 
db.Exec() error: incomplete input
db.Exec() result: <nil>

CREATE TABLE "my_table" (
db.Exec() error: incomplete input
db.Exec() result: <nil>

CREATE TABLE "my_table" ("mt_id"
db.Exec() error: incomplete input
db.Exec() result: <nil>

CREATE TABLE "my_table" ("mt_id" INTEGER
db.Exec() error: incomplete input
db.Exec() result: <nil>

CREATE TABLE "my_table" ("mt_id" INTEGER)
SIGSEGV: segmentation violation
PC=0x81eb510 m=0 sigcode=1
signal arrived during cgo execution
Template code for above log
    fmt.Print(`CREATE TABLE "my_table" ("mt_id" INTEGER NOT NULL);` + "\n")
    res, err = db.Exec(`CREATE TABLE "my_table" ("mt_id" INTEGER NOT NULL);`)
    if err != nil {
        fmt.Printf("db.Exec() error: %v\n", err)
    }
    fmt.Printf("db.Exec() result: %v\n\n", res)

ALSO!
If I register a my_table table with DB Browser for SQLite in advance and run the app again,
the log will look like the following.

(empty query)
db.Exec() result: {0x9d28000 0x9d24040}

CREATE TABLE 
db.Exec() error: incomplete input
db.Exec() result: <nil>

CREATE TABLE "my_table" 
db.Exec() error: incomplete input
db.Exec() result: <nil>

CREATE TABLE "my_table" (
db.Exec() error: table "my_table" already exists
db.Exec() result: <nil>

CREATE TABLE "my_table" ("mt_id"
db.Exec() error: table "my_table" already exists
db.Exec() result: <nil>

CREATE TABLE "my_table" ("mt_id" INTEGER
db.Exec() error: table "my_table" already exists
db.Exec() result: <nil>

CREATE TABLE "my_table" ("mt_id" INTEGER)
db.Exec() error: table "my_table" already exists
db.Exec() result: <nil>

CREATE TABLE "my_table" ("mt_id" INTEGER NOT NULL
db.Exec() error: table "my_table" already exists
db.Exec() result: <nil>

CREATE TABLE "my_table" ("mt_id" INTEGER NOT NULL)
db.Exec() error: table "my_table" already exists
db.Exec() result: <nil>

CREATE TABLE "my_table" ("mt_id" INTEGER NOT NULL);
db.Exec() error: table "my_table" already exists
db.Exec() result: <nil>

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Reproduce the crash with the reported Go 1.21.3 linux/386 setup and the CREATE TABLE call in main.go. Start at SQLiteStmt.execSync in sqlite3.go:2084 and the cgo call shown in the stack trace, then inspect the related SQLite C boundary. Done means valid CREATE TABLE statements return without SIGSEGV and existing error cases still report their errors.

Written by the indexing model from the issue text.

Assessment

Tech stack
c, go, sqlite
Domain
backend, database
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.