Skip to content

Commit 6cfe794

Browse files
authored
Merge pull request #115 from tailscale/alisdair/expandedsql-free
cgosqlite: fix memory leak in ExpandedSQL
2 parents 77567f4 + 1352947 commit 6cfe794

File tree

2 files changed

+34
-1
lines changed

2 files changed

+34
-1
lines changed

cgosqlite/cgosqlite.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,11 @@ func (stmt *Stmt) SQL() string {
222222
}
223223

224224
func (stmt *Stmt) ExpandedSQL() string {
225-
return C.GoString(C.sqlite3_expanded_sql(stmt.stmt.ptr()))
225+
// sqlite3_expanded_sql returns a string obtained by sqlite3_malloc, which
226+
// must be freed after use.
227+
cstr := C.sqlite3_expanded_sql(stmt.stmt.ptr())
228+
defer C.sqlite3_free(unsafe.Pointer(cstr))
229+
return C.GoString(cstr)
226230
}
227231

228232
func (stmt *Stmt) Reset() error {

sqlite_test.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1539,3 +1539,32 @@ func TestConnLogger_read_tx(t *testing.T) {
15391539
}
15401540
}
15411541
}
1542+
1543+
func TestExpandedSQL(t *testing.T) {
1544+
ctx := context.Background()
1545+
connector := Connector("file:"+t.TempDir()+"/test.db", nil, nil)
1546+
sqlConn, err := connector.Connect(ctx)
1547+
if err != nil {
1548+
t.Fatalf("Connect: %v", err)
1549+
}
1550+
conn := sqlConn.(*conn)
1551+
1552+
sqlStmt, err := conn.PrepareContext(ctx, "SELECT ? + ?")
1553+
if err != nil {
1554+
t.Fatalf("PrepareContext: %v", err)
1555+
}
1556+
stmt, ok := sqlStmt.(*stmt)
1557+
if !ok {
1558+
t.Fatalf("not a *stmt: %#v", stmt)
1559+
}
1560+
if err := stmt.bindAll([]driver.NamedValue{
1561+
{Ordinal: 1, Value: 6},
1562+
{Ordinal: 2, Value: 7},
1563+
}); err != nil {
1564+
t.Errorf("bindAll: %v", err)
1565+
}
1566+
1567+
if got, want := stmt.stmt.ExpandedSQL(), "SELECT 6 + 7"; got != want {
1568+
t.Errorf("wrong sql: got %q, want %q", got, want)
1569+
}
1570+
}

0 commit comments

Comments
 (0)