@@ -314,3 +314,45 @@ test('backup has correct name and length', (t) => {
314314 t . assert . strictEqual ( backup . name , 'backup' ) ;
315315 t . assert . strictEqual ( backup . length , 2 ) ;
316316} ) ;
317+
318+ test ( 'source database is kept alive while a backup is in flight' , async ( t ) => {
319+ // Regression test: previously, BackupJob stored a raw DatabaseSync* and the
320+ // source could be garbage-collected while the backup was still running,
321+ // leading to a use-after-free when BackupJob::Finalize() dereferenced the
322+ // stale pointer via source_->RemoveBackup(this).
323+ const destDb = nextDb ( ) ;
324+
325+ let database = makeSourceDb ( ) ;
326+ // Insert enough rows to ensure the backup takes multiple steps.
327+ const insert = database . prepare ( 'INSERT INTO data (key, value) VALUES (?, ?)' ) ;
328+ for ( let i = 3 ; i <= 500 ; i ++ ) {
329+ insert . run ( i , 'A' . repeat ( 1024 ) + i ) ;
330+ }
331+
332+ const p = backup ( database , destDb , {
333+ rate : 1 ,
334+ progress ( ) { } ,
335+ } ) ;
336+ // Drop the last strong JS reference to the source database. With the bug,
337+ // the DatabaseSync could be collected here and the in-flight backup would
338+ // later crash while accessing the freed source.
339+ database = null ;
340+
341+ // Nudge the GC aggressively, but the backup must keep the source alive
342+ // regardless. Without the fix, the source DatabaseSync would be collected
343+ // and BackupJob::Finalize() would crash the process.
344+ if ( typeof global . gc === 'function' ) {
345+ for ( let i = 0 ; i < 5 ; i ++ ) {
346+ global . gc ( ) ;
347+ await new Promise ( ( resolve ) => setImmediate ( resolve ) ) ;
348+ }
349+ }
350+
351+ const totalPages = await p ;
352+ t . assert . ok ( totalPages > 0 ) ;
353+
354+ const backupDb = new DatabaseSync ( destDb ) ;
355+ t . after ( ( ) => { backupDb . close ( ) ; } ) ;
356+ const rows = backupDb . prepare ( 'SELECT COUNT(*) AS n FROM data' ) . get ( ) ;
357+ t . assert . strictEqual ( rows . n , 500 ) ;
358+ } ) ;
0 commit comments