From 4361e79f14cb3e3276574a52bb15adbc27d70196 Mon Sep 17 00:00:00 2001 From: dan Date: Fri, 14 Aug 2009 17:01:22 +0000 Subject: [PATCH] Fix a case where SQLite may write past the end of a buffer as a result of a corrupted database file. FossilOrigin-Name: 43321a556031942389ca11b033c1eae46ac6141b --- manifest | 26 ++++++++------------------ manifest.uuid | 2 +- src/btree.c | 7 ++++--- test/corrupt.test | 28 ++++++++++++++++++++++++++++ 4 files changed, 41 insertions(+), 22 deletions(-) diff --git a/manifest b/manifest index c0489f6f6d..3972e5821c 100644 --- a/manifest +++ b/manifest @@ -1,8 +1,5 @@ ------BEGIN PGP SIGNED MESSAGE----- -Hash: SHA1 - -C Fix\sto\sthe\s"publish.sh"\sscript\sthat\swas\sbroken\sby\sthe\sprevious\scheck-in. -D 2009-08-14T16:15:17 +C Fix\sa\scase\swhere\sSQLite\smay\swrite\spast\sthe\send\sof\sa\sbuffer\sas\sa\sresult\sof\sa\scorrupted\sdatabase\sfile. +D 2009-08-14T17:01:22 F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0 F Makefile.in 0f7761c5d1c62ae7a841e3393ffaff1fa0f5c00a F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654 @@ -109,7 +106,7 @@ F src/auth.c 802a9439dfa0b8c208b10055cba400e82ef18025 F src/backup.c 6f1c2d9862c8a3feb7739dfcca02c1f5352e37f3 F src/bitvec.c e08f6c1a9551b88081fc737916c6c3fd5029a6cf F src/btmutex.c 0f43a75bb5b8147b386e8e1c3e71ba734e3863b7 -F src/btree.c 97d32ef9e00bd9d321fe1c53a3b6651928d8ea06 +F src/btree.c 49212ddaee8d7d12b4f1e17b9de62f7ea91ca59d F src/btree.h 577448a890c2ab9b21e6ab74f073526184bceebe F src/btreeInt.h 1c86297e69380f6577e7ae67452597dd8d5c2705 F src/build.c a15de7c5d020a778b641fca0b2510126843f4b30 @@ -284,7 +281,7 @@ F test/collateA.test b8218ab90d1fa5c59dcf156efabb1b2599c580d6 F test/colmeta.test 087c42997754b8c648819832241daf724f813322 F test/colname.test 08948a4809d22817e0e5de89c7c0a8bd90cb551b F test/conflict.test 0ed68b11f22721052d880ee80bd528a0e0828236 -F test/corrupt.test 04e717ebb644f1b30b142cb5f30797747ef5f02f +F test/corrupt.test f89c25681f60e06631e5cb203d06622f2f84e1e9 F test/corrupt2.test a571e30ea4e82318f319a24b6cc55935ce862079 F test/corrupt3.test 263e8bb04e2728df832fddf6973cf54c91db0c32 F test/corrupt4.test acdb01afaedf529004b70e55de1a6f5a05ae7fff @@ -746,14 +743,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/vdbe-compress.tcl 672f81d693a03f80f5ae60bfefacd8a349e76746 -P 302dabe98f50b472bccd65c58504bc8a330049c4 -R 688485e18fb292248000129c5e459fb9 -U drh -Z 522909aad95eede72dbcce585a963740 ------BEGIN PGP SIGNATURE----- -Version: GnuPG v1.4.6 (GNU/Linux) - -iD8DBQFKhY2YoxKgR168RlERAq9JAJ4uarnaf+/3F5G6GKq4PSOL6msAYACdEo74 -T/jOErN31rwT4iOZlFOpYFw= -=nn3U ------END PGP SIGNATURE----- +P 34c21210eb03bd1230cde5d08039a8a656f35674 +R f46a5a69fe608d04233707dc2ffff1a9 +U dan +Z baaa9683a6aa9b1a09c65002a4959fa5 diff --git a/manifest.uuid b/manifest.uuid index daa641d81c..39a636dba2 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -34c21210eb03bd1230cde5d08039a8a656f35674 \ No newline at end of file +43321a556031942389ca11b033c1eae46ac6141b \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index 75ec937c35..e927ba8a54 100644 --- a/src/btree.c +++ b/src/btree.c @@ -1409,13 +1409,14 @@ static int btreeInitPage(MemPage *pPage){ while( pc>0 ){ u16 next, size; if( pciCellLast ){ - /* Free block is off the page */ + /* 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 ){ - /* Free blocks must be in ascending order */ + 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; diff --git a/test/corrupt.test b/test/corrupt.test index 8911393975..ad7fa3bdab 100644 --- a/test/corrupt.test +++ b/test/corrupt.test @@ -226,4 +226,32 @@ do_test corrupt-5.2 { 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