Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Enhanced detection of problems on the freelist and on overflow list in PRAGMA integrity_check. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA3-256: |
11e58f5b37d99848978007d834d187c2 |
User & Date: | drh 2018-07-20 13:39:28.100 |
Context
2018-07-20
| ||
15:44 | New checks in PRAGMA integrity_check to validate the autovacuum settings in the header. (check-in: a4663f09c9 user: drh tags: trunk) | |
13:39 | Enhanced detection of problems on the freelist and on overflow list in PRAGMA integrity_check. (check-in: 11e58f5b37 user: drh tags: trunk) | |
2018-07-19
| ||
15:27 | Avoid a branch in the commit logic that is unreachable when compiled without SQLITE_ENABLE_BATCH_ATOMIC_WRITE. (check-in: 271b8980c3 user: drh tags: trunk) | |
Changes
Changes to src/btree.c.
︙ | ︙ | |||
9333 9334 9335 9336 9337 9338 9339 | ** reference to the page, add an error message to pCheck->zErrMsg. ** Return 1 if there are 2 or more references to the page and 0 if ** if this is the first reference to the page. ** ** Also check that the page number is in bounds. */ static int checkRef(IntegrityCk *pCheck, Pgno iPage){ | < | | 9333 9334 9335 9336 9337 9338 9339 9340 9341 9342 9343 9344 9345 9346 9347 | ** reference to the page, add an error message to pCheck->zErrMsg. ** Return 1 if there are 2 or more references to the page and 0 if ** if this is the first reference to the page. ** ** Also check that the page number is in bounds. */ static int checkRef(IntegrityCk *pCheck, Pgno iPage){ if( iPage>pCheck->nPage || iPage==0 ){ checkAppendMsg(pCheck, "invalid page number %d", iPage); return 1; } if( getPageReferenced(pCheck, iPage) ){ checkAppendMsg(pCheck, "2nd reference to page %d", iPage); return 1; } |
︙ | ︙ | |||
9389 9390 9391 9392 9393 9394 9395 | IntegrityCk *pCheck, /* Integrity checking context */ int isFreeList, /* True for a freelist. False for overflow page list */ int iPage, /* Page number for first page in the list */ int N /* Expected number of pages in the list */ ){ int i; int expected = N; | | | < < < < < < > | 9388 9389 9390 9391 9392 9393 9394 9395 9396 9397 9398 9399 9400 9401 9402 9403 9404 9405 9406 9407 | IntegrityCk *pCheck, /* Integrity checking context */ int isFreeList, /* True for a freelist. False for overflow page list */ int iPage, /* Page number for first page in the list */ int N /* Expected number of pages in the list */ ){ int i; int expected = N; int nErrAtStart = pCheck->nErr; while( iPage!=0 && pCheck->mxErr ){ DbPage *pOvflPage; unsigned char *pOvflData; if( checkRef(pCheck, iPage) ) break; N--; if( sqlite3PagerGet(pCheck->pPager, (Pgno)iPage, &pOvflPage, 0) ){ checkAppendMsg(pCheck, "failed to get page %d", iPage); break; } pOvflData = (unsigned char *)sqlite3PagerGetData(pOvflPage); if( isFreeList ){ int n = get4byte(&pOvflData[4]); |
︙ | ︙ | |||
9443 9444 9445 9446 9447 9448 9449 | i = get4byte(pOvflData); checkPtrmap(pCheck, i, PTRMAP_OVERFLOW2, iPage); } } #endif iPage = get4byte(pOvflData); sqlite3PagerUnref(pOvflPage); | | | | < > > > | 9437 9438 9439 9440 9441 9442 9443 9444 9445 9446 9447 9448 9449 9450 9451 9452 9453 9454 9455 9456 | i = get4byte(pOvflData); checkPtrmap(pCheck, i, PTRMAP_OVERFLOW2, iPage); } } #endif iPage = get4byte(pOvflData); sqlite3PagerUnref(pOvflPage); } if( N && nErrAtStart==pCheck->nErr ){ checkAppendMsg(pCheck, "%s is %d but should be %d", isFreeList ? "size" : "overflow list length", expected-N, expected); } } #endif /* SQLITE_OMIT_INTEGRITY_CHECK */ /* ** An implementation of a min-heap. ** |
︙ | ︙ |
Changes to test/corrupt2.test.
︙ | ︙ | |||
587 588 589 590 591 592 593 | sqlite3 db test.db execsql { PRAGMA freelist_count } } {2} do_execsql_test 14.3 { PRAGMA integrity_check; } {{*** in database main *** | | | | 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 | sqlite3 db test.db execsql { PRAGMA freelist_count } } {2} do_execsql_test 14.3 { PRAGMA integrity_check; } {{*** in database main *** Main freelist: size is 3 but should be 2}} # Use 2 of the free pages on the free-list. # do_execsql_test 14.4 { INSERT INTO t1 VALUES(randomblob(2500)); PRAGMA freelist_count; } {0} do_execsql_test 14.5 { PRAGMA integrity_check; } {{*** in database main *** Main freelist: size is 1 but should be 0}} finish_test finish_test |
Changes to test/corrupt3.test.
︙ | ︙ | |||
63 64 65 66 67 68 69 | do_test corrupt3-1.5 { hexio_get_int [hexio_read test.db 2048 4] } 0 ;# First chained overflow is 0 integrity_check corrupt3-1.6 # Make the overflow chain loop back on itself. See if the | | < > > | > > > | 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 | do_test corrupt3-1.5 { hexio_get_int [hexio_read test.db 2048 4] } 0 ;# First chained overflow is 0 integrity_check corrupt3-1.6 # Make the overflow chain loop back on itself. See if the # corruption is detected. # do_test corrupt3-1.7 { db close hexio_write test.db 2048 [hexio_render_int32 3] sqlite3 db test.db catchsql { SELECT x FROM t1 } } [list 0 $bigstring] do_test corrupt3-1.8 { catchsql { PRAGMA integrity_check } } {0 {{*** in database main *** On tree page 2 cell 0: 2nd reference to page 3}}} # Change the pointer for the first page of the overflow # change to be a non-existant page. # do_test corrupt3-1.9 { db close hexio_write test.db 2044 [hexio_render_int32 4] |
︙ | ︙ | |||
107 108 109 110 111 112 113 | } } [list 1 {database disk image is malformed}] do_test corrupt3-1.12 { catchsql { PRAGMA integrity_check } } {0 {{*** in database main *** | | | 111 112 113 114 115 116 117 118 119 120 121 | } } [list 1 {database disk image is malformed}] do_test corrupt3-1.12 { catchsql { PRAGMA integrity_check } } {0 {{*** in database main *** On tree page 2 cell 0: overflow list length is 0 but should be 1 Page 3 is never used}}} finish_test |