xref: /sqlite-3.40.0/test/corruptI.test (revision 6ab91a7a)
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