]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Smaller and faster PRAGMA integrity_check that also does a better job of
authordrh <drh@noemail.net>
Thu, 2 Jul 2015 16:17:30 +0000 (16:17 +0000)
committerdrh <drh@noemail.net>
Thu, 2 Jul 2015 16:17:30 +0000 (16:17 +0000)
detecting errors.  Some output text describing discovered file corruption
has changed for clarity.

FossilOrigin-Name: 251a7590ff4f65f59a1c871892533e4e2c544515

manifest
manifest.uuid
src/btree.c
test/corrupt2.test
test/corrupt7.test
test/corruptE.test

index 01d9a5ce330ce5d69cf68d2158db65321858279c..8aa1fddc4a64f351b75b8c321b321e06cba05868 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Remove\s"#ifdef\sSQLITE_ENABLE_FTS5"\sfrom\sindividual\sfts5\ssource\sfiles.\sAdd\sa\ssingle\s"#if\s!defined(SQLITE_CORE)\s||\sdefined(SQLITE_ENABLE_FTS5)"\sto\sfts5.c.
-D 2015-07-02T15:52:21.801
+C Smaller\sand\sfaster\sPRAGMA\sintegrity_check\sthat\salso\sdoes\sa\sbetter\sjob\sof\ndetecting\serrors.\s\sSome\soutput\stext\sdescribing\sdiscovered\sfile\scorruption\nhas\schanged\sfor\sclarity.
+D 2015-07-02T16:17:30.545
 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
 F Makefile.in 1f525f24e2d3a4defd0ce819c10980caeec967fe
 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -269,7 +269,7 @@ F src/auth.c b56c78ebe40a2110fd361379f7e8162d23f92240
 F src/backup.c 4d9134dc988a87838c06056c89c0e8c4700a0452
 F src/bitvec.c d1f21d7d91690747881f03940584f4cc548c9d3d
 F src/btmutex.c 45a968cc85afed9b5e6cf55bf1f42f8d18107f79
-F src/btree.c e283de2f9da7ec5e47bedcd442a66a671aa2e118
+F src/btree.c 98ef3db8f90e2258eae6428cbe9cf47802b81958
 F src/btree.h 969adc948e89e449220ff0ff724c94bb2a52e9f1
 F src/btreeInt.h 2ad754dd4528baa8d0946a593cc373b890bf859e
 F src/build.c b3f15255d5b16e42dafeaa638fd4f8a47c94ed70
@@ -518,19 +518,19 @@ F test/conflict2.test 0d3af4fb534fa1bd020c79960bb56e4d52655f09
 F test/conflict3.test dec0634c0f31dec9a4b01c63063e939f0cd21b6b
 F test/contrib01.test 2a1cbc0f2f48955d7d073f725765da6fbceda6b4
 F test/corrupt.test 141c39ea650c1365e85a49e402fa05cb9617fb97
-F test/corrupt2.test f2064e0bf934124cc38868fd8badb8f0dd67b552
+F test/corrupt2.test 08cec1e5ffa68a3610306d6068f112d08bc9f090
 F test/corrupt3.test 4b548d0bbe2933bc81d3f54099a05fc4d28aff18
 F test/corrupt4.test b99652079d542b21f4965f6248703b983e40fe80
 F test/corrupt5.test 8ead52af76006f3286e9396cb41898018ccea107
 F test/corrupt6.test 269548d19427ac554c830763b1c5ea54a0252f80
-F test/corrupt7.test 22cc644c2e76c9804bc844121267aa6f8f7c0ded
+F test/corrupt7.test e4fa6d6584276679cc1d20c4e58beb9559a4eb85
 F test/corrupt8.test 2399dfe40d2c0c63af86706e30f3e6302a8d0516
 F test/corrupt9.test 730a3db08d4ab9aa43392ea30d9c2b4879cbff85
 F test/corruptA.test 53e56dafd180addcdadb402244b8cb9771d2ba26
 F test/corruptB.test 73a8d6c0b9833697ecf16b63e3c5c05c945b5dec
 F test/corruptC.test 3fcc0f73d2cf2d69befe2d96332b942426a6aae2
 F test/corruptD.test b3c205fac7952b1de645ce44bb02335cd9e3e040
-F test/corruptE.test 193b4ca4e927e77c1d5f4f56203ddc998432a7ee
+F test/corruptE.test be8e5088c369fc7979c662cd644efdaafc0f7f6d
 F test/corruptF.test be9fde98e4c93648f1ba52b74e5318edc8f59fe4
 F test/corruptG.test 1ab3bf97ee7bdba70e0ff3ba2320657df55d1804
 F test/corruptH.test 5dd4fa98c6c1ed33b178f9e8a48c4fdd3cfc9067
@@ -1364,7 +1364,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b
 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
-P c9ddbd88998d9523e72ad910ea67eb55024b3a88
-R 6e7391ae89eb1933cb67f3ce933af577
-U dan
-Z 75f643c411d6a670d86998374f15370f
+P 7819002ed85497bbd0f9cf4d39df641573324436
+R f272e35570685d031c8340df24a1680f
+U drh
+Z 39a394fff4020992662b6a21d701df1d
index 64d940be85de1a5fa9d1dda2a9f092933694df02..b2090c7894b749d05c2b26cb6d41d67a9a27c971 100644 (file)
@@ -1 +1 @@
-7819002ed85497bbd0f9cf4d39df641573324436
\ No newline at end of file
+251a7590ff4f65f59a1c871892533e4e2c544515
\ No newline at end of file
index a34c84fbcd542b8b8c6cc725f9dbc804b5614c19..1e50dcb4c0c8108749a4e819b900d457509157d3 100644 (file)
@@ -8932,20 +8932,30 @@ static int btreeHeapPull(u32 *aHeap, u32 *pOut){
 static int checkTreePage(
   IntegrityCk *pCheck,  /* Context for the sanity check */
   int iPage,            /* Page number of the page to check */
-  i64 *pnParentMinKey, 
-  i64 *pnParentMaxKey
+  i64 *piMinKey,        /* Write minimum integer primary key here */
+  i64 maxKey            /* Error if integer primary key greater than this */
 ){
-  MemPage *pPage = 0;
-  int i, rc, depth, d2, pgno, cnt;
-  int hdr, cellStart;
-  int nCell;
-  u8 *data;
-  BtShared *pBt;
-  int usableSize;
-  u32 *heap = 0;
+  MemPage *pPage = 0;      /* The page being analyzed */
+  int i;                   /* Loop counter */
+  int rc;                  /* Result code from subroutine call */
+  int depth = -1, d2;      /* Depth of a subtree */
+  int pgno;                /* Page number */
+  int nFrag;               /* Number of fragmented bytes on the page */
+  int hdr;                 /* Offset to the page header */
+  int cellStart;           /* Offset to the start of the cell pointer array */
+  int nCell;               /* Number of cells */
+  int doCoverageCheck = 1; /* True if cell coverage checking should be done */
+  int keyCanBeEqual = 1;   /* True if IPK can be equal to maxKey
+                           ** False if IPK must be strictly less than maxKey */
+  u8 *data;                /* Page content */
+  u8 *pCell;               /* Cell content */
+  u8 *pCellIdx;            /* Next element of the cell pointer array */
+  BtShared *pBt;           /* The BtShared object that owns pPage */
+  u32 pc;                  /* Address of a cell */
+  u32 usableSize;          /* Usable size of the page */
+  u32 contentOffset;       /* Offset to the start of the cell content area */
+  u32 *heap = 0;           /* Min-heap used for checking cell coverage */
   u32 x, prev = 0;
-  i64 nMinKey = 0;
-  i64 nMaxKey = 0;
   const char *saved_zPfx = pCheck->zPfx;
   int saved_v1 = pCheck->v1;
   int saved_v2 = pCheck->v2;
@@ -8961,7 +8971,6 @@ static int checkTreePage(
   if( (rc = btreeGetPage(pBt, (Pgno)iPage, &pPage, 0))!=0 ){
     checkAppendMsg(pCheck,
        "unable to get the page. error code=%d", rc);
-    depth = -1;
     goto end_of_check;
   }
 
@@ -8972,41 +8981,85 @@ static int checkTreePage(
     assert( rc==SQLITE_CORRUPT );  /* The only possible error from InitPage */
     checkAppendMsg(pCheck,
                    "btreeInitPage() returns error code %d", rc);
-    depth = -1;
     goto end_of_check;
   }
+  data = pPage->aData;
+  hdr = pPage->hdrOffset;
 
-  /* Check out all the cells.
-  */
-  depth = 0;
+  /* Set up for cell analysis */
   pCheck->zPfx = "On tree page %d cell %d: ";
-  for(i=0; i<pPage->nCell && pCheck->mxErr; i++){
-    u8 *pCell;
-    u32 sz;
+  contentOffset = get2byteNotZero(&data[hdr+5]);
+  assert( contentOffset<=usableSize );  /* Enforced by btreeInitPage() */
+
+  /* EVIDENCE-OF: R-37002-32774 The two-byte integer at offset 3 gives the
+  ** number of cells on the page. */
+  nCell = get2byte(&data[hdr+3]);
+  assert( pPage->nCell==nCell );
+
+  /* EVIDENCE-OF: R-23882-45353 The cell pointer array of a b-tree page
+  ** immediately follows the b-tree page header. */
+  cellStart = hdr + 12 - 4*pPage->leaf;
+  assert( pPage->aCellIdx==&data[cellStart] );
+  pCellIdx = &data[cellStart + 2*(nCell-1)];
+
+  if( !pPage->leaf ){
+    /* Analyze the right-child page of internal pages */
+    pgno = get4byte(&data[hdr+8]);
+#ifndef SQLITE_OMIT_AUTOVACUUM
+    if( pBt->autoVacuum ){
+      pCheck->zPfx = "On page %d at right child: ";
+      checkPtrmap(pCheck, pgno, PTRMAP_BTREE, iPage);
+    }
+#endif
+    depth = checkTreePage(pCheck, pgno, &maxKey, maxKey);
+    keyCanBeEqual = 0;
+  }else{
+    /* For leaf pages, the coverage check will occur in the same loop
+    ** as the other cell checks, so initialize the heap.  */
+    heap = pCheck->heap;
+    heap[0] = 0;
+    btreeHeapInsert(heap, contentOffset-1);
+  }
+
+  /* EVIDENCE-OF: R-02776-14802 The cell pointer array consists of K 2-byte
+  ** integer offsets to the cell contents. */
+  for(i=nCell-1; i>=0 && pCheck->mxErr; i--){
     CellInfo info;
 
-    /* Check payload overflow pages
-    */
+    /* Check cell size */
     pCheck->v2 = i;
-    pCell = findCell(pPage,i);
+    assert( pCellIdx==&data[cellStart + i*2] );
+    pc = get2byteAligned(pCellIdx);
+    pCellIdx -= 2;
+    if( pc<contentOffset || pc>usableSize-4 ){
+      checkAppendMsg(pCheck, "Offset %d out of range %d..%d",
+                             pc, contentOffset, usableSize-4);
+      doCoverageCheck = 0;
+      continue;
+    }
+    pCell = &data[pc];
     pPage->xParseCell(pPage, pCell, &info);
-    sz = info.nPayload;
-    /* For intKey pages, check that the keys are in order.
-    */
+    if( pc+info.nSize>usableSize ){
+      checkAppendMsg(pCheck, "Extends off end of page");
+      doCoverageCheck = 0;
+      continue;
+    }
+
+    /* Check for integer primary key out of range */
     if( pPage->intKey ){
-      if( i==0 ){
-        nMinKey = nMaxKey = info.nKey;
-      }else if( info.nKey <= nMaxKey ){
-        checkAppendMsg(pCheck,
-           "Rowid %lld out of order (previous was %lld)", info.nKey, nMaxKey);
+      if( keyCanBeEqual ? (info.nKey > maxKey) : (info.nKey >= maxKey) ){
+        checkAppendMsg(pCheck, "Rowid %lld out of order", info.nKey);
       }
-      nMaxKey = info.nKey;
+      maxKey = info.nKey;
     }
-    if( (sz>info.nLocal) 
-     && (&pCell[info.iOverflow]<=&pPage->aData[pBt->usableSize])
-    ){
-      int nPage = (sz - info.nLocal + usableSize - 5)/(usableSize - 4);
-      Pgno pgnoOvfl = get4byte(&pCell[info.iOverflow]);
+
+    /* Check the content overflow list */
+    if( info.nPayload>info.nLocal ){
+      int nPage;       /* Number of pages on the overflow chain */
+      Pgno pgnoOvfl;   /* First page of the overflow chain */
+      assert( pc + info.iOverflow <= usableSize );
+      nPage = (info.nPayload - info.nLocal + usableSize - 5)/(usableSize - 4);
+      pgnoOvfl = get4byte(&pCell[info.iOverflow]);
 #ifndef SQLITE_OMIT_AUTOVACUUM
       if( pBt->autoVacuum ){
         checkPtrmap(pCheck, pgnoOvfl, PTRMAP_OVERFLOW1, iPage);
@@ -9015,107 +9068,50 @@ static int checkTreePage(
       checkList(pCheck, 0, pgnoOvfl, nPage);
     }
 
-    /* Check sanity of left child page.
-    */
     if( !pPage->leaf ){
+      /* Check sanity of left child page for internal pages */
       pgno = get4byte(pCell);
 #ifndef SQLITE_OMIT_AUTOVACUUM
       if( pBt->autoVacuum ){
         checkPtrmap(pCheck, pgno, PTRMAP_BTREE, iPage);
       }
 #endif
-      d2 = checkTreePage(pCheck, pgno, &nMinKey, i==0?NULL:&nMaxKey);
-      if( i>0 && d2!=depth ){
+      d2 = checkTreePage(pCheck, pgno, &maxKey, maxKey);
+      keyCanBeEqual = 0;
+      if( d2!=depth ){
         checkAppendMsg(pCheck, "Child page depth differs");
+        depth = d2;
       }
-      depth = d2;
-    }
-  }
-
-  if( !pPage->leaf ){
-    pgno = get4byte(&pPage->aData[pPage->hdrOffset+8]);
-    pCheck->zPfx = "On page %d at right child: ";
-#ifndef SQLITE_OMIT_AUTOVACUUM
-    if( pBt->autoVacuum ){
-      checkPtrmap(pCheck, pgno, PTRMAP_BTREE, iPage);
-    }
-#endif
-    d2 = checkTreePage(pCheck, pgno, NULL, !pPage->nCell?NULL:&nMaxKey);
-    if( d2!=depth && iPage!=1 ){
-      checkAppendMsg(pCheck, "Child page depth differs");
-    }
-  }
-  /* For intKey leaf pages, check that the min/max keys are in order
-  ** with any left/parent/right pages.
-  */
-  pCheck->zPfx = "Page %d: ";
-  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,
-              "Rowid %lld out of order (max larger than parent min of %lld)",
-              nMaxKey, *pnParentMinKey);
-        }
-      }else{
-        if( nMinKey <= *pnParentMinKey ){
-          checkAppendMsg(pCheck,
-              "Rowid %lld out of order (min less than parent min of %lld)",
-              nMinKey, *pnParentMinKey);
-        }
-        if( nMaxKey > *pnParentMaxKey ){
-          checkAppendMsg(pCheck,
-              "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,
-            "Rowid %lld out of order (min less than parent max of %lld)",
-            nMinKey, *pnParentMaxKey);
-      }
+    }else{
+      /* Populate the coverage-checking heap for leaf pages */
+      btreeHeapInsert(heap, (pc<<16)|(pc+info.nSize-1));
     }
   }
+  *piMinKey = maxKey;
 
   /* Check for complete coverage of the page
   */
-  data = pPage->aData;
-  hdr = pPage->hdrOffset;
-  heap = pCheck->heap;
-  heap[0] = 0;
   pCheck->zPfx = 0;
-  {
-    int contentOffset = get2byteNotZero(&data[hdr+5]);
-    assert( contentOffset<=usableSize );  /* Enforced by btreeInitPage() */
-    btreeHeapInsert(heap, contentOffset-1);
-    /* EVIDENCE-OF: R-37002-32774 The two-byte integer at offset 3 gives the
-    ** number of cells on the page. */
-    nCell = get2byte(&data[hdr+3]);
-    /* EVIDENCE-OF: R-23882-45353 The cell pointer array of a b-tree page
-    ** immediately follows the b-tree page header. */
-    cellStart = hdr + 12 - 4*pPage->leaf;
-    /* EVIDENCE-OF: R-02776-14802 The cell pointer array consists of K 2-byte
-    ** integer offsets to the cell contents. */
-    for(i=nCell-1; i>=0; i--){
-      u32 pc = get2byteAligned(&data[cellStart+i*2]);
-      u32 size = pPage->xCellSize(pPage, &data[pc]);
-      if( (int)(pc+size-1)>=usableSize ){
-        pCheck->zPfx = 0;
-        checkAppendMsg(pCheck,
-            "Corruption detected in cell %d on page %d",i,iPage);
-      }else{
+  if( doCoverageCheck && pCheck->mxErr>0 ){
+    /* For leaf pages, the min-heap has already been initialized and the
+    ** cells have already been inserted.  But for internal pages, that has
+    ** not yet been done, so do it now */
+    if( !pPage->leaf ){
+      heap = pCheck->heap;
+      heap[0] = 0;
+      btreeHeapInsert(heap, contentOffset-1);
+      for(i=nCell-1; i>=0; i--){
+        u32 pc = get2byteAligned(&data[cellStart+i*2]);
+        u32 size = pPage->xCellSize(pPage, &data[pc]);
         btreeHeapInsert(heap, (pc<<16)|(pc+size-1));
       }
     }
-    /* EVIDENCE-OF: R-20690-50594 The second field of the b-tree page header
+    /* Add the freeblocks to the min-heap
+    **
+    ** EVIDENCE-OF: R-20690-50594 The second field of the b-tree page header
     ** is the offset of the first freeblock, or zero if there are no
-    ** freeblocks on the page. */
+    ** freeblocks on the page. 
+    */
     i = get2byte(&data[hdr+1]);
     while( i>0 ){
       int size, j;
@@ -9134,7 +9130,10 @@ static int checkTreePage(
       assert( j<=usableSize-4 );   /* Enforced by btreeInitPage() */
       i = j;
     }
-    cnt = 0;
+    /* Analyze the min-heap looking for overlap between cells and/or 
+    ** freeblocks, and counting the number of untracked bytes in nFrag.
+    */
+    nFrag = 0;
     assert( heap[0]>0 );
     assert( (heap[1]>>16)==0 );
     btreeHeapPull(heap,&prev);
@@ -9144,20 +9143,20 @@ static int checkTreePage(
           "Multiple uses for byte %u of page %d", x>>16, iPage);
         break;
       }else{
-        cnt += (x>>16) - (prev&0xffff) - 1;
+        nFrag += (x>>16) - (prev&0xffff) - 1;
         prev = x;
       }
     }
-    cnt += usableSize - (prev&0xffff) - 1;
+    nFrag += usableSize - (prev&0xffff) - 1;
     /* EVIDENCE-OF: R-43263-13491 The total number of bytes in all fragments
     ** is stored in the fifth field of the b-tree page header.
     ** EVIDENCE-OF: R-07161-27322 The one-byte integer at offset 7 gives the
     ** number of fragmented free bytes within the cell content area.
     */
-    if( heap[0]==0 && cnt!=data[hdr+7] ){
+    if( heap[0]==0 && nFrag!=data[hdr+7] ){
       checkAppendMsg(pCheck,
           "Fragmentation of %d bytes reported as %d on page %d",
-          cnt, data[hdr+7], iPage);
+          nFrag, data[hdr+7], iPage);
     }
   }
 
@@ -9192,10 +9191,11 @@ char *sqlite3BtreeIntegrityCheck(
   int *pnErr    /* Write number of errors seen to this variable */
 ){
   Pgno i;
-  VVA_ONLY( int nRef );
   IntegrityCk sCheck;
   BtShared *pBt = p->pBt;
+  int savedDbFlags = pBt->db->flags;
   char zErr[100];
+  VVA_ONLY( int nRef );
 
   sqlite3BtreeEnter(p);
   assert( p->inTrans>TRANS_NONE && pBt->inTransaction>TRANS_NONE );
@@ -9239,15 +9239,19 @@ char *sqlite3BtreeIntegrityCheck(
 
   /* Check all the tables.
   */
+  testcase( pBt->db->flags & SQLITE_CellSizeCk );
+  pBt->db->flags &= ~SQLITE_CellSizeCk;
   for(i=0; (int)i<nRoot && sCheck.mxErr; i++){
+    i64 notUsed;
     if( aRoot[i]==0 ) continue;
 #ifndef SQLITE_OMIT_AUTOVACUUM
     if( pBt->autoVacuum && aRoot[i]>1 ){
       checkPtrmap(&sCheck, aRoot[i], PTRMAP_ROOTPAGE, 0);
     }
 #endif
-    checkTreePage(&sCheck, aRoot[i], NULL, NULL);
+    checkTreePage(&sCheck, aRoot[i], &notUsed, LARGEST_INT64);
   }
+  pBt->db->flags = savedDbFlags;
 
   /* Make sure every page in the file is referenced
   */
index 805a6148f0b4d8e48d0eb99b7475dde1bd140d55..dc417339cde28fbf3276809e53380a158698946a 100644 (file)
@@ -249,7 +249,6 @@ do_test corrupt2-5.1 {
   set result
 } {{*** in database main ***
 On tree page 2 cell 0: 2nd reference to page 10
-On tree page 2 cell 1: Child page depth differs
 Page 4 is never used}}
 
 db2 close
index db92cf1de9f2b4b49bb7622340ef0d7056754f87..7ebebd94e778f2bcdcea6c1ff204e97091f59d6b 100644 (file)
@@ -65,41 +65,20 @@ integrity_check corrupt7-1.4
 
 # Deliberately corrupt some of the cell offsets in the btree page
 # on page 2 of the database.
-#
-# The error message is different depending on whether or not the
-# SQLITE_ENABLE_OVERSIZE_CELL_CHECK compile-time option is engaged.
-#
-ifcapable oversize_cell_check {
-  do_test corrupt7-2.1 {
-    db close
-    hexio_write test.db 1062 FF
-    sqlite3 db test.db
-    db eval {PRAGMA integrity_check(1)}
-  } {{*** in database main ***
-Page 2: btreeInitPage() returns error code 11}}
-  do_test corrupt7-2.2 {
-    db close
-    hexio_write test.db 1062 04
-    sqlite3 db test.db
-    db eval {PRAGMA integrity_check(1)}
-  } {{*** in database main ***
-Page 2: btreeInitPage() returns error code 11}}
-} else {
-  do_test corrupt7-2.1 {
-    db close
-    hexio_write test.db 1062 FF
-    sqlite3 db test.db
-    db eval {PRAGMA integrity_check(1)}
-  } {{*** in database main ***
-Corruption detected in cell 15 on page 2}}
-  do_test corrupt7-2.2 {
-    db close
-    hexio_write test.db 1062 04
-    sqlite3 db test.db
-    db eval {PRAGMA integrity_check(1)}
-  } {{*** in database main ***
-On tree page 2 cell 15: Rowid 0 out of order (previous was 15)}}
-}
+do_test corrupt7-2.1 {
+  db close
+  hexio_write test.db 1062 FF
+  sqlite3 db test.db
+  db eval {PRAGMA integrity_check(1)}
+} {{*** in database main ***
+On tree page 2 cell 15: Offset 65457 out of range 945..1020}}
+do_test corrupt7-2.2 {
+  db close
+  hexio_write test.db 1062 04
+  sqlite3 db test.db
+  db eval {PRAGMA integrity_check(1)}
+} {{*** in database main ***
+On tree page 2 cell 15: Offset 1201 out of range 945..1020}}
   
 # The code path that was causing the buffer overrun that this test
 # case was checking for was removed.
index 4d5b5db3d680134abb8731b88e14d43ca8fe1564..78cabbec8eda01a01079b613bb6e384d0e7cf3b3 100644 (file)
@@ -14,7 +14,6 @@
 # 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 $
 
 set testdir [file dirname $argv0]
 source $testdir/tester.tcl
@@ -79,12 +78,8 @@ do_test corruptE-2.1 {
 
   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}
+  catchsql {PRAGMA integrity_check}
+} {/ out of order/}
 
 do_test corruptE-2.2 {
   db close
@@ -95,12 +90,8 @@ do_test corruptE-2.2 {
 
   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}
+  catchsql {PRAGMA integrity_check}
+} {/ Extends off end of page/}
 
 do_test corruptE-2.3 {
   db close
@@ -112,11 +103,8 @@ do_test corruptE-2.3 {
 
   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}
+  catchsql {PRAGMA integrity_check}
+} {/out of order/}
 
 do_test corruptE-2.4 {
   db close
@@ -127,33 +115,22 @@ do_test corruptE-2.4 {
 
   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}
+  catchsql {PRAGMA integrity_check}
+} {/out of order/}
 
 
 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} ]
 
@@ -168,11 +145,8 @@ foreach test $tests {
 
     sqlite3 db test.db
 
-    set res [ catchsql {PRAGMA integrity_check} ]
-    set ans [lindex $res 1]
-
-    list [regexp {out of order} $ans]
-  } {1}
+    catchsql {PRAGMA integrity_check}
+  } {/out of order/}
   incr tc 1
 }