1# 2014-01-20 2# 3# The author disclaims copyright to this source code. In place of 4# a legal notice, here is a blessing: 5# 6# May you do good and not evil. 7# May you find forgiveness for yourself and forgive others. 8# May you share freely, never taking more than you give. 9# 10#*********************************************************************** 11# 12 13set testdir [file dirname $argv0] 14source $testdir/tester.tcl 15set testprefix corruptI 16 17if {[permutation]=="mmap"} { 18 finish_test 19 return 20} 21 22# Do not use a codec for tests in this file, as the database file is 23# manipulated directly using tcl scripts (using the [hexio_write] command). 24# 25do_not_use_codec 26database_may_be_corrupt 27 28# Initialize the database. 29# 30do_execsql_test 1.1 { 31 PRAGMA page_size=1024; 32 PRAGMA auto_vacuum=0; 33 CREATE TABLE t1(a); 34 CREATE INDEX i1 ON t1(a); 35 INSERT INTO t1 VALUES('abcdefghijklmnop'); 36} {} 37db close 38 39do_test 1.2 { 40 set offset [hexio_get_int [hexio_read test.db [expr 2*1024 + 8] 2]] 41 set off [expr 2*1024 + $offset + 1] 42 hexio_write test.db $off 7f06 43 sqlite3 db test.db 44 catchsql { SELECT * FROM t1 WHERE a = 10 } 45} {0 {}} 46 47do_test 1.3 { 48 db close 49 set offset [hexio_get_int [hexio_read test.db [expr 2*1024 + 8] 2]] 50 set off [expr 2*1024 + $offset + 1] 51 hexio_write test.db $off FFFF7f02 52 sqlite3 db test.db 53 catchsql { SELECT * FROM t1 WHERE a = 10 } 54} {1 {database disk image is malformed}} 55 56do_test 2.0 { 57 execsql { 58 CREATE TABLE r(x); 59 INSERT INTO r VALUES('ABCDEFGHIJK'); 60 CREATE INDEX r1 ON r(x); 61 } 62 set pg [db one {SELECT rootpage FROM sqlite_master WHERE name = 'r1'}] 63} {5} 64 65do_test 2.1 { 66 db close 67 set offset [hexio_get_int [hexio_read test.db [expr (5-1)*1024 + 8] 2]] 68 set off [expr (5-1)*1024 + $offset + 1] 69 hexio_write test.db $off FFFF0004 70 sqlite3 db test.db 71 catchsql { SELECT * FROM r WHERE x >= 10.0 } 72} {1 {database disk image is malformed}} 73 74do_test 2.2 { 75 catchsql { SELECT * FROM r WHERE x >= 10 } 76} {1 {database disk image is malformed}} 77 78if {[db one {SELECT sqlite_compileoption_used('ENABLE_OVERSIZE_CELL_CHECK')}]} { 79 # The following tests only work if OVERSIZE_CELL_CHECK is disabled 80} else { 81 reset_db 82 do_execsql_test 3.1 { 83 PRAGMA auto_vacuum=0; 84 PRAGMA page_size = 512; 85 CREATE TABLE t1(a INTEGER PRIMARY KEY, b); 86 WITH s(a, b) AS ( 87 SELECT 2, 'abcdefghij' 88 UNION ALL 89 SELECT a+2, b FROM s WHERe a < 40 90 ) 91 INSERT INTO t1 SELECT * FROM s; 92 } {} 93 94 do_test 3.2 { 95 hexio_write test.db [expr 512+3] 0054 96 db close 97 sqlite3 db test.db 98 execsql { INSERT INTO t1 VALUES(5, 'klmnopqrst') } 99 execsql { INSERT INTO t1 VALUES(7, 'klmnopqrst') } 100 } {} 101 102 db close 103 sqlite3 db test.db 104 do_catchsql_test 3.3 { 105 INSERT INTO t1 VALUES(9, 'klmnopqrst'); 106 } {1 {database disk image is malformed}} 107} ;# end-if !defined(ENABLE_OVERSIZE_CELL_CHECK) 108 109 110#------------------------------------------------------------------------- 111# Test that an assert() failure discovered by AFL corrupt database file 112# testing has been fixed. 113# 114reset_db 115do_execsql_test 4.0 { 116 PRAGMA page_size = 65536; 117 PRAGMA autovacuum = 0; 118 CREATE TABLE t1(a INTEGER PRIMARY KEY, b); 119 INSERT INTO t1 VALUES(-1, 'abcdefghij'); 120 INSERT INTO t1 VALUES(0, 'abcdefghij'); 121} 122 123set root [db one {SELECT rootpage FROM sqlite_master}] 124set offset [expr ($root-1) * 65536] 125 126do_test 4.1 { 127 db close 128 hexio_write test.db [expr $offset + 8 + 2] 0000 129 hexio_write test.db [expr $offset + 5] 0000 130 sqlite3 db test.db 131 execsql { DELETE FROM t1 WHERE a=0 } 132} {} 133 134 135#------------------------------------------------------------------------- 136# Database properties: 137# 138# * Incremental vacuum mode. 139# * Database root table has a single leaf page. 140# * Free list consists of a single trunk page. 141# 142# The db is then corrupted by adding the root table leaf page as a free-list 143# leaf page (so that it is referenced twice). 144# 145# Then, a new table is created. The new root page is the current free-list 146# trunk. This means that the root table leaf page is made into the new 147# free list trunk, which corrupts its header. Then, when the new entry is 148# inserted into the root table, things would get chaotic. 149# 150reset_db 151do_test 5.0 { 152 execsql { 153 PRAGMA page_size = 512; 154 PRAGMA auto_vacuum = 2; 155 } 156 for {set i 3} {1} {incr i} { 157 execsql "CREATE TABLE t${i}(x)" 158 if {[db one {PRAGMA page_count}]>$i} break 159 } 160 set nPage [db one {PRAGMA page_count}] 161 execsql { 162 CREATE TABLE t100(x); 163 DROP TABLE t100; 164 } 165} {} 166 167do_execsql_test 5.1 { 168 PRAGMA page_count 169} [expr $nPage+1] 170 171do_test 5.2 { 172 # The last page of the db is now the only leaf of the sqlite_master table. 173 # Corrupt the db by adding it to the free-list as well (the second last 174 # page of the db is the free-list trunk). 175 db close 176 hexio_write test.db [expr 512*($nPage-1)] [ 177 format "%.8X%.8X%.8X" 0 1 [expr $nPage+1] 178 ] 179} {12} 180 181do_test 5.3 { 182 sqlite3 db test.db 183 catchsql { CREATE TABLE tx(x); } 184} {1 {database disk image is malformed}} 185 186 187finish_test 188