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.
This commit is contained in:
Joe Shaw 2016-10-27 16:44:56 -07:00
parent e5a3c16c5c
commit bdab31cc98
1 changed files with 7 additions and 2 deletions

View File

@ -65,10 +65,15 @@ func (b *SQLiteBackup) Finish() error {
func (b *SQLiteBackup) Close() error { func (b *SQLiteBackup) Close() error {
ret := C.sqlite3_backup_finish(b.b) 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 { if ret != 0 {
return Error{Code: ErrNo(ret)} return Error{Code: ErrNo(ret)}
} }
b.b = nil
runtime.SetFinalizer(b, nil)
return nil return nil
} }