/ Check-in [ec18667e]
Login

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

Overview
Comment:Fixed crash during an UPDATE when free cell size is corrupt. (CVS 5887)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:ec18667e2d2826a27f2c052ba3790ab5b8cf0bc4
User & Date: shane 2008-11-11 22:18:20
Context
2008-11-12
04:55
Fixed a few more crashes when dealing with corrupt db files. (CVS 5888) check-in: f8bb34e4 user: shane tags: trunk
2008-11-11
22:18
Fixed crash during an UPDATE when free cell size is corrupt. (CVS 5887) check-in: ec18667e user: shane tags: trunk
20:51
Prevent a crash during an UPDATE when the cell offset is corrupt. (CVS 5886) check-in: 99d4172e user: shane tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/btree.c.

5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
....
4647
4648
4649
4650
4651
4652
4653


4654
4655
4656
4657
4658
4659
4660
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** $Id: btree.c,v 1.530 2008/11/11 20:51:51 shane Exp $
**
** This file implements a external (disk-based) database using BTrees.
** See the header comment on "btreeInt.h" for additional information.
** Including a description of file format and an overview of operation.
*/
#include "btreeInt.h"

................................................................................
      defragmentPage(pPage);
      top = get2byte(&data[hdr+5]);
      assert( end + sz <= top );
    }
    idx = allocateSpace(pPage, sz);
    assert( idx>0 );
    assert( end <= get2byte(&data[hdr+5]) );


    pPage->nCell++;
    pPage->nFree -= 2;
    memcpy(&data[idx+nSkip], pCell+nSkip, sz-nSkip);
    for(j=end-2, ptr=&data[j]; j>ins; j-=2, ptr-=2){
      ptr[0] = ptr[-2];
      ptr[1] = ptr[-1];
    }







|







 







>
>







5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
....
4647
4648
4649
4650
4651
4652
4653
4654
4655
4656
4657
4658
4659
4660
4661
4662
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** $Id: btree.c,v 1.531 2008/11/11 22:18:20 shane Exp $
**
** This file implements a external (disk-based) database using BTrees.
** See the header comment on "btreeInt.h" for additional information.
** Including a description of file format and an overview of operation.
*/
#include "btreeInt.h"

................................................................................
      defragmentPage(pPage);
      top = get2byte(&data[hdr+5]);
      assert( end + sz <= top );
    }
    idx = allocateSpace(pPage, sz);
    assert( idx>0 );
    assert( end <= get2byte(&data[hdr+5]) );
    if (idx+sz > pPage->pBt->usableSize) 
      return SQLITE_CORRUPT_BKPT;
    pPage->nCell++;
    pPage->nFree -= 2;
    memcpy(&data[idx+nSkip], pCell+nSkip, sz-nSkip);
    for(j=end-2, ptr=&data[j]; j>ins; j-=2, ptr-=2){
      ptr[0] = ptr[-2];
      ptr[1] = ptr[-1];
    }

Changes to test/corruptC.test.

11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
...
108
109
110
111
112
113
114












115
116
117
118
119
120
121
...
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
...
182
183
184
185
186
187
188



189
190
191
192
193
194
195

196
197
198
199
200
201
202
# This file implements regression tests for SQLite library.
#
# This file implements tests to make sure SQLite does not crash or
# segfault if it sees a corrupt database file.  It creates a base
# data base file, then tests that single byte corruptions in 
# increasingly larger quantities are handled gracefully.
#
# $Id: corruptC.test,v 1.3 2008/11/11 20:51:51 shane Exp $

catch {file delete -force test.db test.db-journal test.bu}

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Set a uniform random seed
................................................................................
  hexio_write test.db 3714 [format %02x 0x58]
  hexio_write test.db 3746 [format %02x 0x9a]

  sqlite3 db test.db
  catchsql {UPDATE t1 SET y=1}
} {0 {}}













#
# now test for a series of quasi-random seeds
#
for {set tn 0} {$tn<=1024} {incr tn 1} {

  # Set a quasi-random random seed
  expr srand($tn)
................................................................................
      set x {}
    } {}
    do_test corruptC-3.$tn.$i.5 {
      catchsql {SELECT count(*) FROM t2 WHERE x<13}
      set x {}
    } {}
    do_test corruptC-3.$tn.$i.6 {
      catchsql {UPDATE t1 SET y=1}
      set x {}
    } {}
    do_test corruptC-3.$tn.$i.7 {
      catchsql {UPDATE t2 SET y=2}
      set x {}
    } {}

    # check the integrity of the database.
    # once the corruption is detected, we can stop.
    ifcapable {integrityck} {
      set res [ catchsql {PRAGMA integrity_check} ]
................................................................................
    ifcapable {!integrityck} {
      if { $i > 5 } {
        set last -1
      }
    }

    # Check that no page references were leaked.



    do_test corruptC-3.$tn.$i.8 {
      set bt [btree_from_db db]
      db_enter db
      array set stats [btree_pager_stats $bt]
      db_leave db
      set stats(ref)
    } {0}

  }
  # end for i

}
# end for tn

finish_test







|







 







>
>
>
>
>
>
>
>
>
>
>
>







 







|



|







 







>
>
>
|
|
|
|
|
|
|
>







11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
...
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
...
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
...
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
# This file implements regression tests for SQLite library.
#
# This file implements tests to make sure SQLite does not crash or
# segfault if it sees a corrupt database file.  It creates a base
# data base file, then tests that single byte corruptions in 
# increasingly larger quantities are handled gracefully.
#
# $Id: corruptC.test,v 1.4 2008/11/11 22:18:20 shane Exp $

catch {file delete -force test.db test.db-journal test.bu}

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Set a uniform random seed
................................................................................
  hexio_write test.db 3714 [format %02x 0x58]
  hexio_write test.db 3746 [format %02x 0x9a]

  sqlite3 db test.db
  catchsql {UPDATE t1 SET y=1}
} {0 {}}

# test that a corrupt free cell size is handled (seed 13329)
do_test corruptC-2.3 {
  db close
  copy_file test.bu test.db

  # insert corrupt byte(s)
  hexio_write test.db 1094 [format %02x 0x76]

  sqlite3 db test.db
  catchsql {UPDATE t1 SET y=1}
} {0 {database disk image is malformed}}

#
# now test for a series of quasi-random seeds
#
for {set tn 0} {$tn<=1024} {incr tn 1} {

  # Set a quasi-random random seed
  expr srand($tn)
................................................................................
      set x {}
    } {}
    do_test corruptC-3.$tn.$i.5 {
      catchsql {SELECT count(*) FROM t2 WHERE x<13}
      set x {}
    } {}
    do_test corruptC-3.$tn.$i.6 {
      catchsql {BEGIN; UPDATE t1 SET y=1; ROLLBACK;}
      set x {}
    } {}
    do_test corruptC-3.$tn.$i.7 {
      catchsql {BEGIN; UPDATE t2 SET y=2; ROLLBACK;}
      set x {}
    } {}

    # check the integrity of the database.
    # once the corruption is detected, we can stop.
    ifcapable {integrityck} {
      set res [ catchsql {PRAGMA integrity_check} ]
................................................................................
    ifcapable {!integrityck} {
      if { $i > 5 } {
        set last -1
      }
    }

    # Check that no page references were leaked.
    # TBD:  need to figure out why this doesn't work
    # work with ROLLBACKs...
    if {0} {
      do_test corruptC-3.$tn.$i.8 {
        set bt [btree_from_db db]
        db_enter db
        array set stats [btree_pager_stats $bt]
        db_leave db
        set stats(ref)
      } {0}
    }
  }
  # end for i

}
# end for tn

finish_test