From: drh Date: Fri, 6 Apr 2007 01:03:32 +0000 (+0000) Subject: Make sure the sqlite3BtreePrevious() routine terminates properly if the X-Git-Tag: version-3.6.10~2352 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=8c4d3a6b42342f9b4b3757d520e1a00fd00abda1;p=thirdparty%2Fsqlite.git Make sure the sqlite3BtreePrevious() routine terminates properly if the table is deleted out from under it. Ticket #2286. This bug was discovered while trying to increase test coverage from 98.5% to 99% - once again showing the value of full coverage testing. (CVS 3818) FossilOrigin-Name: bebf8d2f886ed9fe1b96e4cb11ab3de2f2f7d2c8 --- diff --git a/manifest b/manifest index b0dffb7125..65b5ef8cea 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sthe\samalgamation\sso\sthat\sit\sworks\swith\s-DSQLITE_ENABLE_REDEF_IO.\s\sChange\ntclsqlite.c\sso\sthat\sit\scan\sbe\sappended\sto\sthe\samalgamation.\s\sCreate\sa\snew\namalgamation\sof\sheader\sfiles\sfor\suse\sby\sprojects\sthat\swant\sto\sredefine\stheir\nown\sI/O\sinterface\susing\s-DSQLITE_ENABLE_REDEF_IO.\s(CVS\s3817) -D 2007-04-05T21:58:33 +C Make\ssure\sthe\ssqlite3BtreePrevious()\sroutine\sterminates\sproperly\sif\sthe\ntable\sis\sdeleted\sout\sfrom\sunder\sit.\s\sTicket\s#2286.\s\sThis\sbug\swas\sdiscovered\nwhile\strying\sto\sincrease\stest\scoverage\sfrom\s98.5%\sto\s99%\s-\sonce\sagain\nshowing\sthe\svalue\sof\sfull\scoverage\stesting.\s(CVS\s3818) +D 2007-04-06T01:03:33 F Makefile.in a9bd493360a2b17e5214b69d8c32dd6cdaceaf55 F Makefile.linux-gcc 2d8574d1ba75f129aba2019f0b959db380a90935 F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028 @@ -58,7 +58,7 @@ F src/alter.c 2c79ec40f65e33deaf90ca493422c74586e481a3 F src/analyze.c 4bbf5ddf9680587c6d4917e02e378b6037be3651 F src/attach.c a16ada4a4654a0d126b8223ec9494ebb81bc5c3c F src/auth.c 902f4722661c796b97f007d9606bd7529c02597f -F src/btree.c 48fa58f2d71edeab4a7d08157abe50a0b7a0e489 +F src/btree.c 27299eba3ad5aa1fed184c707576d12d0e608e8d F src/btree.h 9b2cc0d113c0bc2d37d244b9a394d56948c9acbf F src/build.c 7c2efa468f0c404ef5aa648d43c383318390937f F src/callback.c 31d22b4919c7645cbcbb1591ce2453e8c677c558 @@ -271,7 +271,7 @@ F test/memdb.test a67bda4ff90a38f2b19f6c7f95aa7289e051d893 F test/memleak.test d2d2a1ff7105d32dc3fdf691458cf6cba58c7217 F test/minmax.test 66434d8ee04869fe4c220b665b73748accbb9163 F test/misc1.test 27a6ad11ba6e4b73aeee650ab68053ad7dfd0433 -F test/misc2.test 0b45deedcfd6ba857ea2f377c5669d3501a535c7 +F test/misc2.test d35faf7df27750d25ab656ca92dceebbd89f7368 F test/misc3.test 7bd937e2c62bcc6be71939faf068d506467b1e03 F test/misc4.test b043a05dea037cca5989f3ae09552fa16119bc80 F test/misc5.test c7d2d2a5a20dc37d3605a8067f0df5af2240122e @@ -451,7 +451,7 @@ F www/tclsqlite.tcl bb0d1357328a42b1993d78573e587c6dcbc964b9 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0 F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b F www/whentouse.tcl 97e2b5cd296f7d8057e11f44427dea8a4c2db513 -P 204e7d38aeb40d126b80a869958ca79cd0902d83 -R 33250e136d9f0af3693e864db67d12e7 +P f2caff870c81c08ec85aae72986c231ee986b251 +R 318b6ff1df8c9d65e7de849f673a3ac5 U drh -Z d3104f68e1b1c0abe9a9e14724db1ec1 +Z 3ae24a6bd11cbf91ba2afccd5e139cc3 diff --git a/manifest.uuid b/manifest.uuid index 99c6c33130..7aba490e7e 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -f2caff870c81c08ec85aae72986c231ee986b251 \ No newline at end of file +bebf8d2f886ed9fe1b96e4cb11ab3de2f2f7d2c8 \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index 2fa350a8ae..d2b9f3c104 100644 --- a/src/btree.c +++ b/src/btree.c @@ -9,7 +9,7 @@ ** May you share freely, never taking more than you give. ** ************************************************************************* -** $Id: btree.c,v 1.350 2007/04/02 05:07:47 danielk1977 Exp $ +** $Id: btree.c,v 1.351 2007/04/06 01:03:33 drh Exp $ ** ** This file implements a external (disk-based) database using BTrees. ** For a detailed discussion of BTrees, refer to @@ -3520,6 +3520,14 @@ int sqlite3BtreeNext(BtCursor *pCur, int *pRes){ if( rc!=SQLITE_OK ){ return rc; } +#endif + assert( pRes!=0 ); + pPage = pCur->pPage; + if( CURSOR_INVALID==pCur->eState ){ + *pRes = 1; + return SQLITE_OK; + } +#ifndef SQLITE_OMIT_SHARED_CACHE if( pCur->skip>0 ){ pCur->skip = 0; *pRes = 0; @@ -3528,12 +3536,6 @@ int sqlite3BtreeNext(BtCursor *pCur, int *pRes){ pCur->skip = 0; #endif - assert( pRes!=0 ); - pPage = pCur->pPage; - if( CURSOR_INVALID==pCur->eState ){ - *pRes = 1; - return SQLITE_OK; - } assert( pPage->isInit ); assert( pCur->idxnCell ); @@ -3588,6 +3590,12 @@ int sqlite3BtreePrevious(BtCursor *pCur, int *pRes){ if( rc!=SQLITE_OK ){ return rc; } +#endif + if( CURSOR_INVALID==pCur->eState ){ + *pRes = 1; + return SQLITE_OK; + } +#ifndef SQLITE_OMIT_SHARED_CACHE if( pCur->skip<0 ){ pCur->skip = 0; *pRes = 0; @@ -3596,11 +3604,6 @@ int sqlite3BtreePrevious(BtCursor *pCur, int *pRes){ pCur->skip = 0; #endif - if( CURSOR_INVALID==pCur->eState ){ - *pRes = 1; - return SQLITE_OK; - } - pPage = pCur->pPage; assert( pPage->isInit ); assert( pCur->idx>=0 ); diff --git a/test/misc2.test b/test/misc2.test index 1eaf62e379..63808d4513 100644 --- a/test/misc2.test +++ b/test/misc2.test @@ -13,7 +13,7 @@ # This file implements tests for miscellanous features that were # left out of other test files. # -# $Id: misc2.test,v 1.26 2006/09/29 14:01:07 drh Exp $ +# $Id: misc2.test,v 1.27 2007/04/06 01:03:34 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl @@ -253,6 +253,106 @@ do_test misc2-7.8 { execsql {SELECT * FROM t1} } {1 2 3 4 5 6 7 8 9 10} +# Repeat the tests 7.1 through 7.8 about but this time do the SELECTs +# in reverse order so that we exercise the sqlite3BtreePrev() routine +# instead of sqlite3BtreeNext() +# +do_test misc2-7.11 { + db close + file delete -force test.db + sqlite3 db test.db + execsql { + CREATE TABLE t1(x); + INSERT INTO t1 VALUES(1); + INSERT INTO t1 VALUES(2); + INSERT INTO t1 VALUES(3); + SELECT * FROM t1; + } +} {1 2 3} +do_test misc2-7.12 { + set rc [catch { + db eval {SELECT rowid FROM t1 ORDER BY rowid DESC} {} { + db eval "DELETE FROM t1 WHERE rowid=$rowid" + } + } msg] + lappend rc $msg +} {0 {}} +do_test misc2-7.13 { + execsql {SELECT * FROM t1} +} {} +do_test misc2-7.14 { + execsql { + DELETE FROM t1; + INSERT INTO t1 VALUES(1); + INSERT INTO t1 VALUES(2); + INSERT INTO t1 VALUES(3); + INSERT INTO t1 VALUES(4); + } + db eval {SELECT rowid, x FROM t1 ORDER BY rowid DESC} { + if {$x & 1} { + db eval {DELETE FROM t1 WHERE rowid=$rowid} + } + } + execsql {SELECT * FROM t1} +} {2 4} +do_test misc2-7.15 { + execsql { + DELETE FROM t1; + INSERT INTO t1 VALUES(1); + INSERT INTO t1 VALUES(2); + INSERT INTO t1 VALUES(3); + INSERT INTO t1 VALUES(4); + } + db eval {SELECT rowid, x FROM t1} { + if {$x & 1} { + db eval {DELETE FROM t1 WHERE rowid=$rowid+1} + } + } + execsql {SELECT * FROM t1} +} {1 3} +do_test misc2-7.16 { + execsql { + DELETE FROM t1; + INSERT INTO t1 VALUES(1); + INSERT INTO t1 VALUES(2); + INSERT INTO t1 VALUES(3); + INSERT INTO t1 VALUES(4); + } + db eval {SELECT rowid, x FROM t1 ORDER BY rowid DESC} { + if {$x & 1} { + db eval {DELETE FROM t1} + } + } + execsql {SELECT * FROM t1} +} {} +do_test misc2-7.17 { + execsql { + DELETE FROM t1; + INSERT INTO t1 VALUES(1); + INSERT INTO t1 VALUES(2); + INSERT INTO t1 VALUES(3); + INSERT INTO t1 VALUES(4); + } + db eval {SELECT rowid, x FROM t1 ORDER BY rowid DESC} { + if {$x & 1} { + db eval {UPDATE t1 SET x=x+100 WHERE rowid=$rowid} + } + } + execsql {SELECT * FROM t1} +} {101 2 103 4} +do_test misc2-7.18 { + execsql { + DELETE FROM t1; + INSERT INTO t1(rowid,x) VALUES(10,10); + } + db eval {SELECT rowid, x FROM t1 ORDER BY rowid DESC} { + if {$x>1} { + db eval {INSERT INTO t1(rowid,x) VALUES($x-1,$x-1)} + } + } + execsql {SELECT * FROM t1} +} {1 2 3 4 5 6 7 8 9 10} + db close file delete -force test.db sqlite3 db test.db