From: dan Date: Sat, 27 Sep 2014 18:18:32 +0000 (+0000) Subject: Fix a segfault in the sessions module that could follow an OOM. X-Git-Tag: version-3.13.0~148^2~106 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f05ac11214c082d4a849742f3e5c6246c4bf5106;p=thirdparty%2Fsqlite.git Fix a segfault in the sessions module that could follow an OOM. FossilOrigin-Name: 09985fa6b60a0bf38e23bbccd4d8e1d1cbf66124 --- diff --git a/ext/session/session9.test b/ext/session/session9.test index 3b42c31061..a9f61c872f 100644 --- a/ext/session/session9.test +++ b/ext/session/session9.test @@ -200,6 +200,7 @@ do_test 3.3 { do_test 3.3.1 { list [catch {sqlite3changeset_apply db $::ccdel1 conflict_handler} msg] $msg } {1 SQLITE_CONSTRAINT} + do_test 3.3.2 { list [catch {sqlite3changeset_apply db $::ccdel2 conflict_handler} msg] $msg } {1 SQLITE_CONSTRAINT} @@ -251,4 +252,37 @@ do_catchsql_test 4.3.2 { do_catchsql_test 4.3.3 { COMMIT } {0 {}} do_catchsql_test 4.3.4 { BEGIN ; COMMIT } {0 {}} +#-------------------------------------------------------------------- +# Test that if a DELETE change cannot be applied due to an +# SQLITE_CONSTRAINT error thrown by a trigger program, things do not +# go awry. + +drop_all_tables +reset_db +do_execsql_test 5.1 { + CREATE TABLE x1(x PRIMARY KEY, y); + CREATE TABLE x2(x PRIMARY KEY, y); + INSERT INTO x2 VALUES(1, 1); + INSERT INTO x1 VALUES(1, 1); +} + +set ::cc [changeset_from_sql { DELETE FROM x1; }] + +do_execsql_test 5.2 { + INSERT INTO x1 VALUES(1, 1); + CREATE TRIGGER tr1 AFTER DELETE ON x1 BEGIN + INSERT INTO x2 VALUES(old.x, old.y); + END; +} {} + +proc conflict_handler {args} { return "ABORT" } +do_test 5.3 { + list [catch {sqlite3changeset_apply db $::cc conflict_handler} msg] $msg +} {1 SQLITE_ABORT} + +do_execsql_test 5.4 { + SELECT * FROM X1; +} {1 1} + finish_test + diff --git a/ext/session/sessionA.test b/ext/session/sessionA.test index 1ca0f13709..8ee2046519 100644 --- a/ext/session/sessionA.test +++ b/ext/session/sessionA.test @@ -9,8 +9,7 @@ # #*********************************************************************** # -# This file tests that the sessions module handles foreign key constraint -# violations when applying changesets as required. +# This file tests that filter callbacks work as required. # if {![info exists testdir]} { @@ -63,6 +62,46 @@ do_test 2.1 { } db2 } {a b e f} +#------------------------------------------------------------------------- +# Test that filter callbacks passed to sqlite3changeset_apply() are +# invoked correctly. +# +reset_db +do_execsql_test 3.1 { + CREATE TABLE t1(a PRIMARY KEY, b); + CREATE TABLE t2(x PRIMARY KEY, y); +} + +do_test 3.2 { + execsql BEGIN + set ::cs [changeset_from_sql { + INSERT INTO t1 VALUES(1, 2); + INSERT INTO t2 VALUES('x', 'y'); + }] + execsql ROLLBACK + set {} {} +} {} + +proc filter {x y} { + return [string equal $x $y] +} + +do_test 3.3 { + sqlite3changeset_apply db $::cs {} [list filter t1] + execsql { + SELECT * FROM t1; + SELECT * FROM t2; + } +} {1 2} + +do_test 3.4 { + execsql { DELETE FROM t1 } + sqlite3changeset_apply db $::cs {} [list filter t2] + execsql { + SELECT * FROM t1; + SELECT * FROM t2; + } +} {x y} finish_test diff --git a/ext/session/sessionfault.test b/ext/session/sessionfault.test index c94589e372..39f27bfe6d 100644 --- a/ext/session/sessionfault.test +++ b/ext/session/sessionfault.test @@ -285,6 +285,38 @@ do_faultsim_test 5.2 -faults oom-tra* -body { } } +catch {db close} +catch {db2 close} +forcedelete test.db +sqlite3 db test.db +set abc [string repeat abc 256] +set def [string repeat def 256] +execsql " + CREATE TABLE t2(a PRIMARY KEY, b); + INSERT INTO t2 VALUES(1, '$abc'); +" +set changeset [changeset_from_sql " + INSERT INTO t2 VALUES(2, '$def'); + DELETE FROM t2 WHERE a = 1; +"] +db close + +do_faultsim_test 5.3 -faults oom-tra* -body { + set ::inverse [sqlite3changeset_invert $::changeset] + set {} {} +} -test { + faultsim_test_result {0 {}} {1 SQLITE_NOMEM} + if {$testrc==0} { + set x [list] + sqlite3session_foreach c $::inverse { lappend x $c } + foreach c " + {INSERT t2 0 X. {} {i 1 t $::abc}} + {DELETE t2 0 X. {i 2 t $::def} {}} + " { lappend y $c } + if {$x != $y} { error "changeset no good" } + } +} + #------------------------------------------------------------------------- # Test that OOM errors in sqlite3changeset_concat() are handled correctly. # @@ -515,7 +547,41 @@ do_faultsim_test 10 -faults oom-tra* -prep { } } +#------------------------------------------------------------------------- +# Test an OOM with an sqlite3changeset_apply() filter callback. +# +reset_db +do_test 11.prep { + execsql { + CREATE TABLE t1(a PRIMARY KEY, b); + CREATE TABLE t2(x PRIMARY KEY, y); + BEGIN; + } + + set ::cs [changeset_from_sql { + INSERT INTO t1 VALUES(1, 2); + INSERT INTO t2 VALUES('x', 'y'); + }] + + execsql ROLLBACK + set {} {} +} {} +proc filter {x} { return [string equal t1 $x] } +faultsim_save_and_close + +do_faultsim_test 11 -faults oom-tra* -prep { + faultsim_restore_and_reopen +} -body { + sqlite3changeset_apply db $::cs {} filter +} -test { + faultsim_test_result {0 {}} {1 SQLITE_NOMEM} + if {$testrc==0} { + if {[db eval {SELECT * FROM t1 UNION ALL SELECT * FROM t2}] != "1 2"} { + error "data does not look right" + } + } +} finish_test diff --git a/ext/session/sqlite3session.c b/ext/session/sqlite3session.c index 7e69be4cc4..ed8d851083 100644 --- a/ext/session/sqlite3session.c +++ b/ext/session/sqlite3session.c @@ -3495,6 +3495,10 @@ static int sessionChangesetApply( schemaMismatch = (xFilter && (0==xFilter(pCtx, zNew))); if( schemaMismatch ){ zTab = sqlite3_mprintf("%s", zNew); + if( zTab==0 ){ + rc = SQLITE_NOMEM; + break; + } nTab = (int)strlen(zTab); sApply.azCol = (const char **)zTab; }else{ diff --git a/manifest b/manifest index 4cb1bee75c..0d58beec13 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\ssegfault\sin\sthe\sstreaming\sAPI\sfunctions\striggered\sby\sa\svery\slong\stable\sname. -D 2014-09-27T16:33:09.345 +C Fix\sa\ssegfault\sin\sthe\ssessions\smodule\sthat\scould\sfollow\san\sOOM. +D 2014-09-27T18:18:32.969 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in dd5f245aa8c741bc65845747203c8ce2f3fb6c83 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -153,12 +153,12 @@ F ext/session/session4.test a6ed685da7a5293c5d6f99855bcf41dbc352ca84 F ext/session/session5.test 8fdfaf9dba28a2f1c6b89b06168bdab1fef2d478 F ext/session/session6.test 443789bc2fca12e4f7075cf692c60b8a2bea1a26 F ext/session/session8.test 7d35947ad329b8966f095d34f9617a9eff52dc65 -F ext/session/session9.test 776e46785c29c11cda01f5205d0f1e8f8f9a46bf -F ext/session/sessionA.test eb05c13e4ef1ca8046a3a6dbf2d5f6f5b04a11d4 +F ext/session/session9.test b6dd1086de8c59b6f129923425487791f51c689c +F ext/session/sessionA.test 5543846eb9ca045217262f5d8c9376ce812e1ba5 F ext/session/sessionB.test d4ac901b43d4922a17dff08bbaa2f5354487ce4d F ext/session/session_common.tcl 1539d8973b2aea0025c133eb0cc4c89fcef541a5 -F ext/session/sessionfault.test cf9758bfb6ccd5db5f09f170667a8cea1ac8afa7 -F ext/session/sqlite3session.c 228cca8fdb6fd07942be097c516f22e39ec39e3c +F ext/session/sessionfault.test bef044d0952c0d62c31c8d2400be72c8684545cc +F ext/session/sqlite3session.c 0691b8d7434edb07166828778540bb418a7a68e3 F ext/session/sqlite3session.h b57009fb88835cc4684376bd3eae0d6ab364968a F ext/session/test_session.c 56a4ddd443b571c8d365b03197c032bdaed1443a F ext/userauth/sqlite3userauth.h 19cb6f0e31316d0ee4afdfb7a85ef9da3333a220 @@ -1216,7 +1216,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P bfc8bd80f8b225cebc66478448510ce84223ae7d -R 9ca53892e63f9c31475266a6b3e34d34 +P d2642543eed54da1ac0f757d43dd4d72482eb752 +R 7328e4de54076fa7989cf4f3b00a08d8 U dan -Z f7759b84adfee5a6c178fa61db492ce5 +Z 371024a806f6988dfc33105901bfbbae diff --git a/manifest.uuid b/manifest.uuid index 903686ec1f..d5a74ccbec 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -d2642543eed54da1ac0f757d43dd4d72482eb752 \ No newline at end of file +09985fa6b60a0bf38e23bbccd4d8e1d1cbf66124 \ No newline at end of file