From bdab31cc98cdf61a93567c55e85e835ba6fb364f Mon Sep 17 00:00:00 2001 From: Joe Shaw Date: Thu, 27 Oct 2016 16:44:56 -0700 Subject: [PATCH] fix double free in SQLiteBackup.Close() on error The sqlite3_backup_finish() function never fails, it just returns the error code from previous operations. Previously if it returned an error, the finalizer wouldn't be unset and sqlite3_backup_finish() would be run again on an already-finished backup. This results in a double-free and often segfaults. The error handling is described in more detail in the "Error handling" section of https://www.sqlite.org/backup.html. --- backup.go | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/backup.go b/backup.go index 4c1e38c..05f8038 100644 --- a/backup.go +++ b/backup.go @@ -65,10 +65,15 @@ func (b *SQLiteBackup) Finish() error { func (b *SQLiteBackup) Close() error { ret := C.sqlite3_backup_finish(b.b) + + // sqlite3_backup_finish() never fails, it just returns the + // error code from previous operations, so clean up before + // checking and returning an error + b.b = nil + runtime.SetFinalizer(b, nil) + if ret != 0 { return Error{Code: ErrNo(ret)} } - b.b = nil - runtime.SetFinalizer(b, nil) return nil }