From: drh <> Date: Wed, 10 Nov 2021 10:59:10 +0000 (+0000) Subject: Make SQLITE_CORRUPT sticky: If a CORRUPT error is returned, all subsequent X-Git-Tag: version-3.37.0~38 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=46c425b4dd4e0e6371d8794b671135593d2ddf8c;p=thirdparty%2Fsqlite.git Make SQLITE_CORRUPT sticky: If a CORRUPT error is returned, all subsequent write statements within the same transaction also fail early with SQLITE_CORRUPT. FossilOrigin-Name: 3feb0f1c3840904d28fc9a61262820e2b9b764addc1dd178aecc2cd0f952042c --- diff --git a/manifest b/manifest index 944f5f2d29..f23b2c55dd 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Change\stest\scase\serror\smessage\stext\sto\smatch\sthe\scurrent\simplementation. -D 2021-11-09T13:31:42.748 +C Make\sSQLITE_CORRUPT\ssticky:\s\sIf\sa\sCORRUPT\serror\sis\sreturned,\sall\ssubsequent\nwrite\sstatements\swithin\sthe\ssame\stransaction\salso\sfail\searly\swith\nSQLITE_CORRUPT. +D 2021-11-10T10:59:10.748 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -491,7 +491,7 @@ F src/auth.c f4fa91b6a90bbc8e0d0f738aa284551739c9543a367071f55574681e0f24f8cf F src/backup.c 3014889fa06e20e6adfa0d07b60097eec1f6e5b06671625f476a714d2356513d F src/bitvec.c 7c849aac407230278445cb069bebc5f89bf2ddd87c5ed9459b070a9175707b3d F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6 -F src/btree.c 2c8a52a7fd84b1aec4a79e7861b6368aecbf011a43247cc7d9a2946c7f0ae5ea +F src/btree.c 6fd5c54a2edec870a0ba0c2c8b28577bf587e05a6f183da6febe09e3700ded6f F src/btree.h 74d64b8f28cfa4a894d14d4ed64fa432cd697b98b61708d4351482ae15913e22 F src/btreeInt.h ee9348c4cb9077243b049edc93a82c1f32ca48baeabf2140d41362b9f9139ff7 F src/build.c 1b41a6417e5bb260a5988588764863229905b07b3e9a47878030a1c92d49010f @@ -514,7 +514,7 @@ F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71 F src/insert.c 7fcbbe9114ac402ea3c0c6a3810f13fc89cae8131ea1659ec472be7caac10192 F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa F src/loadext.c e1dcff1c916bf6834e150b492eddda5d9792453182d2ad64294d2266b6e93c4c -F src/main.c 5ed1babdec5bbf935fb4586fcb12debbff760c301948ac46cf90e720b4405a8b +F src/main.c 7bd4fdc41ef53535271a1816ff043ba153cda03842b444b6e2f57b27b2cb9090 F src/malloc.c ef796bcc0e81d845d59a469f1cf235056caf9024172fd524e32136e65593647b F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de @@ -555,7 +555,7 @@ F src/shell.c.in f8854bcb0d14707d661732698d5210d7f01694000c46e8014b323ad18f575be F src/sqlite.h.in 5cd209ac7dc4180f0e19292846f40440b8488015849ca0110c70b906b57d68f0 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 8ff2fd2c166150b2e48639f5e506fb44e29f1a3f65031710b9e89d1c126ac839 -F src/sqliteInt.h 8e770859062a87254dabd183b3f7bd29f89fd5905515beac00877958e88e06ce +F src/sqliteInt.h c36cdf01fcd624f9988305158e89bf1d7246b3a05f0fe578bc7dd2507e53e59d F src/sqliteLimit.h d7323ffea5208c6af2734574bae933ca8ed2ab728083caa117c9738581a31657 F src/status.c 4b8bc2a6905163a38b739854a35b826c737333fab5b1f8e03fa7eb9a4799c4c1 F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1 @@ -622,7 +622,7 @@ F src/upsert.c 8789047a8f0a601ea42fa0256d1ba3190c13746b6ba940fe2d25643a7e991937 F src/utf.c ee39565f0843775cc2c81135751ddd93eceb91a673ea2c57f61c76f288b041a0 F src/util.c 30df8356e231dad33be10bb27897655002668343280004ba28c734489414a167 F src/vacuum.c 6c38ddc52f0619865c91dae9c441d4d48bf3040d7dc1bc5b22da1e45547ed0b3 -F src/vdbe.c f2b30e312d2dc69d429998f17fab74298a4d9ed8c6d57c0d23d0284414c6ea1b +F src/vdbe.c 34a0bc8b9e934523fd528885689334821d7a1d7048e739a32801a810ac848c39 F src/vdbe.h 25dabb25c7e157b84e59260cfb5b466c3ac103ede9f36f4db371332c47601abe F src/vdbeInt.h 31fbabdc1ed61d9695337dfe5269ea94e1cf615c17f5cafeaa1bb01066820bab F src/vdbeapi.c f4bd14b42d9717a35baac5f20c0c4bfccbf3691d64dc6ec02fc0ef19374d3c92 @@ -1932,7 +1932,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P ba4fb51853fbcb8c142a350b4db0d59153f28ba0a63ad9a2d6fea7096d3dd544 -R 53a575150d86630b94dc195691567d17 +P de10795a1cf70925088e9652998e813665b2e147ffa4a4edab18c7e2c66bf5ae +R e127d9e9bc185c201fc0d430c0552522 U drh -Z 2471e2a59037263eea8aada9ef5e2a3c +Z 644a270e60b1b5e3bf9aa34104968aa1 diff --git a/manifest.uuid b/manifest.uuid index 72257e642d..ec8cdc26ad 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -de10795a1cf70925088e9652998e813665b2e147ffa4a4edab18c7e2c66bf5ae \ No newline at end of file +3feb0f1c3840904d28fc9a61262820e2b9b764addc1dd178aecc2cd0f952042c \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index 67611c3bf5..49f80b5b39 100644 --- a/src/btree.c +++ b/src/btree.c @@ -1488,7 +1488,7 @@ static int defragmentPage(MemPage *pPage, int nMaxFrag){ if( iFree2+sz2 > usableSize ) return SQLITE_CORRUPT_PAGE(pPage); memmove(&data[iFree+sz+sz2], &data[iFree+sz], iFree2-(iFree+sz)); sz += sz2; - }else if( iFree+sz>usableSize ){ + }else if( NEVER(iFree+sz>usableSize) ){ return SQLITE_CORRUPT_PAGE(pPage); } @@ -7111,7 +7111,7 @@ static int rebuildPage( assert( i(u32)usableSize ){ j = 0; } + if( NEVER(j>(u32)usableSize) ){ j = 0; } memcpy(&pTmp[j], &aData[j], usableSize - j); for(k=0; pCArray->ixNx[k]<=i && ALWAYS(kpDbPage)!=1 || pPage->isInit ){ + if( sqlite3PagerPageRefcount(pPage->pDbPage)!=1 || NEVER(pPage->isInit) ){ rc = SQLITE_CORRUPT_BKPT; }else{ if( iOffset+ovflPageSize<(u32)nTotal ){ diff --git a/src/main.c b/src/main.c index 7eb42f7ae4..4b2d0592c9 100644 --- a/src/main.c +++ b/src/main.c @@ -1460,7 +1460,7 @@ void sqlite3RollbackAll(sqlite3 *db, int tripCode){ /* Any deferred constraint violations have now been resolved. */ db->nDeferredCons = 0; db->nDeferredImmCons = 0; - db->flags &= ~(u64)SQLITE_DeferFKs; + db->flags &= ~(u64)(SQLITE_DeferFKs|SQLITE_CorruptRdOnly); /* If one has been configured, invoke the rollback-hook callback */ if( db->xRollbackCallback && (inTrans || !db->autoCommit) ){ diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 75f3bfca2d..cece2360e8 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -1712,6 +1712,7 @@ struct sqlite3 { #define SQLITE_CountRows HI(0x00001) /* Count rows changed by INSERT, */ /* DELETE, or UPDATE and return */ /* the count using a callback. */ +#define SQLITE_CorruptRdOnly HI(0x00002) /* Prohibit writes due to error */ /* Flags used only if debugging */ #ifdef SQLITE_DEBUG diff --git a/src/vdbe.c b/src/vdbe.c index 5b794ff942..b2390e0567 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -3604,6 +3604,7 @@ case OP_AutoCommit: { sqlite3CloseSavepoints(db); if( p->rc==SQLITE_OK ){ rc = SQLITE_DONE; + if( db->autoCommit ) db->flags &= ~SQLITE_CorruptRdOnly; }else{ rc = SQLITE_ERROR; } @@ -3665,8 +3666,15 @@ case OP_Transaction: { assert( pOp->p1>=0 && pOp->p1nDb ); assert( DbMaskTest(p->btreeMask, pOp->p1) ); assert( rc==SQLITE_OK ); - if( pOp->p2 && (db->flags & SQLITE_QueryOnly)!=0 ){ - rc = SQLITE_READONLY; + if( pOp->p2 && (db->flags & (SQLITE_QueryOnly|SQLITE_CorruptRdOnly))!=0 ){ + if( db->flags & SQLITE_QueryOnly ){ + /* Writes prohibited by the "PRAGMA query_only=TRUE" statement */ + rc = SQLITE_READONLY; + }else{ + /* Writes prohibited due to a prior SQLITE_CORRUPT in the current + ** transaction */ + rc = SQLITE_CORRUPT; + } goto abort_due_to_error; } pBt = db->aDb[pOp->p1].pBt; @@ -8391,6 +8399,9 @@ abort_due_to_error: (int)(pOp - aOp), p->zSql, p->zErrMsg); sqlite3VdbeHalt(p); if( rc==SQLITE_IOERR_NOMEM ) sqlite3OomFault(db); + if( rc==SQLITE_CORRUPT && db->autoCommit==0 ){ + db->flags |= SQLITE_CorruptRdOnly; + } rc = SQLITE_ERROR; if( resetSchemaOnFault>0 ){ sqlite3ResetOneSchema(db, resetSchemaOnFault-1);