github.com/jdgcs/sqlite3@v1.12.1-0.20210908114423-bc5f96e4dd51/testdata/tcl/corruptI.test (about) 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 13 set testdir [file dirname $argv0] 14 source $testdir/tester.tcl 15 set testprefix corruptI 16 17 if {[permutation]=="mmap"} { 18 finish_test 19 return 20 } 21 22 # This module uses hard-coded offsets which do not work if the reserved_bytes 23 # value is nonzero. 24 if {[nonzero_reserved_bytes]} {finish_test; return;} 25 26 database_may_be_corrupt 27 28 # Initialize the database. 29 # 30 do_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 } {} 37 db close 38 39 do_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 47 do_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 56 do_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 65 do_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 74 do_test 2.2 { 75 catchsql { SELECT * FROM r WHERE x >= 10 } 76 } {1 {database disk image is malformed}} 77 78 if {[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 # 114 reset_db 115 do_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 123 set root [db one {SELECT rootpage FROM sqlite_master}] 124 set offset [expr ($root-1) * 65536] 125 126 ifcapable oversize_cell_check { 127 set res {1 {database disk image is malformed}} 128 } else { 129 set res {0 {}} 130 } 131 do_test 4.1 { 132 db close 133 hexio_write test.db [expr $offset + 8 + 2] 0000 134 hexio_write test.db [expr $offset + 5] 0000 135 sqlite3 db test.db 136 catchsql { DELETE FROM t1 WHERE a=0 } 137 } $res 138 139 140 #------------------------------------------------------------------------- 141 # Database properties: 142 # 143 # * Incremental vacuum mode. 144 # * Database root table has a single leaf page. 145 # * Free list consists of a single trunk page. 146 # 147 # The db is then corrupted by adding the root table leaf page as a free-list 148 # leaf page (so that it is referenced twice). 149 # 150 # Then, a new table is created. The new root page is the current free-list 151 # trunk. This means that the root table leaf page is made into the new 152 # free list trunk, which corrupts its header. Then, when the new entry is 153 # inserted into the root table, things would get chaotic. 154 # 155 reset_db 156 do_test 5.0 { 157 execsql { 158 PRAGMA page_size = 512; 159 PRAGMA auto_vacuum = 2; 160 } 161 for {set i 3} {1} {incr i} { 162 execsql "CREATE TABLE t${i}(x)" 163 if {[db one {PRAGMA page_count}]>$i} break 164 } 165 set nPage [db one {PRAGMA page_count}] 166 execsql { 167 CREATE TABLE t100(x); 168 DROP TABLE t100; 169 } 170 } {} 171 172 do_execsql_test 5.1 { 173 PRAGMA page_count 174 } [expr $nPage+1] 175 176 do_test 5.2 { 177 # The last page of the db is now the only leaf of the sqlite_master table. 178 # Corrupt the db by adding it to the free-list as well (the second last 179 # page of the db is the free-list trunk). 180 db close 181 hexio_write test.db [expr 512*($nPage-1)] [ 182 format "%.8X%.8X%.8X" 0 1 [expr $nPage+1] 183 ] 184 } {12} 185 186 do_test 5.3 { 187 sqlite3 db test.db 188 catchsql { CREATE TABLE tx(x); } 189 } {1 {database disk image is malformed}} 190 191 192 #------------------------------------------------------------------------- 193 # Set the payload size of a cell to just less than 2^32 bytes (not 194 # possible in an uncorrupted db). Then try to delete the cell. At one 195 # point this led to an integer overflow that caused an assert() to fail. 196 # 197 reset_db 198 do_execsql_test 6.0 { 199 PRAGMA page_size = 512; 200 PRAGMA auto_vacuum=0; 201 CREATE TABLE t1(x); 202 INSERT INTO t1 VALUES(zeroblob(300)); 203 INSERT INTO t1 VALUES(zeroblob(600)); 204 } {} 205 do_test 6.1 { 206 db close 207 hexio_write test.db 616 8FFFFFFF7F02 208 sqlite3 db test.db 209 execsql { DELETE FROM t1 WHERE rowid=2 } 210 } {} 211 212 #------------------------------------------------------------------------- 213 # See what happens if the sqlite_master entry associated with a PRIMARY 214 # KEY or UNIQUE index is removed. 215 # 216 reset_db 217 do_execsql_test 7.0 { 218 PRAGMA auto_vacuum=0; 219 CREATE TABLE t1(x PRIMARY KEY, y); 220 INSERT INTO t1 VALUES('a', 'A'); 221 INSERT INTO t1 VALUES('b', 'A'); 222 INSERT INTO t1 VALUES('c', 'A'); 223 SELECT name FROM sqlite_master; 224 } {t1 sqlite_autoindex_t1_1} 225 sqlite3_db_config db DEFENSIVE 0 226 do_execsql_test 7.1 { 227 PRAGMA writable_schema = 1; 228 DELETE FROM sqlite_master WHERE name = 'sqlite_autoindex_t1_1'; 229 } 230 do_test 7.2 { 231 db close 232 sqlite3 db test.db 233 catchsql { UPDATE t1 SET x='d' AND y='D' WHERE rowid = 2 } 234 } {1 {database disk image is malformed}} 235 236 #------------------------------------------------------------------------- 237 # At one point an assert() would fail if attempt was made to free page 1. 238 # 239 reset_db 240 do_execsql_test 8.0 { 241 PRAGMA auto_vacuum=0; 242 CREATE TABLE t1(x); 243 INSERT INTO t1 VALUES(zeroblob(300)); 244 INSERT INTO t1 VALUES(zeroblob(300)); 245 INSERT INTO t1 VALUES(zeroblob(300)); 246 INSERT INTO t1 VALUES(zeroblob(300)); 247 } {} 248 249 do_test 8.1 { 250 db close 251 hexio_write test.db [expr 1024 + 8] 00000001 252 sqlite3 db test.db 253 catchsql { DELETE FROM t1 } 254 } {1 {database disk image is malformed}} 255 256 do_test 8.2 { 257 db close 258 sqlite3 db test.db 259 execsql { PRAGMA integrity_check } 260 } {/.*in database main.*/} 261 262 263 finish_test