]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Have the btree layer detect when a "DELETE FROM tbl" statement is clearing a database...
authordan <Dan Kennedy>
Sat, 16 Oct 2021 17:09:36 +0000 (17:09 +0000)
committerdan <Dan Kennedy>
Sat, 16 Oct 2021 17:09:36 +0000 (17:09 +0000)
FossilOrigin-Name: a6fda39e81d0da98dd6b60b32e6df786f0089c1f4ac7f3a2936afd118bd04353

manifest
manifest.uuid
src/btree.c
src/btreeInt.h
test/corruptN.test

index 55b329d50fcd75ef104d5e2c55dffad0316e7497..ba3554551d05ec5bdcfe9888739dec25f5f249fa 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Fix\san\sassert()\sin\sfts5\sthat\scould\sfail\swith\sa\scorrupt\sdatabase.
-D 2021-10-16T13:59:08.125
+C Have\sthe\sbtree\slayer\sdetect\swhen\sa\s"DELETE\sFROM\stbl"\sstatement\sis\sclearing\sa\sdatabase\spage\sthat\sis\sstill\sin\suse\s(due\sto\sdatabase\scorruption)\sand\sreport\sSQLITE_CORRUPT.
+D 2021-10-16T17:09:36.325
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -490,9 +490,9 @@ F src/auth.c f4fa91b6a90bbc8e0d0f738aa284551739c9543a367071f55574681e0f24f8cf
 F src/backup.c 3014889fa06e20e6adfa0d07b60097eec1f6e5b06671625f476a714d2356513d
 F src/bitvec.c 7c849aac407230278445cb069bebc5f89bf2ddd87c5ed9459b070a9175707b3d
 F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6
-F src/btree.c 35782a608c940e219a01cf9d84de55e11668a42ede3b7b2d2fb4a6edb52e97e5
+F src/btree.c 91cc6d99b047c4d8672780ced92ad4ee45345fc92eef62f1b4193356d930f5f6
 F src/btree.h 74d64b8f28cfa4a894d14d4ed64fa432cd697b98b61708d4351482ae15913e22
-F src/btreeInt.h 7bc15a24a02662409ebcd6aeaa1065522d14b7fda71573a2b0568b458f514ae0
+F src/btreeInt.h ee9348c4cb9077243b049edc93a82c1f32ca48baeabf2140d41362b9f9139ff7
 F src/build.c f70d6375ea5b78daac5b1d24eab53ed7b81c3e68a17dff9581c50c0c06180e00
 F src/callback.c 106b585da1edd57d75fa579d823a5218e0bf37f191dbf7417eeb4a8a9a267dbc
 F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
@@ -808,7 +808,7 @@ F test/corruptJ.test 4d5ccc4bf959464229a836d60142831ef76a5aa4
 F test/corruptK.test 5b4212fe346699831c5ad559a62c54e11c0611bdde1ea8423a091f9c01aa32af
 F test/corruptL.test 7d3440831ca24ba64305583c4d4506d417d3f89f5775c0b7cc8102db078f8ff5
 F test/corruptM.test 7d574320e08c1b36caa3e47262061f186367d593a7e305d35f15289cc2c3e067
-F test/corruptN.test c2a96ff81386027f7d7e95858783aa36f82ba1532106969575e3c8f90903a5bb
+F test/corruptN.test 14962dc3f5567b5722a24d166bf143bec790673476f7b0932d82609210d1becd
 F test/cost.test b11cdbf9f11ffe8ef99c9881bf390e61fe92baf2182bad1dbe6de59a7295c576
 F test/count.test 5364003488249957750a5f15ee42ca1cd7b100b1131c2dc71fff266a1250bf55
 F test/countofview.test e17d6e6688cf74f22783c9ec6e788c0790ee4fbbaee713affd00b1ac0bb39b86
@@ -1929,7 +1929,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 8a56de5b9c6f4522000f8d991373490b67b9e9d97f03c1ca2cf32816d84789ef
-R 4bcaeff59bcce0f4ef771608de87df49
+P e99979855de937ed5ee0994b180054501400bf8776fb70acd31786d2ba1ad49a
+R 3f77e71e98554900f2c6a9f0c33e3266
 U dan
-Z af80492fe37d3ad04ab438f47d1814c1
+Z ce8477010c93ae34e562deaff5d43b53
index 115e10ee3f1f58568b0a99e4474fd6d76a6d6c44..97c6f0d807c9c454b81ad2242b15bcac16d0d66d 100644 (file)
@@ -1 +1 @@
-e99979855de937ed5ee0994b180054501400bf8776fb70acd31786d2ba1ad49a
\ No newline at end of file
+a6fda39e81d0da98dd6b60b32e6df786f0089c1f4ac7f3a2936afd118bd04353
\ No newline at end of file
index 766fd0805b5f5fa65e8a3f2ade06675467af726e..809aeb4887c6fd284e9a435970845541c267adf4 100644 (file)
@@ -9549,11 +9549,12 @@ static int clearDatabasePage(
   }
   rc = getAndInitPage(pBt, pgno, &pPage, 0, 0);
   if( rc ) return rc;
-  if( pPage->bBusy ){
+  if( (pBt->openFlags & BTREE_SINGLE)==0 
+   && sqlite3PagerPageRefcount(pPage->pDbPage)!=1
+  ){
     rc = SQLITE_CORRUPT_BKPT;
     goto cleardatabasepage_out;
   }
-  pPage->bBusy = 1;
   hdr = pPage->hdrOffset;
   for(i=0; i<pPage->nCell; i++){
     pCell = findCell(pPage, i);
@@ -9580,7 +9581,6 @@ static int clearDatabasePage(
   }
 
 cleardatabasepage_out:
-  pPage->bBusy = 0;
   releasePage(pPage);
   return rc;
 }
@@ -9659,9 +9659,9 @@ static int btreeDropTable(Btree *p, Pgno iTable, int *piMoved){
     return SQLITE_CORRUPT_BKPT;
   }
 
-  rc = btreeGetPage(pBt, (Pgno)iTable, &pPage, 0);
-  if( rc ) return rc;
   rc = sqlite3BtreeClearTable(p, iTable, 0);
+  if( rc ) return rc;
+  rc = btreeGetPage(pBt, (Pgno)iTable, &pPage, 0);
   if( rc ){
     releasePage(pPage);
     return rc;
index 37c07fe93be6a26a6a2a3fa2e0209324915b658a..1076fd8f2ca394eff503ecd98d888333eb194956 100644 (file)
@@ -272,7 +272,6 @@ typedef struct CellInfo CellInfo;
 */
 struct MemPage {
   u8 isInit;           /* True if previously initialized. MUST BE FIRST! */
-  u8 bBusy;            /* Prevent endless loops on corrupt database files */
   u8 intKey;           /* True if table b-trees.  False for index b-trees */
   u8 intKeyLeaf;       /* True if the leaf of an intKey table */
   Pgno pgno;           /* Page number for this page */
index 8600e438da3fe2d538a2998b0afc1e90b41d4184..1452a7f68312ee3bb27d9fb1526a298832ee5bab 100644 (file)
@@ -224,5 +224,52 @@ ifcapable json1&&vtab {
   }
 }; # ifcapable json1&&vtab
 
+#-------------------------------------------------------------------------
+reset_db
+
+do_execsql_test 6.0 {
+  PRAGMA page_size=1024;
+  CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
+  INSERT INTO t1(b) VALUES(zeroblob(300)),(zeroblob(300)),(zeroblob(300)),(zeroblob(300));
+  CREATE TABLE t2(a);
+  CREATE TRIGGER t1tr BEFORE UPDATE ON t1 BEGIN DELETE FROM t2; END;
+  PRAGMA writable_schema=ON;
+  UPDATE sqlite_schema SET rootpage=3 WHERE rowid=2;
+  PRAGMA writable_schema=RESET;
+  INSERT INTO t2 VALUES('active'),('boomer'),('atom'),('atomic'),
+         ('alpha channel backup abandon test aback boomer atom alpha active');
+}
+do_catchsql_test 6.1 {
+  UPDATE t1 SET b=zeroblob(299);
+} {1 {database disk image is malformed}}
+
+reset_db
+do_execsql_test 6.2 {
+  -- Make "t1" a large table. Large enough that the children of the root
+  -- node are interior nodes.
+  PRAGMA page_size = 1024;
+  PRAGMA autovacuum = 0;
+  CREATE TABLE t1(x);
+  WITH s(i) AS (
+    SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<500
+  )
+  INSERT INTO t1 SELECT zeroblob(300) FROM s;
+  
+  CREATE TABLE t2(y);
+  CREATE TRIGGER tr BEFORE UPDATE ON t1 BEGIN
+    DELETE FROM t2;
+  END;
+  
+  -- Set the root of table t2 to 137 - the leftmost child of the root of t1.
+  PRAGMA writable_schema = ON;
+  UPDATE sqlite_schema SET rootpage = 137 WHERE name='t2';
+  PRAGMA writable_schema = RESET;
+}
+  
+do_catchsql_test 6.3 {
+  -- Run an UPDATE on t1 that will hit a child of page 136. Have the trigger
+  -- clear page 136 and its children. Assert fails.
+  UPDATE t1 SET x='hello world' WHERE rowid=1;
+} {1 {database disk image is malformed}}
 
 finish_test