From: drh Date: Wed, 1 Jul 2015 17:13:45 +0000 (+0000) Subject: Rework the PRAGMA integrity_check logic. Simplify the checkTreePage() routine X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=refs%2Fheads%2Fintegrity-check-refactor;p=thirdparty%2Fsqlite.git Rework the PRAGMA integrity_check logic. Simplify the checkTreePage() routine and clean up the error messages generated. FossilOrigin-Name: 1c52212369692ca7c0b16a14e3a403cd4c5fbffc --- diff --git a/manifest b/manifest index ad6e53acd5..2a439fcfa1 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\ssome\sharmless\scompiler\swarnings. -D 2015-07-01T04:08:40.538 +C Rework\sthe\sPRAGMA\sintegrity_check\slogic.\s\sSimplify\sthe\scheckTreePage()\sroutine\nand\sclean\sup\sthe\serror\smessages\sgenerated. +D 2015-07-01T17:13:45.237 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 285a0a234ed7610d431d91671c136098c2bd86a9 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -269,9 +269,9 @@ F src/auth.c b56c78ebe40a2110fd361379f7e8162d23f92240 F src/backup.c ff743689c4d6c5cb55ad42ed9d174b2b3e71f1e3 F src/bitvec.c d1f21d7d91690747881f03940584f4cc548c9d3d F src/btmutex.c 45a968cc85afed9b5e6cf55bf1f42f8d18107f79 -F src/btree.c 075ce6ddce9e66277c898f5b6a44a8a7c61c8125 +F src/btree.c 41c63a0f4e24ca02a9e1142020669a8a3485f22c F src/btree.h 969adc948e89e449220ff0ff724c94bb2a52e9f1 -F src/btreeInt.h c54d380cb262549c4176e0d665518cc1a3861bdf +F src/btreeInt.h 2ad754dd4528baa8d0946a593cc373b890bf859e F src/build.c b3f15255d5b16e42dafeaa638fd4f8a47c94ed70 F src/callback.c 7b44ce59674338ad48b0e84e7b72f935ea4f68b0 F src/complete.c addcd8160b081131005d5bc2d34adf20c1c5c92f @@ -314,8 +314,8 @@ F src/os_setup.h c9d4553b5aaa6f73391448b265b89bed0b890faa F src/os_unix.c 23eb5f56fac54d8fe0cb204291f3b3b2d94f23fc F src/os_win.c 27cc135e2d0b8b1e2e4944db1e2669a6a18fa0f8 F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca -F src/pager.c 922d8ea28387b79a117488da06ee84f77d50d71e -F src/pager.h c3476e7c89cdf1c6914e50a11f3714e30b4e0a77 +F src/pager.c aa916ca28606ccf4b6877dfc2b643ccbca86589f +F src/pager.h 6d435f563b3f7fcae4b84433b76a6ac2730036e2 F src/parse.y 6d60dda8f8d418b6dc034f1fbccd816c459983a8 F src/pcache.c cde06aa50962595e412d497e22fd2e07878ba1f0 F src/pcache.h 9968603796240cdf83da7e7bef76edf90619cea9 @@ -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/corrupt3.test 4b548d0bbe2933bc81d3f54099a05fc4d28aff18 +F test/corrupt2.test 929c68b858f066599960ca8f8529a43602bc2759 +F test/corrupt3.test 747c0d5993ee85a739600f17957cd6ab360f1d8d F test/corrupt4.test b99652079d542b21f4965f6248703b983e40fe80 F test/corrupt5.test 8ead52af76006f3286e9396cb41898018ccea107 F test/corrupt6.test 269548d19427ac554c830763b1c5ea54a0252f80 -F test/corrupt7.test 22cc644c2e76c9804bc844121267aa6f8f7c0ded +F test/corrupt7.test beb6b166443c392c7e0348f6b5b8d03fb75e7667 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 4d81d3079c75f49ec2494221e5c46757a0bfac30 F test/corruptF.test be9fde98e4c93648f1ba52b74e5318edc8f59fe4 F test/corruptG.test 1ab3bf97ee7bdba70e0ff3ba2320657df55d1804 F test/corruptH.test 5dd4fa98c6c1ed33b178f9e8a48c4fdd3cfc9067 @@ -903,7 +903,7 @@ F test/pcache.test b09104b03160aca0d968d99e8cd2c5b1921a993d F test/pcache2.test a83efe2dec0d392f814bfc998def1d1833942025 F test/percentile.test 4243af26b8f3f4555abe166f723715a1f74c77ff F test/permutations.test 6a88fd9ca15b804e9c20990773262ca67494058f -F test/pragma.test be7195f0aa72bdb8a512133e9640ac40f15b57a2 +F test/pragma.test 75fcb9bc90940fea538e542e07798ac2732130b6 F test/pragma2.test f624a496a95ee878e81e59961eade66d5c00c028 F test/pragma3.test 6f849ccffeee7e496d2f2b5e74152306c0b8757c F test/printf.test b3ff34e73d59124140eaf89f7672e21bc2ca5fcc @@ -1364,7 +1364,10 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 59ad912c4c1f858e04d27b1b8f25581a5f6e5daf -R 71a875c7f3b6312a533d9c1fd4d005d9 +P 307195c8709d7fd2a642baa8011eb0c88cfdc0ac +R b1c4a6aaa6fdb8ddbfc860994709a186 +T *branch * integrity-check-refactor +T *sym-integrity-check-refactor * +T -sym-trunk * U drh -Z 39cb6954bdcd951136843b690dd37c51 +Z 7bdf3de567fd950f32ae21a90fed9aca diff --git a/manifest.uuid b/manifest.uuid index 71a9643813..ad09793ef0 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -307195c8709d7fd2a642baa8011eb0c88cfdc0ac \ No newline at end of file +1c52212369692ca7c0b16a14e3a403cd4c5fbffc \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index a8e5beb227..76c016631b 100644 --- a/src/btree.c +++ b/src/btree.c @@ -8923,23 +8923,19 @@ static int btreeHeapPull(u32 *aHeap, u32 *pOut){ ** These checks are done: ** ** 1. Make sure that cells and freeblocks do not overlap -** but combine to completely cover the page. -** NO 2. Make sure cell keys are in order. -** NO 3. Make sure no key is less than or equal to zLowerBound. -** NO 4. Make sure no key is greater than or equal to zUpperBound. -** 5. Check the integrity of overflow pages. -** 6. Recursively call checkTreePage on all children. -** 7. Verify that the depth of all children is the same. -** 8. Make sure this page is at least 33% full or else it is -** the root of the tree. +** 2. Ensure that every byte of the page is accounted for +** 3. Make sure integer cell keys are in order. +** 4. Check the integrity of overflow pages. +** 5. Recursively call checkTreePage on all children. +** 6. Verify that the depth of all children is the same. */ static int checkTreePage( IntegrityCk *pCheck, /* Context for the sanity check */ int iPage, /* Page number of the page to check */ - i64 *pnParentMinKey, - i64 *pnParentMaxKey + i64 minKey, /* All integer primary keys must be >= this value */ + i64 maxKey /* All integer primary keys must be <= this value */ ){ - MemPage *pPage; + MemPage *pPage = 0; int i, rc, depth, d2, pgno, cnt; int hdr, cellStart; int nCell; @@ -8948,8 +8944,9 @@ static int checkTreePage( int usableSize; u32 *heap = 0; u32 x, prev = 0; - i64 nMinKey = 0; - i64 nMaxKey = 0; + u32 pc; + int doCoverageCheck = 1; + int contentOffset; const char *saved_zPfx = pCheck->zPfx; int saved_v1 = pCheck->v1; int saved_v2 = pCheck->v2; @@ -8963,8 +8960,7 @@ static int checkTreePage( pCheck->zPfx = "Page %d: "; pCheck->v1 = iPage; if( (rc = btreeGetPage(pBt, (Pgno)iPage, &pPage, 0))!=0 ){ - checkAppendMsg(pCheck, - "unable to get the page. error code=%d", rc); + checkAppendMsg(pCheck, "unreadable - error code=%d", rc); depth = -1; goto end_of_check; } @@ -8974,45 +8970,56 @@ static int checkTreePage( pPage->isInit = 0; if( (rc = btreeInitPage(pPage))!=0 ){ assert( rc==SQLITE_CORRUPT ); /* The only possible error from InitPage */ - checkAppendMsg(pCheck, - "btreeInitPage() returns error code %d", rc); - releasePage(pPage); + checkAppendMsg(pCheck, "corrupt header or freelist"); depth = -1; goto end_of_check; } - /* Check out all the cells. - */ + /* Initialize variables used during cell scan */ + data = pPage->aData; + hdr = pPage->hdrOffset; depth = 0; + 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( nCell==pPage->nCell ); + + /* EVIDENCE-OF: R-23882-45353 The cell pointer array of a b-tree page + ** immediately follows the b-tree page header. */ + cellStart = pPage->cellOffset; + + /* EVIDENCE-OF: R-02776-14802 The cell pointer array consists of K 2-byte + ** integer offsets to the cell contents. */ + pCheck->zPfx = "Page %d cell %d: "; for(i=0; inCell && pCheck->mxErr; i++){ - u8 *pCell; - u32 sz; CellInfo info; - /* Check payload overflow pages - */ - pCheck->zPfx = "On tree page %d cell %d: "; - pCheck->v1 = iPage; pCheck->v2 = i; - pCell = findCell(pPage,i); - pPage->xParseCell(pPage, pCell, &info); - sz = info.nPayload; - /* For intKey pages, check that the keys are in order. - */ - 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); - } - nMaxKey = 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]); + pc = get2byteAligned(&data[cellStart+i*2]); + if( pcusableSize-4 ){ + checkAppendMsg(pCheck, + "offset (%d) out of range %d..%d", + pc, contentOffset, usableSize-4 + ); + doCoverageCheck = 0; + continue; + } + pPage->xParseCell(pPage, &data[pc], &info); + if( pc+info.nSize > usableSize ){ + checkAppendMsg(pCheck, "oversized content"); + doCoverageCheck = 0; + }else + + /* Scan overflow pages */ + if( info.nPayload>info.nLocal ){ + int nPage; + Pgno pgnoOvfl; + assert( pc+info.iOverflow <= usableSize-4 ); + nPage = (info.nPayload - info.nLocal + usableSize-5)/(usableSize-4); + pgnoOvfl = get4byte(&data[pc+info.iOverflow]); #ifndef SQLITE_OMIT_AUTOVACUUM if( pBt->autoVacuum ){ checkPtrmap(pCheck, pgnoOvfl, PTRMAP_OVERFLOW1, iPage); @@ -9021,104 +9028,58 @@ static int checkTreePage( checkList(pCheck, 0, pgnoOvfl, nPage); } - /* Check sanity of left child page. - */ + /* Check sanity of left child page. */ if( !pPage->leaf ){ - pgno = get4byte(pCell); + pgno = get4byte(&data[pc]); #ifndef SQLITE_OMIT_AUTOVACUUM if( pBt->autoVacuum ){ checkPtrmap(pCheck, pgno, PTRMAP_BTREE, iPage); } #endif - d2 = checkTreePage(pCheck, pgno, &nMinKey, i==0?NULL:&nMaxKey); + d2 = checkTreePage(pCheck, pgno, minKey, info.nKey); if( i>0 && d2!=depth ){ - checkAppendMsg(pCheck, "Child page depth differs"); + checkAppendMsg(pCheck, "inconsistent subtree depth"); } depth = d2; } + + /* For intKey pages, check that the keys are in order. */ + if( pPage->intKey ){ + i64 mx = maxKey - (nCell - (i+1)); + if( info.nKeymx ){ + checkAppendMsg(pCheck, "rowid %lld out of range %lld..%lld", + info.nKey, minKey, mx); + }else{ + minKey = info.nKey+1; + } + } } if( !pPage->leaf ){ - pgno = get4byte(&pPage->aData[pPage->hdrOffset+8]); - pCheck->zPfx = "On page %d at right child: "; - pCheck->v1 = iPage; + pgno = get4byte(&data[pPage->hdrOffset+8]); #ifndef SQLITE_OMIT_AUTOVACUUM if( pBt->autoVacuum ){ + pCheck->zPfx = "Page %d right child: "; checkPtrmap(pCheck, pgno, PTRMAP_BTREE, iPage); } #endif - checkTreePage(pCheck, pgno, NULL, !pPage->nCell?NULL:&nMaxKey); - } - - /* For intKey leaf pages, check that the min/max keys are in order - ** with any left/parent/right pages. - */ - pCheck->zPfx = "Page %d: "; - pCheck->v1 = iPage; - 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); - } + d2 = checkTreePage(pCheck, pgno, minKey, maxKey); + if( d2!=depth && nCell>0 ){ + checkAppendMsg(pCheck, "inconsistent subtree depth"); } } /* Check for complete coverage of the page */ - data = pPage->aData; - hdr = pPage->hdrOffset; - heap = (u32*)sqlite3PageMalloc( pBt->pageSize ); - pCheck->zPfx = 0; - if( heap==0 ){ - pCheck->mallocFailed = 1; - }else{ - int contentOffset = get2byteNotZero(&data[hdr+5]); - assert( contentOffset<=usableSize ); /* Enforced by btreeInitPage() */ + if( doCoverageCheck ){ + heap = pCheck->heap; heap[0] = 0; 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{ - btreeHeapInsert(heap, (pc<<16)|(pc+size-1)); - } + assert( pc+size <= usableSize ); /* Otherwise doCoverageCheck==0 */ + btreeHeapInsert(heap, (pc<<16)|(pc+size-1)); } /* 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 @@ -9145,10 +9106,10 @@ static int checkTreePage( assert( heap[0]>0 ); assert( (heap[1]>>16)==0 ); btreeHeapPull(heap,&prev); + pCheck->zPfx = "Page %d: "; while( btreeHeapPull(heap,&x) ){ if( (prev&0xffff)+1>(x>>16) ){ - checkAppendMsg(pCheck, - "Multiple uses for byte %u of page %d", x>>16, iPage); + checkAppendMsg(pCheck, "multiple uses for byte %u", x>>16); break; }else{ cnt += (x>>16) - (prev&0xffff) - 1; @@ -9163,14 +9124,12 @@ static int checkTreePage( */ if( heap[0]==0 && cnt!=data[hdr+7] ){ checkAppendMsg(pCheck, - "Fragmentation of %d bytes reported as %d on page %d", - cnt, data[hdr+7], iPage); + "fragmentation of %d should be %d", data[hdr+7], cnt); } } - sqlite3PageFree(heap); - releasePage(pPage); end_of_check: + releasePage(pPage); pCheck->zPfx = saved_zPfx; pCheck->v1 = saved_v1; pCheck->v2 = saved_v2; @@ -9200,14 +9159,15 @@ char *sqlite3BtreeIntegrityCheck( int *pnErr /* Write number of errors seen to this variable */ ){ Pgno i; - int nRef; + VVA_ONLY( int nRef ); IntegrityCk sCheck; BtShared *pBt = p->pBt; + int savedDbFlags = pBt->db->flags; char zErr[100]; sqlite3BtreeEnter(p); assert( p->inTrans>TRANS_NONE && pBt->inTransaction>TRANS_NONE ); - nRef = sqlite3PagerRefcount(pBt->pPager); + assert( (nRef = sqlite3PagerRefcount(pBt->pPager))>=0 ); sCheck.pBt = pBt; sCheck.pPager = pBt->pPager; sCheck.nPage = btreePagecount(sCheck.pBt); @@ -9217,21 +9177,26 @@ char *sqlite3BtreeIntegrityCheck( sCheck.zPfx = 0; sCheck.v1 = 0; sCheck.v2 = 0; - *pnErr = 0; + sCheck.aPgRef = 0; + sCheck.heap = 0; + sqlite3StrAccumInit(&sCheck.errMsg, 0, zErr, sizeof(zErr), SQLITE_MAX_LENGTH); if( sCheck.nPage==0 ){ - sqlite3BtreeLeave(p); - return 0; + goto integrity_ck_cleanup; } sCheck.aPgRef = sqlite3MallocZero((sCheck.nPage / 8)+ 1); if( !sCheck.aPgRef ){ - *pnErr = 1; - sqlite3BtreeLeave(p); - return 0; + sCheck.nErr = 1; + goto integrity_ck_cleanup; } + sCheck.heap = (u32*)sqlite3PageMalloc( pBt->pageSize ); + if( sCheck.heap==0 ){ + sCheck.mallocFailed = 1; + goto integrity_ck_cleanup; + } + i = PENDING_BYTE_PAGE(pBt); if( i<=sCheck.nPage ) setPageReferenced(&sCheck, i); - sqlite3StrAccumInit(&sCheck.errMsg, 0, zErr, sizeof(zErr), SQLITE_MAX_LENGTH); /* Check the integrity of the freelist */ @@ -9242,17 +9207,18 @@ char *sqlite3BtreeIntegrityCheck( /* Check all the tables. */ + pBt->db->flags &= ~SQLITE_CellSizeCk; for(i=0; (int)iautoVacuum && aRoot[i]>1 ){ checkPtrmap(&sCheck, aRoot[i], PTRMAP_ROOTPAGE, 0); } #endif - sCheck.zPfx = "List of tree roots: "; - checkTreePage(&sCheck, aRoot[i], NULL, NULL); - sCheck.zPfx = 0; + checkTreePage(&sCheck, aRoot[i], SMALLEST_INT64, LARGEST_INT64); } + pBt->db->flags = savedDbFlags; /* Make sure every page in the file is referenced */ @@ -9276,28 +9242,20 @@ char *sqlite3BtreeIntegrityCheck( #endif } - /* Make sure this analysis did not leave any unref() pages. - ** This is an internal consistency check; an integrity check - ** of the integrity check. - */ - if( NEVER(nRef != sqlite3PagerRefcount(pBt->pPager)) ){ - checkAppendMsg(&sCheck, - "Outstanding page count goes from %d to %d during this analysis", - nRef, sqlite3PagerRefcount(pBt->pPager) - ); - } - /* Clean up and report errors. */ - sqlite3BtreeLeave(p); +integrity_ck_cleanup: + sqlite3PageFree(sCheck.heap); sqlite3_free(sCheck.aPgRef); if( sCheck.mallocFailed ){ sqlite3StrAccumReset(&sCheck.errMsg); - *pnErr = sCheck.nErr+1; - return 0; + sCheck.nErr++; } *pnErr = sCheck.nErr; if( sCheck.nErr==0 ) sqlite3StrAccumReset(&sCheck.errMsg); + /* Make sure this analysis did not leave any unref() pages. */ + assert( nRef==sqlite3PagerRefcount(pBt->pPager) ); + sqlite3BtreeLeave(p); return sqlite3StrAccumFinish(&sCheck.errMsg); } #endif /* SQLITE_OMIT_INTEGRITY_CHECK */ diff --git a/src/btreeInt.h b/src/btreeInt.h index d74ea5557f..cbf6c99847 100644 --- a/src/btreeInt.h +++ b/src/btreeInt.h @@ -682,6 +682,7 @@ struct IntegrityCk { const char *zPfx; /* Error message prefix */ int v1, v2; /* Values for up to two %d fields in zPfx */ StrAccum errMsg; /* Accumulate the error message text here */ + u32 *heap; /* Min-heap used for analyzing cell coverage */ }; /* diff --git a/src/pager.c b/src/pager.c index 982413ca8a..060edb8d1d 100644 --- a/src/pager.c +++ b/src/pager.c @@ -6387,12 +6387,14 @@ u8 sqlite3PagerIsreadonly(Pager *pPager){ return pPager->readOnly; } +#ifdef SQLITE_DEBUG /* ** Return the number of references to the pager. */ int sqlite3PagerRefcount(Pager *pPager){ return sqlite3PcacheRefCount(pPager->pPCache); } +#endif /* ** Return the approximate number of bytes of memory currently diff --git a/src/pager.h b/src/pager.h index e07fa88fc5..e3b57f435e 100644 --- a/src/pager.h +++ b/src/pager.h @@ -173,7 +173,9 @@ int sqlite3PagerSharedLock(Pager *pPager); /* Functions used to query pager state and configuration. */ u8 sqlite3PagerIsreadonly(Pager*); u32 sqlite3PagerDataVersion(Pager*); -int sqlite3PagerRefcount(Pager*); +#ifdef SQLITE_DEBUG + int sqlite3PagerRefcount(Pager*); +#endif int sqlite3PagerMemUsed(Pager*); const char *sqlite3PagerFilename(Pager*, int); const sqlite3_vfs *sqlite3PagerVfs(Pager*); diff --git a/test/corrupt2.test b/test/corrupt2.test index 805a6148f0..3cc2ed3d9a 100644 --- a/test/corrupt2.test +++ b/test/corrupt2.test @@ -248,8 +248,8 @@ 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 2 cell 0: 2nd reference to page 10 +Page 2 cell 1: inconsistent subtree depth Page 4 is never used}} db2 close diff --git a/test/corrupt3.test b/test/corrupt3.test index 436a466189..230626a447 100644 --- a/test/corrupt3.test +++ b/test/corrupt3.test @@ -97,7 +97,7 @@ do_test corrupt3-1.10 { PRAGMA integrity_check } } {0 {{*** in database main *** -On tree page 2 cell 0: invalid page number 4 +Page 2 cell 0: invalid page number 4 Page 3 is never used}}} do_test corrupt3-1.11 { db close @@ -112,7 +112,7 @@ do_test corrupt3-1.12 { PRAGMA integrity_check } } {0 {{*** in database main *** -On tree page 2 cell 0: 1 of 1 pages missing from overflow list starting at 0 +Page 2 cell 0: 1 of 1 pages missing from overflow list starting at 0 Page 3 is never used}}} finish_test diff --git a/test/corrupt7.test b/test/corrupt7.test index db92cf1de9..18deefb19b 100644 --- a/test/corrupt7.test +++ b/test/corrupt7.test @@ -69,37 +69,20 @@ integrity_check corrupt7-1.4 # 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 cell_size_check=OFF; PRAGMA integrity_check(1)} +} {{*** in database main *** +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 cell_size_check=OFF; PRAGMA integrity_check(1)} +} {{*** in database main *** +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. diff --git a/test/corruptE.test b/test/corruptE.test index 4d5b5db3d6..10555126d3 100644 --- a/test/corruptE.test +++ b/test/corruptE.test @@ -82,9 +82,8 @@ do_test corruptE-2.1 { 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} + regexp {rowid \d+ out of range \d+\.\.\d+} $ans] +} {1} do_test corruptE-2.2 { db close @@ -98,9 +97,8 @@ do_test corruptE-2.2 { 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} + regexp {rowid \d+ out of range \d+\.\.\d+} $ans] +} {1} do_test corruptE-2.3 { db close @@ -115,7 +113,7 @@ do_test corruptE-2.3 { set res [ catchsql {PRAGMA integrity_check} ] set ans [lindex $res 1] - list [regexp {out of order.*max larger than parent min} $ans] + regexp {rowid \d+ out of range \d+\.\.\d+} $ans] } {1} do_test corruptE-2.4 { @@ -130,10 +128,9 @@ do_test corruptE-2.4 { set res [ catchsql {PRAGMA integrity_check} ] set ans [lindex $res 1] - list [regexp {out of order.*min less than parent max} $ans] + regexp {rowid \d+ out of range \d+\.\.\d+} $ans] } {1} - set tests [list {10233 0xd0} \ {941 0x42} \ {1028 0x53} \ @@ -171,7 +168,7 @@ foreach test $tests { set res [ catchsql {PRAGMA integrity_check} ] set ans [lindex $res 1] - list [regexp {out of order} $ans] + list [regexp {out of range|database disk image is malformed} $ans] } {1} incr tc 1 } diff --git a/test/pragma.test b/test/pragma.test index 587a03c8a6..aa238cedf2 100644 --- a/test/pragma.test +++ b/test/pragma.test @@ -1749,14 +1749,14 @@ do_test 21.1 { } {100} set mainerr {*** in database main *** -Multiple uses for byte 672 of page 15} +Page 15: multiple uses for byte 672} set auxerr {*** in database aux *** -Multiple uses for byte 672 of page 15} +Page 15: Multiple uses for byte 672} set mainerr {/{\*\*\* in database main \*\*\* -Multiple uses for byte 672 of page 15}.*/} +Page 15: multiple uses for byte 672}.*/} set auxerr {/{\*\*\* in database aux \*\*\* -Multiple uses for byte 672 of page 15}.*/} +Page 15: multiple uses for byte 672}.*/} do_test 22.2 { catch { db close }