SQLite

Check-in [11e58f5b37]
Login

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: 11e58f5b37d99848978007d834d187c262d904eb9d58924742e028d7cb324e64
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
Side-by-Side Diff Ignore Whitespace Patch
Changes to src/btree.c.
9333
9334
9335
9336
9337
9338
9339
9340
9341

9342
9343
9344
9345
9346
9347
9348
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==0 ) return 1;
  if( iPage>pCheck->nPage ){
  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
9396
9397


9398
9399
9400
9401
9402
9403
9404
9405
9406

9407
9408
9409
9410
9411
9412
9413
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 iFirst = iPage;
  while( N-- > 0 && pCheck->mxErr ){
  int nErrAtStart = pCheck->nErr;
  while( iPage!=0 && pCheck->mxErr ){
    DbPage *pOvflPage;
    unsigned char *pOvflData;
    if( iPage<1 ){
      checkAppendMsg(pCheck,
         "%d of %d pages missing from overflow list starting at %d",
          N+1, expected, iFirst);
      break;
    }
    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
9450
9451
9452



9453



9454
9455
9456
9457
9458
9459
9460
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( isFreeList && N<(iPage!=0) ){
      checkAppendMsg(pCheck, "free-page count in header is too small");
  }
  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
594

595
596
597
598
599
600
601
602
603
604
605
606

607
608
609
610
611
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: free-page count in header is too small}}
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 ***
Page 3 is never used}}
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
70

71
72
73
74
75
76
77
78
79
80


81




82
83
84
85
86
87
88
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.   (Actually, the last pointer in
# corruption is detected.
# an overflow chain is ignored, so this is not an error.)
#
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 {
integrity_check corrupt3-1.8
    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
114

115
116
117
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: 1 of 1 pages missing from overflow list starting at 0
On tree page 2 cell 0: overflow list length is 0 but should be 1
Page 3 is never used}}}

finish_test