]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Changes to pragma integrity_check to check rowid order. Tests of same in corruptE...
authorshaneh <shaneh@noemail.net>
Fri, 19 Feb 2010 04:28:08 +0000 (04:28 +0000)
committershaneh <shaneh@noemail.net>
Fri, 19 Feb 2010 04:28:08 +0000 (04:28 +0000)
FossilOrigin-Name: cae47c5b09cb122689bcb020a66ce14982cc4aa8

manifest
manifest.uuid
src/btree.c
test/corrupt7.test
test/corruptE.test [new file with mode: 0644]

index 58fc3f466d1e812d0b12e2f32f006a7bd379218c..48afeee08a459d8993daad09c31651ea21bde752 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,8 +1,5 @@
------BEGIN PGP SIGNED MESSAGE-----
-Hash: SHA1
-
-C Add\sa\snew,\sexperimental\slogging\sinterface\sdesigned\sto\said\sin\sdebugging\sof\ndeeply\sembedded\sprojects\sthat\suse\sSQLite.
-D 2010-02-18T18:45:10
+C Changes\sto\spragma\sintegrity_check\sto\scheck\srowid\sorder.\s\sTests\sof\ssame\sin\scorruptE.test.
+D 2010-02-19T04:28:09
 F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
 F Makefile.in c5827ead754ab32b9585487177c93bb00b9497b3
 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
@@ -112,7 +109,7 @@ F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34
 F src/backup.c 744e98359dfc79fed43e8dec911e33e108b06aae
 F src/bitvec.c 06ad2c36a9c3819c0b9cbffec7b15f58d5d834e0
 F src/btmutex.c 96a12f50f7a17475155971a241d85ec5171573ff
-F src/btree.c c9ee3c30fbf21ebb4f45c244bd47d7999e6f2704
+F src/btree.c b7ac4420d10662259ad3421145eab16a279f5bd3
 F src/btree.h 0e193b7e90f1d78b79c79474040e3d66a553a4fa
 F src/btreeInt.h 71ed5e7f009caf17b7dc304350b3cb64b5970135
 F src/build.c 81412e0f3cabd0cc7a71a1644c46d9ccad9613f5
@@ -300,13 +297,14 @@ F test/corrupt3.test 263e8bb04e2728df832fddf6973cf54c91db0c32
 F test/corrupt4.test acdb01afaedf529004b70e55de1a6f5a05ae7fff
 F test/corrupt5.test c23da7bfb20917cc7fdbb13ee25c7cc4e9fffeff
 F test/corrupt6.test e69b877d478224deab7b66844566258cecacd25e
-F test/corrupt7.test e66cb109ed64e7ac985d8b4a3422c213d074c62d
+F test/corrupt7.test 1eb2214f29474fa6b155aa3da8a7d46bf52089e1
 F test/corrupt8.test 9992ef7f67cefc576b92373f6bf5ab8775280f51
 F test/corrupt9.test 4aa1cb1ef091cb0e13e89a819c72911631b5176a
 F test/corruptA.test 99e95620b980161cb3e79f06a884a4bb8ae265ff
 F test/corruptB.test 66b4544104dd03d0f33ea69ddac3fa4a682cd3c2
 F test/corruptC.test 691ed070baef5e1345939caadf270a52837a5064
 F test/corruptD.test 3ae6e2dc6e2226c6935a8a40d4b5ee3eba75f8c0
+F test/corruptE.test dbf66cae4c0e977ca9625a9114cdd01df8967bef
 F test/count.test 454e1ce985c94d13efeac405ce54439f49336163
 F test/crash.test 1b6ac8410689ff78028887f445062dc897c9ac89
 F test/crash2.test 5b14d4eb58b880e231361d3b609b216acda86651
@@ -792,14 +790,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
 F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
-P 0e4225804010cb0e3f254e2dbffc4fe0e7d982ce
-R e1b84b3199b12981899c4cf8ff08b1fe
-U drh
-Z 01212a28378b63d61c38823b1b1cabd0
------BEGIN PGP SIGNATURE-----
-Version: GnuPG v1.4.10 (Darwin)
-
-iEYEARECAAYFAkt9irYACgkQoxKgR168RlFqLACfTtjHG4O+0YQ6hh1MZq3NFfjO
-3wAAn2U6GgjbwSAri4XLyLGkLsGJgnkn
-=i25A
------END PGP SIGNATURE-----
+P 103321e37ae46eacfad4e127d13477ad5dd02bab
+R becff0b48e882ac8f957bf23a46ac2b6
+U shaneh
+Z 75f7bf2a2627891ab273971d988089a2
index 0ead8aa2d9a0db4a8b55206d9866c1ea1476be1f..459fd3c446c39719df6490d8062d8531d8eb622c 100644 (file)
@@ -1 +1 @@
-103321e37ae46eacfad4e127d13477ad5dd02bab
\ No newline at end of file
+cae47c5b09cb122689bcb020a66ce14982cc4aa8
\ No newline at end of file
index 68f290720356a3183b55e63e89d132e9c5068465..7754f3a213fa477372122c50e70f51876d93bc5c 100644 (file)
@@ -7411,7 +7411,9 @@ static void checkList(
 static int checkTreePage(
   IntegrityCk *pCheck,  /* Context for the sanity check */
   int iPage,            /* Page number of the page to check */
-  char *zParentContext  /* Parent context */
+  char *zParentContext, /* Parent context */
+  i64 *pnParentMinKey, 
+  i64 *pnParentMaxKey
 ){
   MemPage *pPage;
   int i, rc, depth, d2, pgno, cnt;
@@ -7422,6 +7424,8 @@ static int checkTreePage(
   int usableSize;
   char zContext[100];
   char *hit = 0;
+  i64 nMinKey = 0;
+  i64 nMaxKey = 0;
 
   sqlite3_snprintf(sizeof(zContext), zContext, "Page %d: ", iPage);
 
@@ -7464,6 +7468,16 @@ static int checkTreePage(
     btreeParseCellPtr(pPage, pCell, &info);
     sz = info.nData;
     if( !pPage->intKey ) sz += (int)info.nKey;
+    /* For intKey pages, check that the keys are in order.
+    */
+    else if( i==0 ) nMinKey = nMaxKey = info.nKey;
+    else{
+      if( info.nKey <= nMaxKey ){
+        checkAppendMsg(pCheck, zContext, 
+            "Rowid %lld out of order (previous was %lld)", info.nKey, nMaxKey);
+      }
+      nMaxKey = info.nKey;
+    }
     assert( sz==info.nPayload );
     if( (sz>info.nLocal) 
      && (&pCell[info.iOverflow]<=&pPage->aData[pBt->usableSize])
@@ -7487,25 +7501,62 @@ static int checkTreePage(
         checkPtrmap(pCheck, pgno, PTRMAP_BTREE, iPage, zContext);
       }
 #endif
-      d2 = checkTreePage(pCheck, pgno, zContext);
+      d2 = checkTreePage(pCheck, pgno, zContext, &nMinKey, i==0 ? NULL : &nMaxKey);
       if( i>0 && d2!=depth ){
         checkAppendMsg(pCheck, zContext, "Child page depth differs");
       }
       depth = d2;
     }
   }
+
   if( !pPage->leaf ){
     pgno = get4byte(&pPage->aData[pPage->hdrOffset+8]);
     sqlite3_snprintf(sizeof(zContext), zContext, 
                      "On page %d at right child: ", iPage);
 #ifndef SQLITE_OMIT_AUTOVACUUM
     if( pBt->autoVacuum ){
-      checkPtrmap(pCheck, pgno, PTRMAP_BTREE, iPage, 0);
+      checkPtrmap(pCheck, pgno, PTRMAP_BTREE, iPage, zContext);
     }
 #endif
-    checkTreePage(pCheck, pgno, zContext);
+    checkTreePage(pCheck, pgno, zContext, NULL, !pPage->nCell ? NULL : &nMaxKey);
   }
  
+  /* For intKey leaf pages, check that the min/max keys are in order
+  ** with any left/parent/right pages.
+  */
+  if( pPage->leaf && pPage->intKey ){
+    /* if we are a left child page */
+    if( pnParentMinKey ){
+      /* if we are the left most child page */
+      if( !pnParentMaxKey ){
+        if( nMaxKey > *pnParentMinKey ){
+          checkAppendMsg(pCheck, zContext, 
+              "Rowid %lld out of order (max larger than parent min of %lld)",
+              nMaxKey, *pnParentMinKey);
+        }
+      }else{
+        if( nMinKey <= *pnParentMinKey ){
+          checkAppendMsg(pCheck, zContext, 
+              "Rowid %lld out of order (min less than parent min of %lld)",
+              nMinKey, *pnParentMinKey);
+        }
+        if( nMaxKey > *pnParentMaxKey ){
+          checkAppendMsg(pCheck, zContext, 
+              "Rowid %lld out of order (max larger than parent max of %lld)",
+              nMaxKey, *pnParentMaxKey);
+        }
+        *pnParentMinKey = nMaxKey;
+      }
+    /* else if we're a right child page */
+    } else if( pnParentMaxKey ){
+      if( nMinKey <= *pnParentMaxKey ){
+        checkAppendMsg(pCheck, zContext, 
+            "Rowid %lld out of order (min less than parent max of %lld)",
+            nMinKey, *pnParentMaxKey);
+      }
+    }
+  }
+
   /* Check for complete coverage of the page
   */
   data = pPage->aData;
@@ -7529,7 +7580,7 @@ static int checkTreePage(
       }
       if( (pc+size-1)>=usableSize ){
         checkAppendMsg(pCheck, 0, 
-            "Corruption detected in cell %d on page %d",i,iPage,0);
+            "Corruption detected in cell %d on page %d",i,iPage);
       }else{
         for(j=pc+size-1; j>=pc; j--) hit[j]++;
       }
@@ -7635,7 +7686,7 @@ char *sqlite3BtreeIntegrityCheck(
       checkPtrmap(&sCheck, aRoot[i], PTRMAP_ROOTPAGE, 0, 0);
     }
 #endif
-    checkTreePage(&sCheck, aRoot[i], "List of tree roots: ");
+    checkTreePage(&sCheck, aRoot[i], "List of tree roots: ", NULL, NULL);
   }
 
   /* Make sure every page in the file is referenced
index 8f8d437a62154ae8f24359cd6dcd3c789227dce3..39aa62018eac09b6bc3b3fa3fd53b79bf84fc7a1 100644 (file)
@@ -89,7 +89,7 @@ Corruption detected in cell 15 on page 2}}
     sqlite3 db test.db
     db eval {PRAGMA integrity_check(1)}
   } {{*** in database main ***
-Corruption detected in cell 15 on page 2}}
+On tree page 2 cell 15: Rowid 0 out of order (previous was 15)}}
 }
   
 # The code path that was causing the buffer overrun that this test
diff --git a/test/corruptE.test b/test/corruptE.test
new file mode 100644 (file)
index 0000000..35fa545
--- /dev/null
@@ -0,0 +1,171 @@
+# 2010 February 18
+#
+# 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.
+#
+#***********************************************************************
+# This file implements regression tests for SQLite library.
+#
+# This file implements tests to make sure SQLite does not crash or
+# segfault if it sees a corrupt database file.  It specifcally
+# focuses on rowid order corruption.
+#
+# $Id: corruptE.test,v 1.14 2009/07/11 06:55:34 danielk1977 Exp $
+
+catch {file delete -force test.db test.db-journal test.bu}
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+# Construct a compact, dense database for testing.
+#
+do_test corruptE-1.1 {
+  execsql {
+    PRAGMA auto_vacuum = 0;
+    PRAGMA legacy_file_format=1;
+    BEGIN;
+    CREATE TABLE t1(x,y);
+    INSERT INTO t1 VALUES(1,1);
+    INSERT OR IGNORE INTO t1 SELECT x*2,y FROM t1;
+    INSERT OR IGNORE INTO t1 SELECT x*3,y FROM t1;
+    INSERT OR IGNORE INTO t1 SELECT x*5,y FROM t1;
+    INSERT OR IGNORE INTO t1 SELECT x*7,y FROM t1;
+    INSERT OR IGNORE INTO t1 SELECT x*11,y FROM t1;
+    INSERT OR IGNORE INTO t1 SELECT x*13,y FROM t1;
+    INSERT OR IGNORE INTO t1 SELECT x*17,y FROM t1;
+    INSERT OR IGNORE INTO t1 SELECT x*19,y FROM t1;
+    CREATE INDEX t1i1 ON t1(x);
+    CREATE TABLE t2 AS SELECT x,2 as y FROM t1 WHERE rowid%5!=0;
+    COMMIT;
+  }
+} {}
+
+ifcapable {integrityck} {
+  integrity_check corruptE-1.2
+}
+
+# Copy file $from into $to
+#
+proc copy_file {from to} {
+  file copy -force $from $to
+}
+
+# Setup for the tests.  Make a backup copy of the good database in test.bu.
+#
+db close
+copy_file test.db test.bu
+sqlite3 db test.db
+set fsize [file size test.db]
+
+
+do_test corruptE-2.1 {
+  db close
+  copy_file test.bu test.db
+
+  # insert corrupt byte(s)
+  hexio_write test.db 2041 [format %02x 0x2e]
+
+  sqlite3 db test.db
+
+  set res [ catchsql {PRAGMA integrity_check} ]
+  set ans [lindex $res 1]
+
+  list [regexp {out of order.*previous was} $ans] \
+       [regexp {out of order.*max larger than parent max} $ans]
+} {1 1}
+
+do_test corruptE-2.2 {
+  db close
+  copy_file test.bu test.db
+
+  # insert corrupt byte(s)
+  hexio_write test.db 2047 [format %02x 0x84]
+
+  sqlite3 db test.db
+
+  set res [ catchsql {PRAGMA integrity_check} ]
+  set ans [lindex $res 1]
+
+  list [regexp {out of order.*previous was} $ans] \
+       [regexp {out of order.*min less than parent min} $ans]
+} {1 1}
+
+do_test corruptE-2.3 {
+  db close
+  copy_file test.bu test.db
+
+  # insert corrupt byte(s)
+  hexio_write test.db 7420 [format %02x 0xa8]
+  hexio_write test.db 10459 [format %02x 0x8d]
+
+  sqlite3 db test.db
+
+  set res [ catchsql {PRAGMA integrity_check} ]
+  set ans [lindex $res 1]
+
+  list [regexp {out of order.*max larger than parent min} $ans]
+} {1}
+
+do_test corruptE-2.4 {
+  db close
+  copy_file test.bu test.db
+
+  # insert corrupt byte(s)
+  hexio_write test.db 10233 [format %02x 0xd0]
+
+  sqlite3 db test.db
+
+  set res [ catchsql {PRAGMA integrity_check} ]
+  set ans [lindex $res 1]
+
+  list [regexp {out of order.*min less than parent max} $ans]
+} {1}
+
+
+set tests [list {10233 0xd0} \
+                {941 0x42} \
+                {1028 0x53} \
+                {2041 0xd0} \
+                {2042 0x1f} \
+                {2047 0xaa} \
+                {2263 0x29} \
+                {2274 0x75} \
+                {3267 0xf2} \
+                {4104 0x2c} \
+                {5113 0x36} \
+                {10233 0x84} \
+                {10234 0x74} \
+                {10239 0x41} \
+                {10453 0x11} \
+                {11273 0x28} \
+                {11455 0x11} \
+                {11461 0xe6} \
+                {12281 0x99} \
+                {12296 0x9e} \
+                {12297 0xd7} \
+                {13303 0x53} ]
+
+set tc 1
+foreach test $tests {
+  do_test corruptE-3.$tc {
+    db close
+    copy_file test.bu test.db
+
+    # insert corrupt byte(s)
+    hexio_write test.db [lindex $test 0] [format %02x [lindex $test 1]]
+
+    sqlite3 db test.db
+
+    set res [ catchsql {PRAGMA integrity_check} ]
+    set ans [lindex $res 1]
+
+    list [regexp {out of order} $ans]
+  } {1}
+  incr tc 1
+}
+
+finish_test