xref: /sqlite-3.40.0/test/corruptI.test (revision 6ab91a7a)
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# This module uses hard-coded offsets which do not work if the reserved_bytes
23# value is nonzero.
24if {[nonzero_reserved_bytes]} {finish_test; return;}
25
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
126ifcapable oversize_cell_check {
127  set res {1 {database disk image is malformed}}
128} else {
129  set res {0 {}}
130}
131do_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#
155reset_db
156do_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
172do_execsql_test 5.1 {
173  PRAGMA page_count
174} [expr $nPage+1]
175
176do_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
186do_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#
197reset_db
198do_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} {}
205do_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#
216reset_db
217do_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}
225sqlite3_db_config db DEFENSIVE 0
226do_execsql_test 7.1 {
227  PRAGMA writable_schema = 1;
228  DELETE FROM sqlite_master WHERE name = 'sqlite_autoindex_t1_1';
229}
230do_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#
239reset_db
240do_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
249do_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
256do_test 8.2 {
257  db close
258  sqlite3 db test.db
259  execsql { PRAGMA integrity_check }
260} {/.*in database main.*/}
261
262
263finish_test
264