From 2d16fb1d34a22e1d32a28a05c9fdb6760b80a9b4 Mon Sep 17 00:00:00 2001 From: shane Date: Fri, 31 Oct 2008 13:57:40 +0000 Subject: [PATCH] Test that single byte corruptions in increasingly larger quantities are handled gracefully. (CVS 5854) FossilOrigin-Name: c73d915923e393f72e1c0897526a20527db2e03c --- manifest | 13 ++-- manifest.uuid | 2 +- test/corruptC.test | 147 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 155 insertions(+), 7 deletions(-) create mode 100644 test/corruptC.test diff --git a/manifest b/manifest index 1a85c3c033..99ab695234 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Change\sthe\sway\ssqlite3VdbeSetColName()\sis\scalled\sso\sas\sto\sremove\sa\sfew\slines\sof\scode.\sThis\salso\sfixes\s#3470.\s(CVS\s5853) -D 2008-10-31T10:53:23 +C Test\sthat\ssingle\sbyte\scorruptions\sin\sincreasingly\slarger\squantities\sare\shandled\sgracefully.\s(CVS\s5854) +D 2008-10-31T13:57:40 F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0 F Makefile.in da817da72422f9b876602c225fcd17d6ca4182f7 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654 @@ -265,6 +265,7 @@ F test/corrupt8.test 9992ef7f67cefc576b92373f6bf5ab8775280f51 F test/corrupt9.test 794d284109c65c8f10a2b275479045e02d163bae F test/corruptA.test 99e95620b980161cb3e79f06a884a4bb8ae265ff F test/corruptB.test 505331779fe7a96fe38ecbb817f19c63bc27d171 +F test/corruptC.test c918825035449c5b1371182a584d75619d43b9ac F test/crash.test 1b6ac8410689ff78028887f445062dc897c9ac89 F test/crash2.test 5b14d4eb58b880e231361d3b609b216acda86651 F test/crash3.test 776f9363554c029fcce71d9e6600fa0ba6359ce7 @@ -652,7 +653,7 @@ F tool/speedtest16.c c8a9c793df96db7e4933f0852abb7a03d48f2e81 F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e -P cd1662e964d9c071a41038676c5a6ef2c990f1ac -R b172d3b1ff630a63b0aeae4b91cf2a82 -U danielk1977 -Z 95f190d0347133a0479177ca7cc777a4 +P bfce91429b1dad6e0ca36929e41a7adfb30f8522 +R 7e7399b4dd0e7285795a33efa071b32a +U shane +Z 036cf1ab4484f24cac77efa2333c4427 diff --git a/manifest.uuid b/manifest.uuid index fdb88df788..9e58313020 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -bfce91429b1dad6e0ca36929e41a7adfb30f8522 \ No newline at end of file +c73d915923e393f72e1c0897526a20527db2e03c \ No newline at end of file diff --git a/test/corruptC.test b/test/corruptC.test new file mode 100644 index 0000000000..f92d729255 --- /dev/null +++ b/test/corruptC.test @@ -0,0 +1,147 @@ +# 2004 August 30 +# +# 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. It creates a base +# data base file, then tests that single byte corruptions in +# increasingly larger quantities are handled gracefully. +# +# $Id: corruptC.test,v 1.1 2008/10/31 13:57:40 shane Exp $ + +catch {file delete -force test.db test.db-journal test.bu} + +set testdir [file dirname $argv0] +source $testdir/tester.tcl + +# Construct a compact, dense database for testing. +# +do_test corruptC-1.1 { + execsql { + BEGIN; + CREATE TABLE t1(x); + INSERT INTO t1 VALUES(1); + INSERT OR IGNORE INTO t1 SELECT x*2 FROM t1; + INSERT OR IGNORE INTO t1 SELECT x*3 FROM t1; + INSERT OR IGNORE INTO t1 SELECT x*5 FROM t1; + INSERT OR IGNORE INTO t1 SELECT x*7 FROM t1; + INSERT OR IGNORE INTO t1 SELECT x*11 FROM t1; + INSERT OR IGNORE INTO t1 SELECT x*13 FROM t1; + CREATE INDEX t1i1 ON t1(x); + CREATE TABLE t2 AS SELECT * FROM t1 WHERE rowid%5!=0; + COMMIT; + } +} {} + +ifcapable {integrityck} { + integrity_check corruptC-1.2 +} + +# Generate random integer +# +proc random {range} { + return [expr {round(rand()*$range)}] +} + +# Copy file $from into $to +# +proc copy_file {from to} { + set f [open $from] + fconfigure $f -translation binary + set t [open $to w] + fconfigure $t -translation binary + puts -nonewline $t [read $f [file size $from]] + close $t + close $f +} + +# Setup for the tests. Make a backup copy of the good database in test.bu. +# +copy_file test.db test.bu +set fsize [file size test.db] + +for {set tn 1} {$tn<=1024} {incr tn 1} { + + # setup for test + db close + copy_file test.bu test.db + + # 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 + # the database engine can handle the corruption gracefully. + # + set last 0 + for {set i 1} {$i<=1024 && !$last} {incr i 1} { + + # insert random byte at random location + set fd [open test.db r+] + fconfigure $fd -translation binary + seek $fd [random $fsize] + puts -nonewline $fd [format "%c" [expr [random 255]]] + close $fd + + # do a few random operations to make sure that if + # they error, they error gracefully instead of crashing. + do_test corruptC-2.$tn.$i.1 { + sqlite3 db test.db + catchsql {SELECT count(*) FROM sqlite_master} + set x {} + } {} + do_test corruptC-2.$tn.$i.2 { + catchsql {SELECT count(*) FROM t1} + set x {} + } {} + do_test corruptC-2.$tn.$i.3 { + catchsql {SELECT count(*) FROM t1 WHERE x>13} + set x {} + } {} + do_test corruptC-2.$tn.$i.4 { + catchsql {SELECT count(*) FROM t2} + set x {} + } {} + do_test corruptC-2.$tn.$i.5 { + catchsql {SELECT count(*) FROM t2 WHERE x<13} + set x {} + } {} + + # check the integrity of the database. + # once the corruption is detected, we can stop. + ifcapable {integrityck} { + set res [ catchsql {PRAGMA integrity_check} ] + set ans [lindex $res 1] + if { [ string compare $ans "ok" ] != 0 } { + set last -1 + } + } + # if we are not capable of doing an integrity check, + # stop after corrupting 5 bytes. + ifcapable {!integrityck} { + if { $i > 5 } { + set last -1 + } + } + + # Check that no page references were leaked. + do_test corruptC-2.$tn.$i.6 { + set bt [btree_from_db db] + db_enter db + array set stats [btree_pager_stats $bt] + db_leave db + set stats(ref) + } {0} + + } + # end for i + +} +# end for tn + +finish_test