Index: src/btree.c ================================================================== --- src/btree.c +++ src/btree.c @@ -7,11 +7,11 @@ ** 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.424 2007/09/06 23:39:37 drh Exp $ +** $Id: btree.c,v 1.425 2007/09/07 14:32:07 drh 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. */ @@ -4138,16 +4138,19 @@ k = get4byte(&pTrunk->aData[4]); if( k>=pBt->usableSize/4 - 8 ){ /* The trunk is full. Turn the page being freed into a new ** trunk page with no leaves. */ rc = sqlite3PagerWrite(pPage->pDbPage); - if( rc ) return rc; - put4byte(pPage->aData, pTrunk->pgno); - put4byte(&pPage->aData[4], 0); - put4byte(&pPage1->aData[32], pPage->pgno); - TRACE(("FREE-PAGE: %d new trunk page replacing %d\n", - pPage->pgno, pTrunk->pgno)); + if( rc==SQLITE_OK ){ + put4byte(pPage->aData, pTrunk->pgno); + put4byte(&pPage->aData[4], 0); + put4byte(&pPage1->aData[32], pPage->pgno); + TRACE(("FREE-PAGE: %d new trunk page replacing %d\n", + pPage->pgno, pTrunk->pgno)); + } + }else if( k<0 ){ + rc = SQLITE_CORRUPT; }else{ /* Add the newly freed page as a leaf on the current trunk */ rc = sqlite3PagerWrite(pTrunk->pDbPage); if( rc==SQLITE_OK ){ put4byte(&pTrunk->aData[4], k+1); ADDED test/corrupt4.test Index: test/corrupt4.test ================================================================== --- /dev/null +++ test/corrupt4.test @@ -0,0 +1,74 @@ +# 2007 Sept 7 +# +# The author disclaims copyright to this source code. In place of +# 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. +# +#*********************************************************************** +# 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. +# +# $Id: corrupt4.test,v 1.1 2007/09/07 14:32:07 drh Exp $ + +set testdir [file dirname $argv0] +source $testdir/tester.tcl + +# We must have the page_size pragma for these tests to work. +# +ifcapable !pager_pragmas { + finish_test + return +} + +# Create a database with a freelist containing at least two pages. +# +do_test corrupt4-1.1 { + set bigstring [string repeat 0123456789 200] + execsql { + PRAGMA auto_vacuum=OFF; + PRAGMA page_size=1024; + CREATE TABLE t1(x); + INSERT INTO t1 VALUES($bigstring); + CREATE TABLE t2(y); + INSERT INTO t2 VALUES(1); + DROP TABLE t1; + } + file size test.db +} [expr {1024*4}] + +# Verify that there are two pages on the freelist. +# +do_test corrupt4-1.2 { + execsql {PRAGMA freelist_count} +} {2} + +# Get the page number for the trunk of the freelist. +# +set trunkpgno [hexio_get_int [hexio_read test.db 32 4]] +set baseaddr [expr {($trunkpgno-1)*1024}] + +# Verify that the trunk of the freelist has exactly one +# leaf. +# +do_test corrupt4-1.3 { + hexio_get_int [hexio_read test.db [expr {$::baseaddr+4}] 4] +} {1} + +# Insert a negative number as the number of leaves on the trunk. +# Then try to add a new element to the freelist. +# +do_test corrupt4-1.4 { + hexio_write test.db [expr {$::baseaddr+4}] [hexio_render_int32 -100000000] + db close + sqlite3 db test.db + catchsql { + DROP TABLE t2 + } +} {1 {database disk image is malformed}} + +finish_test