19b8afef2Sdan# 2014-01-20 29b8afef2Sdan# 39b8afef2Sdan# The author disclaims copyright to this source code. In place of 49b8afef2Sdan# a legal notice, here is a blessing: 59b8afef2Sdan# 69b8afef2Sdan# May you do good and not evil. 79b8afef2Sdan# May you find forgiveness for yourself and forgive others. 89b8afef2Sdan# May you share freely, never taking more than you give. 99b8afef2Sdan# 109b8afef2Sdan#*********************************************************************** 119b8afef2Sdan# 129b8afef2Sdan 139b8afef2Sdanset testdir [file dirname $argv0] 149b8afef2Sdansource $testdir/tester.tcl 159b8afef2Sdanset testprefix corruptI 169b8afef2Sdan 17d520041bSdanif {[permutation]=="mmap"} { 18d520041bSdan finish_test 19d520041bSdan return 20d520041bSdan} 21d520041bSdan 22af3906a7Sdrh# This module uses hard-coded offsets which do not work if the reserved_bytes 23af3906a7Sdrh# value is nonzero. 24af3906a7Sdrhif {[nonzero_reserved_bytes]} {finish_test; return;} 25af3906a7Sdrh 269b8afef2Sdandatabase_may_be_corrupt 279b8afef2Sdan 289b8afef2Sdan# Initialize the database. 299b8afef2Sdan# 309b8afef2Sdando_execsql_test 1.1 { 319b8afef2Sdan PRAGMA page_size=1024; 329b8afef2Sdan PRAGMA auto_vacuum=0; 339b8afef2Sdan CREATE TABLE t1(a); 349b8afef2Sdan CREATE INDEX i1 ON t1(a); 35d9c131c3Sdrh INSERT INTO t1 VALUES('abcdefghijklmnop'); 369b8afef2Sdan} {} 379b8afef2Sdandb close 389b8afef2Sdan 399b8afef2Sdando_test 1.2 { 409b8afef2Sdan set offset [hexio_get_int [hexio_read test.db [expr 2*1024 + 8] 2]] 419b8afef2Sdan set off [expr 2*1024 + $offset + 1] 42d9c131c3Sdrh hexio_write test.db $off 7f06 43d9c131c3Sdrh sqlite3 db test.db 44d9c131c3Sdrh catchsql { SELECT * FROM t1 WHERE a = 10 } 45d9c131c3Sdrh} {0 {}} 46d9c131c3Sdrh 47d9c131c3Sdrhdo_test 1.3 { 48d9c131c3Sdrh db close 49d9c131c3Sdrh set offset [hexio_get_int [hexio_read test.db [expr 2*1024 + 8] 2]] 50d9c131c3Sdrh set off [expr 2*1024 + $offset + 1] 51d9c131c3Sdrh hexio_write test.db $off FFFF7f02 529b8afef2Sdan sqlite3 db test.db 539b8afef2Sdan catchsql { SELECT * FROM t1 WHERE a = 10 } 54a1f7c0a2Sdrh} {1 {database disk image is malformed}} 559b8afef2Sdan 5668916c9fSdando_test 2.0 { 5768916c9fSdan execsql { 5868916c9fSdan CREATE TABLE r(x); 5968916c9fSdan INSERT INTO r VALUES('ABCDEFGHIJK'); 6068916c9fSdan CREATE INDEX r1 ON r(x); 6168916c9fSdan } 6268916c9fSdan set pg [db one {SELECT rootpage FROM sqlite_master WHERE name = 'r1'}] 6368916c9fSdan} {5} 6468916c9fSdan 6568916c9fSdando_test 2.1 { 6668916c9fSdan db close 6768916c9fSdan set offset [hexio_get_int [hexio_read test.db [expr (5-1)*1024 + 8] 2]] 6868916c9fSdan set off [expr (5-1)*1024 + $offset + 1] 6968916c9fSdan hexio_write test.db $off FFFF0004 7068916c9fSdan sqlite3 db test.db 7168916c9fSdan catchsql { SELECT * FROM r WHERE x >= 10.0 } 7268916c9fSdan} {1 {database disk image is malformed}} 7368916c9fSdan 7468916c9fSdando_test 2.2 { 7568916c9fSdan catchsql { SELECT * FROM r WHERE x >= 10 } 7668916c9fSdan} {1 {database disk image is malformed}} 7768916c9fSdan 7889a5833cSdrhif {[db one {SELECT sqlite_compileoption_used('ENABLE_OVERSIZE_CELL_CHECK')}]} { 7989a5833cSdrh # The following tests only work if OVERSIZE_CELL_CHECK is disabled 8089a5833cSdrh} else { 81f216e324Sdan reset_db 82f216e324Sdan do_execsql_test 3.1 { 8389a5833cSdrh PRAGMA auto_vacuum=0; 84f216e324Sdan PRAGMA page_size = 512; 85f216e324Sdan CREATE TABLE t1(a INTEGER PRIMARY KEY, b); 86f216e324Sdan WITH s(a, b) AS ( 87f216e324Sdan SELECT 2, 'abcdefghij' 88f216e324Sdan UNION ALL 89f216e324Sdan SELECT a+2, b FROM s WHERe a < 40 90f216e324Sdan ) 91f216e324Sdan INSERT INTO t1 SELECT * FROM s; 92f216e324Sdan } {} 93f216e324Sdan 94f216e324Sdan do_test 3.2 { 95f216e324Sdan hexio_write test.db [expr 512+3] 0054 96f216e324Sdan db close 97f216e324Sdan sqlite3 db test.db 98f216e324Sdan execsql { INSERT INTO t1 VALUES(5, 'klmnopqrst') } 99f216e324Sdan execsql { INSERT INTO t1 VALUES(7, 'klmnopqrst') } 100f216e324Sdan } {} 101f216e324Sdan 102f216e324Sdan db close 103f216e324Sdan sqlite3 db test.db 10489a5833cSdrh do_catchsql_test 3.3 { 105f216e324Sdan INSERT INTO t1 VALUES(9, 'klmnopqrst'); 106f216e324Sdan } {1 {database disk image is malformed}} 10789a5833cSdrh} ;# end-if !defined(ENABLE_OVERSIZE_CELL_CHECK) 108cf3d17c6Sdan 109cf3d17c6Sdan 110cf3d17c6Sdan#------------------------------------------------------------------------- 111cf3d17c6Sdan# Test that an assert() failure discovered by AFL corrupt database file 112cf3d17c6Sdan# testing has been fixed. 113cf3d17c6Sdan# 114cf3d17c6Sdanreset_db 115cf3d17c6Sdando_execsql_test 4.0 { 116cf3d17c6Sdan PRAGMA page_size = 65536; 117cf3d17c6Sdan PRAGMA autovacuum = 0; 118cf3d17c6Sdan CREATE TABLE t1(a INTEGER PRIMARY KEY, b); 119cf3d17c6Sdan INSERT INTO t1 VALUES(-1, 'abcdefghij'); 120cf3d17c6Sdan INSERT INTO t1 VALUES(0, 'abcdefghij'); 121cf3d17c6Sdan} 122cf3d17c6Sdan 123cf3d17c6Sdanset root [db one {SELECT rootpage FROM sqlite_master}] 124cf3d17c6Sdanset offset [expr ($root-1) * 65536] 125cf3d17c6Sdan 1266c1944f6Sdanifcapable oversize_cell_check { 1276c1944f6Sdan set res {1 {database disk image is malformed}} 1286c1944f6Sdan} else { 1296c1944f6Sdan set res {0 {}} 1306c1944f6Sdan} 131cf3d17c6Sdando_test 4.1 { 132cf3d17c6Sdan db close 133cf3d17c6Sdan hexio_write test.db [expr $offset + 8 + 2] 0000 134cf3d17c6Sdan hexio_write test.db [expr $offset + 5] 0000 135cf3d17c6Sdan sqlite3 db test.db 1366c1944f6Sdan catchsql { DELETE FROM t1 WHERE a=0 } 1376c1944f6Sdan} $res 138cf3d17c6Sdan 1392fc3a6cdSdan 1402fc3a6cdSdan#------------------------------------------------------------------------- 1412fc3a6cdSdan# Database properties: 1422fc3a6cdSdan# 1432fc3a6cdSdan# * Incremental vacuum mode. 1442fc3a6cdSdan# * Database root table has a single leaf page. 1452fc3a6cdSdan# * Free list consists of a single trunk page. 1462fc3a6cdSdan# 1472fc3a6cdSdan# The db is then corrupted by adding the root table leaf page as a free-list 1482fc3a6cdSdan# leaf page (so that it is referenced twice). 1492fc3a6cdSdan# 1502fc3a6cdSdan# Then, a new table is created. The new root page is the current free-list 1512fc3a6cdSdan# trunk. This means that the root table leaf page is made into the new 1522fc3a6cdSdan# free list trunk, which corrupts its header. Then, when the new entry is 1532fc3a6cdSdan# inserted into the root table, things would get chaotic. 1542fc3a6cdSdan# 1552fc3a6cdSdanreset_db 1562fc3a6cdSdando_test 5.0 { 1572fc3a6cdSdan execsql { 1582fc3a6cdSdan PRAGMA page_size = 512; 1592fc3a6cdSdan PRAGMA auto_vacuum = 2; 1602fc3a6cdSdan } 1612fc3a6cdSdan for {set i 3} {1} {incr i} { 1622fc3a6cdSdan execsql "CREATE TABLE t${i}(x)" 1632fc3a6cdSdan if {[db one {PRAGMA page_count}]>$i} break 1642fc3a6cdSdan } 1652fc3a6cdSdan set nPage [db one {PRAGMA page_count}] 1662fc3a6cdSdan execsql { 1672fc3a6cdSdan CREATE TABLE t100(x); 1682fc3a6cdSdan DROP TABLE t100; 1692fc3a6cdSdan } 1702fc3a6cdSdan} {} 1712fc3a6cdSdan 1722fc3a6cdSdando_execsql_test 5.1 { 1732fc3a6cdSdan PRAGMA page_count 1742fc3a6cdSdan} [expr $nPage+1] 1752fc3a6cdSdan 1762fc3a6cdSdando_test 5.2 { 1772fc3a6cdSdan # The last page of the db is now the only leaf of the sqlite_master table. 1782fc3a6cdSdan # Corrupt the db by adding it to the free-list as well (the second last 1792fc3a6cdSdan # page of the db is the free-list trunk). 1802fc3a6cdSdan db close 1812fc3a6cdSdan hexio_write test.db [expr 512*($nPage-1)] [ 1822fc3a6cdSdan format "%.8X%.8X%.8X" 0 1 [expr $nPage+1] 1832fc3a6cdSdan ] 1842fc3a6cdSdan} {12} 1852fc3a6cdSdan 1862fc3a6cdSdando_test 5.3 { 1872fc3a6cdSdan sqlite3 db test.db 1882fc3a6cdSdan catchsql { CREATE TABLE tx(x); } 1892fc3a6cdSdan} {1 {database disk image is malformed}} 1902fc3a6cdSdan 1912fc3a6cdSdan 1920f8076ddSdan#------------------------------------------------------------------------- 1930f8076ddSdan# Set the payload size of a cell to just less than 2^32 bytes (not 1940f8076ddSdan# possible in an uncorrupted db). Then try to delete the cell. At one 1950f8076ddSdan# point this led to an integer overflow that caused an assert() to fail. 1960f8076ddSdan# 1970f8076ddSdanreset_db 1980f8076ddSdando_execsql_test 6.0 { 1990f8076ddSdan PRAGMA page_size = 512; 2006c1944f6Sdan PRAGMA auto_vacuum=0; 2010f8076ddSdan CREATE TABLE t1(x); 2020f8076ddSdan INSERT INTO t1 VALUES(zeroblob(300)); 2030f8076ddSdan INSERT INTO t1 VALUES(zeroblob(600)); 2040f8076ddSdan} {} 2050f8076ddSdando_test 6.1 { 2060f8076ddSdan db close 207eeab2c63Sdrh hexio_write test.db 616 8FFFFFFF7F02 2080f8076ddSdan sqlite3 db test.db 2090f8076ddSdan execsql { DELETE FROM t1 WHERE rowid=2 } 2100f8076ddSdan} {} 2110f8076ddSdan 21208f901b0Sdan#------------------------------------------------------------------------- 21308f901b0Sdan# See what happens if the sqlite_master entry associated with a PRIMARY 21408f901b0Sdan# KEY or UNIQUE index is removed. 21508f901b0Sdan# 21608f901b0Sdanreset_db 21708f901b0Sdando_execsql_test 7.0 { 2186c1944f6Sdan PRAGMA auto_vacuum=0; 21908f901b0Sdan CREATE TABLE t1(x PRIMARY KEY, y); 22008f901b0Sdan INSERT INTO t1 VALUES('a', 'A'); 22108f901b0Sdan INSERT INTO t1 VALUES('b', 'A'); 22208f901b0Sdan INSERT INTO t1 VALUES('c', 'A'); 22308f901b0Sdan SELECT name FROM sqlite_master; 22408f901b0Sdan} {t1 sqlite_autoindex_t1_1} 225*6ab91a7aSdrhsqlite3_db_config db DEFENSIVE 0 22608f901b0Sdando_execsql_test 7.1 { 22708f901b0Sdan PRAGMA writable_schema = 1; 22808f901b0Sdan DELETE FROM sqlite_master WHERE name = 'sqlite_autoindex_t1_1'; 22908f901b0Sdan} 23008f901b0Sdando_test 7.2 { 23108f901b0Sdan db close 23208f901b0Sdan sqlite3 db test.db 23308f901b0Sdan catchsql { UPDATE t1 SET x='d' AND y='D' WHERE rowid = 2 } 23408f901b0Sdan} {1 {database disk image is malformed}} 2350f8076ddSdan 236fb0246baSdan#------------------------------------------------------------------------- 237fb0246baSdan# At one point an assert() would fail if attempt was made to free page 1. 238fb0246baSdan# 239fb0246baSdanreset_db 240fb0246baSdando_execsql_test 8.0 { 2416c1944f6Sdan PRAGMA auto_vacuum=0; 242fb0246baSdan CREATE TABLE t1(x); 243fb0246baSdan INSERT INTO t1 VALUES(zeroblob(300)); 244fb0246baSdan INSERT INTO t1 VALUES(zeroblob(300)); 245fb0246baSdan INSERT INTO t1 VALUES(zeroblob(300)); 246fb0246baSdan INSERT INTO t1 VALUES(zeroblob(300)); 247fb0246baSdan} {} 248fb0246baSdan 249fb0246baSdando_test 8.1 { 250fb0246baSdan db close 251fb0246baSdan hexio_write test.db [expr 1024 + 8] 00000001 252fb0246baSdan sqlite3 db test.db 253fb0246baSdan catchsql { DELETE FROM t1 } 254fb0246baSdan} {1 {database disk image is malformed}} 255fb0246baSdan 256fb0246baSdando_test 8.2 { 257fb0246baSdan db close 258fb0246baSdan sqlite3 db test.db 259fb0246baSdan execsql { PRAGMA integrity_check } 260fb0246baSdan} {/.*in database main.*/} 261fb0246baSdan 262fb0246baSdan 2639b8afef2Sdanfinish_test 264