From 2b780b4a7fb3a4a06eb341184933d7c5691f4dda Mon Sep 17 00:00:00 2001 From: Patrick DeVivo Date: Mon, 25 Oct 2021 17:13:24 +0200 Subject: [PATCH] fix idxStr freeing issue (#898) uses snippet suggested by @rittneje https://github.com/mattn/go-sqlite3/issues/897#issuecomment-752162125 --- sqlite3_opt_vtable.go | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/sqlite3_opt_vtable.go b/sqlite3_opt_vtable.go index 8fd6cdf..4aae1d1 100644 --- a/sqlite3_opt_vtable.go +++ b/sqlite3_opt_vtable.go @@ -472,10 +472,21 @@ func goVBestIndex(pVTab unsafe.Pointer, icp unsafe.Pointer) *C.char { } info.idxNum = C.int(res.IdxNum) - idxStr := C.CString(res.IdxStr) - defer C.free(unsafe.Pointer(idxStr)) - info.idxStr = idxStr - info.needToFreeIdxStr = C.int(0) + info.idxStr = (*C.char)(C.sqlite3_malloc(C.int(len(res.IdxStr) + 1))) + if info.idxStr == nil { + // C.malloc and C.CString ordinarily do this for you. See https://golang.org/cmd/cgo/ + panic("out of memory") + } + info.needToFreeIdxStr = C.int(1) + + idxStr := *(*[]byte)(unsafe.Pointer(&reflect.SliceHeader{ + Data: uintptr(unsafe.Pointer(info.idxStr)), + Len: len(res.IdxStr) + 1, + Cap: len(res.IdxStr) + 1, + })) + copy(idxStr, res.IdxStr) + idxStr[len(idxStr)-1] = 0 // null-terminated string + if res.AlreadyOrdered { info.orderByConsumed = C.int(1) }