1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-08-07 02:42:48 +03:00

Prevent a crash during an UPDATE when the cell offset is corrupt. (CVS 5886)

FossilOrigin-Name: 99d4172ed6825c7efb6cbb28eb00d98323a13954
This commit is contained in:
shane
2008-11-11 20:51:50 +00:00
parent dfef499856
commit 826d5b7e1c
4 changed files with 57 additions and 25 deletions

View File

@@ -1,5 +1,5 @@
C Send\sthe\s"Incomplete\sSQL"\serror\smessage\sof\sthe\sCLI\sto\sstderr\sinstead\sof\nstdout.\s\sTicket\s#3476.\s(CVS\s5885) C Prevent\sa\scrash\sduring\san\sUPDATE\swhen\sthe\scell\soffset\sis\scorrupt.\s(CVS\s5886)
D 2008-11-11T18:55:04 D 2008-11-11T20:51:51
F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0 F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
F Makefile.in 48172b58e444a9725ec482e0c022a564749acab4 F Makefile.in 48172b58e444a9725ec482e0c022a564749acab4
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
@@ -99,7 +99,7 @@ F src/attach.c 208881c87160d9e2c73a46cf86116c5a6d66f9d7
F src/auth.c c8b2ab5c8bad4bd90ed7c294694f48269162c627 F src/auth.c c8b2ab5c8bad4bd90ed7c294694f48269162c627
F src/bitvec.c 9e922b2577b7e46d8f95349bca6a52f7674d7582 F src/bitvec.c 9e922b2577b7e46d8f95349bca6a52f7674d7582
F src/btmutex.c 3a90096c3080b9057dc570b8e16e46511e1c788a F src/btmutex.c 3a90096c3080b9057dc570b8e16e46511e1c788a
F src/btree.c 7824bc89b38bafb8a87b7091e912ea789b60e428 F src/btree.c 16dda042b6da72b2f93dd2694bd388d3ceb849ca
F src/btree.h 179c3ea813780df78a289a8f5130db18e6d4616e F src/btree.h 179c3ea813780df78a289a8f5130db18e6d4616e
F src/btreeInt.h e38e9b2b285f40f5bc0a6664f630d4a141622f16 F src/btreeInt.h e38e9b2b285f40f5bc0a6664f630d4a141622f16
F src/build.c 98a6884d47c3cc12faeb2e9a926018d3a7382133 F src/build.c 98a6884d47c3cc12faeb2e9a926018d3a7382133
@@ -265,7 +265,7 @@ F test/corrupt8.test 9992ef7f67cefc576b92373f6bf5ab8775280f51
F test/corrupt9.test 794d284109c65c8f10a2b275479045e02d163bae F test/corrupt9.test 794d284109c65c8f10a2b275479045e02d163bae
F test/corruptA.test 99e95620b980161cb3e79f06a884a4bb8ae265ff F test/corruptA.test 99e95620b980161cb3e79f06a884a4bb8ae265ff
F test/corruptB.test 505331779fe7a96fe38ecbb817f19c63bc27d171 F test/corruptB.test 505331779fe7a96fe38ecbb817f19c63bc27d171
F test/corruptC.test 02a12dee8b1b58b41d30eb68e6dc95f7e9e59243 F test/corruptC.test 8b4d848df99263ebe1e8e6096606cbd02cccde19
F test/crash.test 1b6ac8410689ff78028887f445062dc897c9ac89 F test/crash.test 1b6ac8410689ff78028887f445062dc897c9ac89
F test/crash2.test 5b14d4eb58b880e231361d3b609b216acda86651 F test/crash2.test 5b14d4eb58b880e231361d3b609b216acda86651
F test/crash3.test 776f9363554c029fcce71d9e6600fa0ba6359ce7 F test/crash3.test 776f9363554c029fcce71d9e6600fa0ba6359ce7
@@ -655,7 +655,7 @@ F tool/speedtest16.c c8a9c793df96db7e4933f0852abb7a03d48f2e81
F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
P 9d880a6fd244fb73d0fce7e8180177c54d95cde2 P dacae200477afffec826b3ca1517f33b110b6122
R 63bbb49c4cc7793be5e7d22293e8e21a R c6b4375503ef710b993689e9c5ab48c6
U drh U shane
Z eeca2ee067319fbf1321ccc6e9285efb Z 8f9f799d20d3f92be2619657c8038797

View File

@@ -1 +1 @@
dacae200477afffec826b3ca1517f33b110b6122 99d4172ed6825c7efb6cbb28eb00d98323a13954

View File

@@ -9,7 +9,7 @@
** May you share freely, never taking more than you give. ** May you share freely, never taking more than you give.
** **
************************************************************************* *************************************************************************
** $Id: btree.c,v 1.529 2008/11/11 17:36:30 shane Exp $ ** $Id: btree.c,v 1.530 2008/11/11 20:51:51 shane Exp $
** **
** This file implements a external (disk-based) database using BTrees. ** This file implements a external (disk-based) database using BTrees.
** See the header comment on "btreeInt.h" for additional information. ** See the header comment on "btreeInt.h" for additional information.
@@ -4570,7 +4570,8 @@ static void dropCell(MemPage *pPage, int idx, int sz){
assert( sqlite3_mutex_held(pPage->pBt->mutex) ); assert( sqlite3_mutex_held(pPage->pBt->mutex) );
data = pPage->aData; data = pPage->aData;
ptr = &data[pPage->cellOffset + 2*idx]; ptr = &data[pPage->cellOffset + 2*idx];
pc = get2byte(ptr); /* mask the cell offset to ensure a corrupt db does not result in a crash */
pc = pPage->maskPage & get2byte(ptr);
assert( pc>10 && pc+sz<=pPage->pBt->usableSize ); assert( pc>10 && pc+sz<=pPage->pBt->usableSize );
freeSpace(pPage, pc, sz); freeSpace(pPage, pc, sz);
for(i=idx+1; i<pPage->nCell; i++, ptr+=2){ for(i=idx+1; i<pPage->nCell; i++, ptr+=2){

View File

@@ -15,7 +15,7 @@
# data base file, then tests that single byte corruptions in # data base file, then tests that single byte corruptions in
# increasingly larger quantities are handled gracefully. # increasingly larger quantities are handled gracefully.
# #
# $Id: corruptC.test,v 1.2 2008/11/11 17:36:30 shane Exp $ # $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} catch {file delete -force test.db test.db-journal test.bu}
@@ -30,16 +30,16 @@ expr srand(0)
do_test corruptC-1.1 { do_test corruptC-1.1 {
execsql { execsql {
BEGIN; BEGIN;
CREATE TABLE t1(x); CREATE TABLE t1(x,y);
INSERT INTO t1 VALUES(1); INSERT INTO t1 VALUES(1,1);
INSERT OR IGNORE INTO t1 SELECT x*2 FROM t1; INSERT OR IGNORE INTO t1 SELECT x*2,y FROM t1;
INSERT OR IGNORE INTO t1 SELECT x*3 FROM t1; INSERT OR IGNORE INTO t1 SELECT x*3,y FROM t1;
INSERT OR IGNORE INTO t1 SELECT x*5 FROM t1; INSERT OR IGNORE INTO t1 SELECT x*5,y FROM t1;
INSERT OR IGNORE INTO t1 SELECT x*7 FROM t1; INSERT OR IGNORE INTO t1 SELECT x*7,y FROM t1;
INSERT OR IGNORE INTO t1 SELECT x*11 FROM t1; INSERT OR IGNORE INTO t1 SELECT x*11,y FROM t1;
INSERT OR IGNORE INTO t1 SELECT x*13 FROM t1; INSERT OR IGNORE INTO t1 SELECT x*13,y FROM t1;
CREATE INDEX t1i1 ON t1(x); CREATE INDEX t1i1 ON t1(x);
CREATE TABLE t2 AS SELECT * FROM t1 WHERE rowid%5!=0; CREATE TABLE t2 AS SELECT x,2 FROM t1 WHERE rowid%5!=0;
COMMIT; COMMIT;
} }
} {} } {}
@@ -68,7 +68,9 @@ proc copy_file {from to} {
# Setup for the tests. Make a backup copy of the good database in test.bu. # Setup for the tests. Make a backup copy of the good database in test.bu.
# #
db close
copy_file test.db test.bu copy_file test.db test.bu
sqlite3 db test.db
set fsize [file size test.db] set fsize [file size test.db]
# #
@@ -81,7 +83,7 @@ do_test corruptC-2.1 {
copy_file test.bu test.db copy_file test.bu test.db
# insert corrupt byte(s) # insert corrupt byte(s)
hexio_write test.db 2053 04 hexio_write test.db 2053 [format %02x 0x04]
sqlite3 db test.db sqlite3 db test.db
catchsql {PRAGMA integrity_check} catchsql {PRAGMA integrity_check}
@@ -89,6 +91,26 @@ do_test corruptC-2.1 {
Corruption detected in header on page 3 Corruption detected in header on page 3
Multiple uses for byte 604 of page 3}}} Multiple uses for byte 604 of page 3}}}
# test that a corrupt content offset size is handled (seed 5649)
do_test corruptC-2.2 {
db close
copy_file test.bu test.db
# insert corrupt byte(s)
hexio_write test.db 27 [format %02x 0x08]
hexio_write test.db 233 [format %02x 0x6a]
hexio_write test.db 328 [format %02x 0x67]
hexio_write test.db 750 [format %02x 0x1f]
hexio_write test.db 1132 [format %02x 0x52]
hexio_write test.db 1133 [format %02x 0x84]
hexio_write test.db 1220 [format %02x 0x01]
hexio_write test.db 3688 [format %02x 0xc1]
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 # now test for a series of quasi-random seeds
@@ -101,6 +123,7 @@ for {set tn 0} {$tn<=1024} {incr tn 1} {
# setup for test # setup for test
db close db close
copy_file test.bu test.db copy_file test.bu test.db
sqlite3 db test.db
# Seek to a random location in the file, and write a random single byte # Seek to a random location in the file, and write a random single byte
# value. Then do various operations on the file to make sure that # value. Then do various operations on the file to make sure that
@@ -110,12 +133,13 @@ for {set tn 0} {$tn<=1024} {incr tn 1} {
for {set i 1} {$i<=1024 && !$last} {incr i 1} { for {set i 1} {$i<=1024 && !$last} {incr i 1} {
# insert random byte at random location # insert random byte at random location
db close
hexio_write test.db [random $fsize] [format %02x [random 255]] hexio_write test.db [random $fsize] [format %02x [random 255]]
sqlite3 db test.db
# do a few random operations to make sure that if # do a few random operations to make sure that if
# they error, they error gracefully instead of crashing. # they error, they error gracefully instead of crashing.
do_test corruptC-3.$tn.$i.1 { do_test corruptC-3.$tn.$i.1 {
sqlite3 db test.db
catchsql {SELECT count(*) FROM sqlite_master} catchsql {SELECT count(*) FROM sqlite_master}
set x {} set x {}
} {} } {}
@@ -135,6 +159,14 @@ for {set tn 0} {$tn<=1024} {incr tn 1} {
catchsql {SELECT count(*) FROM t2 WHERE x<13} catchsql {SELECT count(*) FROM t2 WHERE x<13}
set x {} 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. # check the integrity of the database.
# once the corruption is detected, we can stop. # once the corruption is detected, we can stop.
@@ -154,14 +186,13 @@ for {set tn 0} {$tn<=1024} {incr tn 1} {
} }
# Check that no page references were leaked. # Check that no page references were leaked.
do_test corruptC-3.$tn.$i.6 { do_test corruptC-3.$tn.$i.8 {
set bt [btree_from_db db] set bt [btree_from_db db]
db_enter db db_enter db
array set stats [btree_pager_stats $bt] array set stats [btree_pager_stats $bt]
db_leave db db_leave db
set stats(ref) set stats(ref)
} {0} } {0}
} }
# end for i # end for i