SQLite

Check-in [43321a5560]
Login

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

Overview
Comment:Fix a case where SQLite may write past the end of a buffer as a result of a corrupted database file.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 43321a556031942389ca11b033c1eae46ac6141b
User & Date: dan 2009-08-14 17:01:22.000
Context
2009-08-14
17:53
Work around an over-zealous optimization in GCC 4.3.3. See CVSTrac ticket #4027. (check-in: 9cbe365405 user: drh tags: trunk)
17:01
Fix a case where SQLite may write past the end of a buffer as a result of a corrupted database file. (check-in: 43321a5560 user: dan tags: trunk)
16:15
Fix to the "publish.sh" script that was broken by the previous check-in. (check-in: 34c21210eb user: drh tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/btree.c.
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418

1419
1420
1421
1422
1423
1424
1425

    /* Compute the total free space on the page */
    pc = get2byte(&data[hdr+1]);
    nFree = data[hdr+7] + top;
    while( pc>0 ){
      u16 next, size;
      if( pc<iCellFirst || pc>iCellLast ){
        /* Free block is off the page */
        return SQLITE_CORRUPT_BKPT; 
      }
      next = get2byte(&data[pc]);
      size = get2byte(&data[pc+2]);
      if( next>0 && next<=pc+size+3 ){
        /* Free blocks must be in ascending order */

        return SQLITE_CORRUPT_BKPT; 
      }
      nFree = nFree + size;
      pc = next;
    }

    /* At this point, nFree contains the sum of the offset to the start







|




|
|
>







1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426

    /* Compute the total free space on the page */
    pc = get2byte(&data[hdr+1]);
    nFree = data[hdr+7] + top;
    while( pc>0 ){
      u16 next, size;
      if( pc<iCellFirst || pc>iCellLast ){
        /* Start of free block is off the page */
        return SQLITE_CORRUPT_BKPT; 
      }
      next = get2byte(&data[pc]);
      size = get2byte(&data[pc+2]);
      if( (next>0 && next<=pc+size+3) || pc+size>usableSize ){
        /* Free blocks must be in ascending order. And the last byte of
	** the free-block must lie on the database page.  */
        return SQLITE_CORRUPT_BKPT; 
      }
      nFree = nFree + size;
      pc = next;
    }

    /* At this point, nFree contains the sum of the offset to the start
Changes to test/corrupt.test.
221
222
223
224
225
226
227




























228
229

do_test corrupt-5.2 {
  db close
  hexio_write test.db 108 00000000 
  sqlite3 db test.db
  catchsql { SELECT * FROM sqlite_master }
} {1 {database disk image is malformed}}





























finish_test







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


221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257

do_test corrupt-5.2 {
  db close
  hexio_write test.db 108 00000000 
  sqlite3 db test.db
  catchsql { SELECT * FROM sqlite_master }
} {1 {database disk image is malformed}}

do_test corrupt-6.1 {
  db close
  file delete -force test.db test.db-journal
  sqlite3 db test.db
  execsql { 
    PRAGMA page_size = 1024; CREATE TABLE t1(x);
  }

  # The root page of t1 is 1024 bytes in size. The header is 8 bytes, and
  # each of the cells inserted by the following INSERT statements consume
  # 16 bytes (including the 2 byte cell-offset array entry). So the page
  # can contain up to 63 cells.
  for {set i 0} {$i < 63} {incr i} {
    execsql { INSERT INTO t1 VALUES( randomblob(10) ) }
  }

  # Free the cell stored right at the end of the page (at offset pgsz-14).
  execsql { DELETE FROM t1 WHERE rowid=1 }
  set rootpage [db one {SELECT rootpage FROM sqlite_master WHERE name = 't1'}]
  db close

  set offset [expr ($rootpage * 1024)-14+2]
  hexio_write test.db $offset 00FF
  sqlite3 db test.db 

  catchsql { INSERT INTO t1 VALUES( randomblob(10) ) }
} {}

finish_test