/ Check-in [0659a666]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Fixed crash in integrity_check with corrupt content offset size in page header. (CVS 5881)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 0659a666ff0a9fc81ee4df3c35e535164c79e588
User & Date: shane 2008-11-11 17:36:30
Context
2008-11-11
18:28
Cleanup in flattenSubquery. Add OOM tests for flattenSubquery. Fix issues with OOM errors causes problems for flattenSubquery. Ticket #3485. (CVS 5882) check-in: ea5f4baa user: drh tags: trunk
17:36
Fixed crash in integrity_check with corrupt content offset size in page header. (CVS 5881) check-in: 0659a666 user: shane tags: trunk
15:48
Avoid signed/unsigned comparison warnings in bitvec.c by changing the types of loop variables to unsigned int. (CVS 5880) check-in: da869446 user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/btree.c.

     5      5   ** a legal notice, here is a blessing:
     6      6   **
     7      7   **    May you do good and not evil.
     8      8   **    May you find forgiveness for yourself and forgive others.
     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   *************************************************************************
    12         -** $Id: btree.c,v 1.528 2008/11/10 17:14:58 shane Exp $
           12  +** $Id: btree.c,v 1.529 2008/11/11 17:36:30 shane Exp $
    13     13   **
    14     14   ** This file implements a external (disk-based) database using BTrees.
    15     15   ** See the header comment on "btreeInt.h" for additional information.
    16     16   ** Including a description of file format and an overview of operation.
    17     17   */
    18     18   #include "btreeInt.h"
    19     19   
................................................................................
  6796   6796     */
  6797   6797     data = pPage->aData;
  6798   6798     hdr = pPage->hdrOffset;
  6799   6799     hit = sqlite3PageMalloc( pBt->pageSize );
  6800   6800     if( hit==0 ){
  6801   6801       pCheck->mallocFailed = 1;
  6802   6802     }else{
  6803         -    memset(hit, 0, usableSize );
  6804         -    memset(hit, 1, get2byte(&data[hdr+5]));
         6803  +    u16 contentOffset = get2byte(&data[hdr+5]);
         6804  +    if (contentOffset > usableSize) {
         6805  +      checkAppendMsg(pCheck, 0, 
         6806  +                     "Corruption detected in header on page %d",iPage,0);
         6807  +      contentOffset = usableSize; /* try to keep going */
         6808  +    }
         6809  +    memset(hit+contentOffset, 0, usableSize-contentOffset);
         6810  +    memset(hit, 1, contentOffset);
  6805   6811       nCell = get2byte(&data[hdr+3]);
  6806   6812       cellStart = hdr + 12 - 4*pPage->leaf;
  6807   6813       for(i=0; i<nCell; i++){
  6808   6814         int pc = get2byte(&data[cellStart+i*2]);
  6809   6815         u16 size = 1024;
  6810   6816         int j;
  6811   6817         if( pc<=usableSize ){

Changes to test/corruptC.test.

    11     11   # This file implements regression tests for SQLite library.
    12     12   #
    13     13   # This file implements tests to make sure SQLite does not crash or
    14     14   # segfault if it sees a corrupt database file.  It creates a base
    15     15   # data base file, then tests that single byte corruptions in 
    16     16   # increasingly larger quantities are handled gracefully.
    17     17   #
    18         -# $Id: corruptC.test,v 1.1 2008/10/31 13:57:40 shane Exp $
           18  +# $Id: corruptC.test,v 1.2 2008/11/11 17:36:30 shane Exp $
    19     19   
    20     20   catch {file delete -force test.db test.db-journal test.bu}
    21     21   
    22     22   set testdir [file dirname $argv0]
    23     23   source $testdir/tester.tcl
           24  +
           25  +# Set a uniform random seed
           26  +expr srand(0)
    24     27   
    25     28   # Construct a compact, dense database for testing.
    26     29   #
    27     30   do_test corruptC-1.1 {
    28     31     execsql {
    29     32       BEGIN;
    30     33       CREATE TABLE t1(x);
................................................................................
    64     67   }
    65     68   
    66     69   # Setup for the tests.  Make a backup copy of the good database in test.bu.
    67     70   #
    68     71   copy_file test.db test.bu
    69     72   set fsize [file size test.db]
    70     73   
    71         -for {set tn 1} {$tn<=1024} {incr tn 1} {
           74  +#
           75  +# first test some specific corruption tests found from earlier runs
           76  +#
           77  +
           78  +# test that a corrupt content offset size is handled (seed 5577)
           79  +do_test corruptC-2.1 {
           80  +  db close
           81  +  copy_file test.bu test.db
           82  +
           83  +  # insert corrupt byte(s)
           84  +  hexio_write test.db 2053 04
           85  +
           86  +  sqlite3 db test.db
           87  +  catchsql {PRAGMA integrity_check}
           88  +} {0 {{*** in database main ***
           89  +Corruption detected in header on page 3
           90  +Multiple uses for byte 604 of page 3}}}
           91  +
           92  +
           93  +#
           94  +# now test for a series of quasi-random seeds
           95  +#
           96  +for {set tn 0} {$tn<=1024} {incr tn 1} {
           97  +
           98  +  # Set a quasi-random random seed
           99  +  expr srand($tn)
    72    100   
    73    101     # setup for test
    74    102     db close
    75    103     copy_file test.bu test.db
    76    104   
    77    105     # Seek to a random location in the file, and write a random single byte
    78    106     # value.  Then do various operations on the file to make sure that
    79    107     # the database engine can handle the corruption gracefully.
    80    108     #
    81    109     set last 0
    82    110     for {set i 1} {$i<=1024 && !$last} {incr i 1} {
    83    111   
    84    112       # insert random byte at random location
    85         -    set fd [open test.db r+]
    86         -    fconfigure $fd -translation binary
    87         -    seek $fd [random $fsize]
    88         -    puts -nonewline $fd [format "%c" [expr [random 255]]]
    89         -    close $fd
          113  +    hexio_write test.db [random $fsize] [format %02x [random 255]]
    90    114   
    91    115       # do a few random operations to make sure that if 
    92    116       # they error, they error gracefully instead of crashing.
    93         -    do_test corruptC-2.$tn.$i.1 {
          117  +    do_test corruptC-3.$tn.$i.1 {
    94    118         sqlite3 db test.db
    95    119         catchsql {SELECT count(*) FROM sqlite_master}
    96    120         set x {}
    97    121       } {}
    98         -    do_test corruptC-2.$tn.$i.2 {
          122  +    do_test corruptC-3.$tn.$i.2 {
    99    123         catchsql {SELECT count(*) FROM t1}
   100    124         set x {}
   101    125       } {}
   102         -    do_test corruptC-2.$tn.$i.3 {
          126  +    do_test corruptC-3.$tn.$i.3 {
   103    127         catchsql {SELECT count(*) FROM t1 WHERE x>13}
   104    128         set x {}
   105    129       } {}
   106         -    do_test corruptC-2.$tn.$i.4 {
          130  +    do_test corruptC-3.$tn.$i.4 {
   107    131         catchsql {SELECT count(*) FROM t2}
   108    132         set x {}
   109    133       } {}
   110         -    do_test corruptC-2.$tn.$i.5 {
          134  +    do_test corruptC-3.$tn.$i.5 {
   111    135         catchsql {SELECT count(*) FROM t2 WHERE x<13}
   112    136         set x {}
   113    137       } {}
   114    138   
   115    139       # check the integrity of the database.
   116    140       # once the corruption is detected, we can stop.
   117    141       ifcapable {integrityck} {
................................................................................
   126    150       ifcapable {!integrityck} {
   127    151         if { $i > 5 } {
   128    152           set last -1
   129    153         }
   130    154       }
   131    155   
   132    156       # Check that no page references were leaked.
   133         -    do_test corruptC-2.$tn.$i.6 {
          157  +    do_test corruptC-3.$tn.$i.6 {
   134    158         set bt [btree_from_db db]
   135    159         db_enter db
   136    160         array set stats [btree_pager_stats $bt]
   137    161         db_leave db
   138    162         set stats(ref)
   139    163       } {0}
   140    164