/ Check-in [0ce42e76]
Login

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

Overview
Comment:Store the MemPage structure in memory following, instead of preceding, the page data for cached pages. This reduces the likelihood of a corrupt database page image causing SQLite to read past the end of a buffer.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 0ce42e76654d9ba52dac74c940d38b17866016ba
User & Date: dan 2010-06-10 06:53:27
Context
2010-06-10
10:51
Update the test VFS in test_journal.c so that it implements the xCurrentTimeInt64 method. check-in: ec3b4a7e user: drh tags: trunk
06:53
Store the MemPage structure in memory following, instead of preceding, the page data for cached pages. This reduces the likelihood of a corrupt database page image causing SQLite to read past the end of a buffer. check-in: 0ce42e76 user: dan tags: trunk
01:07
Remove a condition that must always be true. Replace it with an assert(). check-in: 7abcd54e user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/pcache.c.

256
257
258
259
260
261
262
263
264
265

266
267
268
269
270

271
272
273
274
275
276
277
278
    }

    pPage = sqlite3GlobalConfig.pcache.xFetch(pCache->pCache, pgno, 2);
  }

  if( pPage ){
    if( !pPage->pData ){
      memset(pPage, 0, sizeof(PgHdr) + pCache->szExtra);
      pPage->pExtra = (void*)&pPage[1];
      pPage->pData = (void *)&((char *)pPage)[sizeof(PgHdr) + pCache->szExtra];

      pPage->pCache = pCache;
      pPage->pgno = pgno;
    }
    assert( pPage->pCache==pCache );
    assert( pPage->pgno==pgno );

    assert( pPage->pExtra==(void *)&pPage[1] );

    if( 0==pPage->nRef ){
      pCache->nRef++;
    }
    pPage->nRef++;
    if( pgno==1 ){
      pCache->pPage1 = pPage;







|
|
|
>





>
|







256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
    }

    pPage = sqlite3GlobalConfig.pcache.xFetch(pCache->pCache, pgno, 2);
  }

  if( pPage ){
    if( !pPage->pData ){
      memset(pPage, 0, sizeof(PgHdr));
      pPage->pData = (void *)&pPage[1];
      pPage->pExtra = (void*)&((char *)pPage->pData)[pCache->szPage];
      memset(pPage->pExtra, 0, pCache->szExtra);
      pPage->pCache = pCache;
      pPage->pgno = pgno;
    }
    assert( pPage->pCache==pCache );
    assert( pPage->pgno==pgno );
    assert( pPage->pData==(void *)&pPage[1] );
    assert( pPage->pExtra==(void *)&((char *)&pPage[1])[pCache->szPage] );

    if( 0==pPage->nRef ){
      pCache->nRef++;
    }
    pPage->nRef++;
    if( pgno==1 ){
      pCache->pPage1 = pPage;

Changes to test/corruptC.test.

271
272
273
274
275
276
277











278
279
280
281
282
283
284
  execsql { INSERT INTO t1 VALUES (1, $blob) }

  sqlite3 db test.db
  set filesize [file size test.db]
  hexio_write test.db [expr $filesize-2048] 00000001
  catchsql {DELETE FROM t1 WHERE rowid = (SELECT max(rowid) FROM t1)}
} {1 {database disk image is malformed}}












#
# Now test for a series of quasi-random seeds.
# We loop over the entire file size and touch
# each byte at least once.
for {set tn 0} {$tn<$fsize} {incr tn 1} {








>
>
>
>
>
>
>
>
>
>
>







271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
  execsql { INSERT INTO t1 VALUES (1, $blob) }

  sqlite3 db test.db
  set filesize [file size test.db]
  hexio_write test.db [expr $filesize-2048] 00000001
  catchsql {DELETE FROM t1 WHERE rowid = (SELECT max(rowid) FROM t1)}
} {1 {database disk image is malformed}}

# At one point this particular corrupt database was causing a buffer
# overread. Which caused a crash in a run of all.test once.
#
do_test corruptC-2.15 {
  db close
  copy_file test.bu test.db
  hexio_write test.db 986 b9
  sqlite3 db test.db
  catchsql {SELECT count(*) FROM sqlite_master;}
} {1 {malformed database schema (t1i1) - no such table: main.t1}}

#
# Now test for a series of quasi-random seeds.
# We loop over the entire file size and touch
# each byte at least once.
for {set tn 0} {$tn<$fsize} {incr tn 1} {