From: dan Date: Thu, 11 Dec 2014 16:38:18 +0000 (+0000) Subject: Fix a race condition to do with very large index keys in shared-cache mode. X-Git-Tag: version-3.8.8~93 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=857536623a7cf447c028ca1d9fd251fdbcf9ea0b;p=thirdparty%2Fsqlite.git Fix a race condition to do with very large index keys in shared-cache mode. FossilOrigin-Name: fc157dd7f18c94b7ae5f155e1b4a5d7714b7da8c --- diff --git a/manifest b/manifest index 17ec6c7d04..69fe030103 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\stypo\sin\sthe\sdocumentation\sfor\ssqlite3_threadsafe(). -D 2014-12-11T15:27:04.851 +C Fix\sa\srace\scondition\sto\sdo\swith\svery\slarge\sindex\skeys\sin\sshared-cache\smode. +D 2014-12-11T16:38:18.086 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 6c4f961fa91d0b4fa121946a19f9e5eac2f2f809 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -173,7 +173,7 @@ F src/auth.c b56c78ebe40a2110fd361379f7e8162d23f92240 F src/backup.c 7ddee9c7d505e07e959a575b18498f17c71e53ea F src/bitvec.c 19a4ba637bd85f8f63fc8c9bae5ade9fb05ec1cb F src/btmutex.c 49ca66250c7dfa844a4d4cb8272b87420d27d3a5 -F src/btree.c ea6692ce58bfba55b12c75d2947fec0906d1ef7a +F src/btree.c ab4b60fcf9920d862ff4d96efb1d605e4e7701a0 F src/btree.h e31a3a3ebdedb1caf9bda3ad5dbab3db9b780f6e F src/btreeInt.h 3363e18fd76f69a27a870b25221b2345b3fd4d21 F src/build.c 67bb05b1077e0cdaccb2e36bfcbe7a5df9ed31e8 @@ -294,7 +294,7 @@ F src/vacuum.c 9b30ec729337dd012ed88d4c292922c8ef9cf00c F src/vdbe.c 1a9e671c9cfc259e4d2affc71f7df4a4c00a842c F src/vdbe.h 6fc69d9c5e146302c56e163cb4b31d1ee64a18c3 F src/vdbeInt.h 9bb69ff2447c34b6ccc58b34ec35b615f86ead78 -F src/vdbeapi.c 07acb615d1e4170e71fc1b0d087f3c53a1ad8e83 +F src/vdbeapi.c f8dd2d33a30938188fc292d524e88a91f2e65887 F src/vdbeaux.c 6f7f39c3fcf0f5923758df8561bb5d843908a553 F src/vdbeblob.c 4af4bfb71f6df7778397b4a0ebc1879793276778 F src/vdbemem.c 31d8eabb0cd78bfeab4e5124c7363c3e9e54db9f @@ -912,7 +912,7 @@ F test/thread2.test f35d2106452b77523b3a2b7d1dcde2e5ee8f9e46 F test/thread_common.tcl 334639cadcb9f912bf82aa73f49efd5282e6cadd F test/threadtest1.c 6029d9c5567db28e6dc908a0c63099c3ba6c383b F test/threadtest2.c ace893054fa134af3fc8d6e7cfecddb8e3acefb9 -F test/threadtest3.c fca8d360b470405ae3ed431b5cb4cdf031f85a74 +F test/threadtest3.c 2b6e07e915c383c250a5b531cf6ef163a3047d7e F test/tkt-02a8e81d44.test 6c80d9c7514e2a42d4918bf87bf6bc54f379110c F test/tkt-26ff0c2d1e.test 888324e751512972c6e0d1a09df740d8f5aaf660 F test/tkt-2a5629202f.test 0521bd25658428baa26665aa53ffed9367d33af2 @@ -1076,7 +1076,8 @@ F test/triggerC.test a68980c5955d62ee24be6f97129d824f199f9a4c F test/triggerD.test 8e7f3921a92a5797d472732108109e44575fa650 F test/triggerE.test 355e9c5cbaed5cd039a60baad1fb2197caeb8e52 F test/tt3_checkpoint.c 415eccce672d681b297485fc20f44cdf0eac93af -F test/tt3_index.c 2e7f3151a0ae522f031e8e2761ca2bda63f4d221 +F test/tt3_index.c 14f4b0cc3f4c05353e25778cf531c9d6e3b0d27f +F test/tt3_lookaside1.c 0b5b79ba37f21a1eb849cd4a54eed367f4d4aaaf F test/types.test bf816ce73c7dfcfe26b700c19f97ef4050d194ff F test/types2.test 3555aacf8ed8dc883356e59efc314707e6247a84 F test/types3.test 99e009491a54f4dc02c06bdbc0c5eea56ae3e25a @@ -1227,7 +1228,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 d9f916ba09f1a61684b4d59548ab6cf71cdb6a37 -R be485ee74d8699a155e9699a0ceccb5f -U drh -Z 8b7cdafef867d0fe5e1164d6f32f45ce +P 258e747bb7e3a2bc46f932cc2b06c2689d43aeb0 +R 016d1b9c16d412ff926cdf599ae97f64 +U dan +Z 8da7cca75b292da60a4687ff246cc6b3 diff --git a/manifest.uuid b/manifest.uuid index de0c011b0b..0de4da3602 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -258e747bb7e3a2bc46f932cc2b06c2689d43aeb0 \ No newline at end of file +fc157dd7f18c94b7ae5f155e1b4a5d7714b7da8c \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index 4283d00fd3..a73c831219 100644 --- a/src/btree.c +++ b/src/btree.c @@ -3913,7 +3913,7 @@ int sqlite3BtreeCloseCursor(BtCursor *pCur){ releasePage(pCur->apPage[i]); } unlockBtreeIfUnused(pBt); - sqlite3DbFree(pBtree->db, pCur->aOverflow); + sqlite3_free(pCur->aOverflow); /* sqlite3_free(pCur); */ sqlite3BtreeLeave(pBtree); } @@ -4208,6 +4208,7 @@ static int accessPayload( offset -= pCur->info.nLocal; } + if( rc==SQLITE_OK && amt>0 ){ const u32 ovflSize = pBt->usableSize - 4; /* Bytes content per ovfl page */ Pgno nextPage; @@ -4225,8 +4226,8 @@ static int accessPayload( if( eOp!=2 && (pCur->curFlags & BTCF_ValidOvfl)==0 ){ int nOvfl = (pCur->info.nPayload-pCur->info.nLocal+ovflSize-1)/ovflSize; if( nOvfl>pCur->nOvflAlloc ){ - Pgno *aNew = (Pgno*)sqlite3DbRealloc( - pCur->pBtree->db, pCur->aOverflow, nOvfl*2*sizeof(Pgno) + Pgno *aNew = (Pgno*)sqlite3Realloc( + pCur->aOverflow, nOvfl*2*sizeof(Pgno) ); if( aNew==0 ){ rc = SQLITE_NOMEM; @@ -4273,6 +4274,7 @@ static int accessPayload( */ assert( eOp!=2 ); assert( pCur->curFlags & BTCF_ValidOvfl ); + assert( pCur->pBtree->db==pBt->db ); if( pCur->aOverflow[iIdx+1] ){ nextPage = pCur->aOverflow[iIdx+1]; }else{ diff --git a/src/vdbeapi.c b/src/vdbeapi.c index 5744c28632..c611688193 100644 --- a/src/vdbeapi.c +++ b/src/vdbeapi.c @@ -580,7 +580,6 @@ int sqlite3_step(sqlite3_stmt *pStmt){ ** sqlite3_errmsg() and sqlite3_errcode(). */ const char *zErr = (const char *)sqlite3_value_text(db->pErr); - assert( zErr!=0 || db->mallocFailed ); sqlite3DbFree(db, v->zErrMsg); if( !db->mallocFailed ){ v->zErrMsg = sqlite3DbStrDup(db, zErr); diff --git a/test/threadtest3.c b/test/threadtest3.c index 084ca022a9..afa4197ee2 100644 --- a/test/threadtest3.c +++ b/test/threadtest3.c @@ -1398,6 +1398,7 @@ static void dynamic_triggers(int nMs){ #include "tt3_checkpoint.c" #include "tt3_index.c" +#include "tt3_lookaside1.c" int main(int argc, char **argv){ struct ThreadTest { @@ -1419,6 +1420,7 @@ int main(int argc, char **argv){ { checkpoint_starvation_2, "checkpoint_starvation_2", 10000 }, { create_drop_index_1, "create_drop_index_1", 10000 }, + { lookaside1, "lookaside1", 10000 }, }; int i; diff --git a/test/tt3_index.c b/test/tt3_index.c index b79768c6c7..4bad64aabc 100644 --- a/test/tt3_index.c +++ b/test/tt3_index.c @@ -67,8 +67,8 @@ static void create_drop_index_1(int nMs){ launch_thread(&err, &threads, create_drop_index_thread, 0); launch_thread(&err, &threads, create_drop_index_thread, 0); launch_thread(&err, &threads, create_drop_index_thread, 0); - sqlite3_enable_shared_cache(0); join_all_threads(&err, &threads); + sqlite3_enable_shared_cache(0); print_and_free_err(&err); } diff --git a/test/tt3_lookaside1.c b/test/tt3_lookaside1.c new file mode 100644 index 0000000000..486de808cd --- /dev/null +++ b/test/tt3_lookaside1.c @@ -0,0 +1,99 @@ +/* +** 2014 December 9 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** +** lookaside1 +*/ + +/* +** The test in this file attempts to expose a specific race condition +** that is suspected to exist at time of writing. +*/ + +static char *lookaside1_thread_reader(int iTid, int iArg){ + Error err = {0}; /* Error code and message */ + Sqlite db = {0}; /* SQLite database connection */ + + opendb(&err, &db, "test.db", 0); + + while( !timetostop(&err) ){ + sqlite3_stmt *pStmt = 0; + int rc; + + sqlite3_prepare_v2(db.db, "SELECT 1 FROM t1", -1, &pStmt, 0); + while( sqlite3_step(pStmt)==SQLITE_ROW ){ + execsql(&err, &db, "SELECT length(x||y||z) FROM t2"); + } + rc = sqlite3_finalize(pStmt); + if( err.rc==SQLITE_OK && rc!=SQLITE_OK ){ + sqlite_error(&err, &db, "finalize"); + } + } + + closedb(&err, &db); + print_and_free_err(&err); + return sqlite3_mprintf("ok"); +} + +static char *lookaside1_thread_writer(int iTid, int iArg){ + Error err = {0}; /* Error code and message */ + Sqlite db = {0}; /* SQLite database connection */ + + opendb(&err, &db, "test.db", 0); + + do{ + sql_script(&err, &db, + "BEGIN;" + "UPDATE t3 SET i=i+1 WHERE x=1;" + "ROLLBACK;" + ); + }while( !timetostop(&err) ); + + closedb(&err, &db); + print_and_free_err(&err); + return sqlite3_mprintf("ok"); +} + + +static void lookaside1(int nMs){ + Error err = {0}; + Sqlite db = {0}; + Threadset threads = {0}; + + opendb(&err, &db, "test.db", 1); + sql_script(&err, &db, + "CREATE TABLE t1(x PRIMARY KEY) WITHOUT ROWID;" + "WITH data(x,y) AS (" + " SELECT 1, quote(randomblob(750)) UNION ALL " + " SELECT x*2, y||y FROM data WHERE x<5) " + "INSERT INTO t1 SELECT y FROM data;" + + "CREATE TABLE t3(x PRIMARY KEY,i) WITHOUT ROWID;" + "INSERT INTO t3 VALUES(1, 1);" + + "CREATE TABLE t2(x,y,z);" + "INSERT INTO t2 VALUES(randomblob(50), randomblob(50), randomblob(50));" + ); + closedb(&err, &db); + + setstoptime(&err, nMs); + + sqlite3_enable_shared_cache(1); + launch_thread(&err, &threads, lookaside1_thread_reader, 0); + launch_thread(&err, &threads, lookaside1_thread_reader, 0); + launch_thread(&err, &threads, lookaside1_thread_reader, 0); + launch_thread(&err, &threads, lookaside1_thread_reader, 0); + launch_thread(&err, &threads, lookaside1_thread_reader, 0); + launch_thread(&err, &threads, lookaside1_thread_writer, 0); + join_all_threads(&err, &threads); + sqlite3_enable_shared_cache(0); + print_and_free_err(&err); +}