OLD | NEW |
| (Empty) |
1 # 2009 June 3 | |
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 # $Id: corruptD.test,v 1.2 2009/06/05 17:09:12 drh Exp $ | |
13 | |
14 set testdir [file dirname $argv0] | |
15 source $testdir/tester.tcl | |
16 | |
17 # Do not use a codec for tests in this file, as the database file is | |
18 # manipulated directly using tcl scripts (using the [hexio_write] command). | |
19 # | |
20 do_not_use_codec | |
21 | |
22 # These tests deal with corrupt database files | |
23 # | |
24 database_may_be_corrupt | |
25 | |
26 #-------------------------------------------------------------------------- | |
27 # OVERVIEW | |
28 # | |
29 # This test file attempts to verify that SQLite does not read past the | |
30 # end of any in-memory buffers as a result of corrupted database page | |
31 # images. Usually this happens because a field within a database page | |
32 # that contains an offset to some other structure within the same page | |
33 # is set to too large a value. A database page contains the following | |
34 # such fields: | |
35 # | |
36 # 1. The page header field that contains the offset to the first | |
37 # free block of space. | |
38 # | |
39 # 2. The first two bytes of all but the last free block on the free-block | |
40 # list (the offset to the next free block). | |
41 # | |
42 # 3. The page header field containing the number of cells on the page | |
43 # (implicitly defines the offset to the final element in the cell offset | |
44 # array, which could potentially be off the end of the page). | |
45 # | |
46 # 4. The page header field containing the offset to the start of the cell | |
47 # content area. | |
48 # | |
49 # 5. The contents of the cell offset array. | |
50 # | |
51 # 6. The first few bytes of each cell determine the size of the cell | |
52 # stored within the page, and hence the offset to the final byte of | |
53 # the cell. | |
54 # | |
55 # If any of the above fields are set to too large a value, then a buffer | |
56 # overread may occur. This test script creates and operates on various | |
57 # strategically corrupted database files to attempt to provoke such buffer | |
58 # overreads. | |
59 # | |
60 # Very often, a buffer overread passes unnoticed, particularly in workstation | |
61 # environments. For this reason, this test script should be run using valgrind | |
62 # (or similar) in order to verify that no overreads occur. | |
63 # | |
64 # TEST PLAN | |
65 # | |
66 # Test cases corruptD-1.* are white-box tests. They attempt to corrupt | |
67 # one of the above fields, then exercise each part of the code in btree.c | |
68 # that uses said field. | |
69 # | |
70 # Offset variables 1, 2, 3 and 4 are all checked to make sure they | |
71 # will not result in buffer overruns as part of page initialization in | |
72 # sqlite3BtreeInitPage(). Offsets 5 and 6 cannot be tested as part of | |
73 # page initialization, as trying to do so causes a performance hit. | |
74 # | |
75 | |
76 do_test corruptD-1.0 { | |
77 execsql { | |
78 PRAGMA auto_vacuum = 0; | |
79 PRAGMA page_size = 1024; | |
80 CREATE TABLE t1(a, b); | |
81 CREATE INDEX i1 ON t1(a, b); | |
82 } | |
83 for {set ii 1} {$ii < 50} {incr ii} { | |
84 execsql { INSERT INTO t1 VALUES($ii, $ii * $ii) } | |
85 } | |
86 execsql { | |
87 DELETE FROM t1 WHERE a = 10; | |
88 DELETE FROM t1 WHERE a = 20; | |
89 DELETE FROM t1 WHERE a = 30; | |
90 DELETE FROM t1 WHERE a = 40; | |
91 } | |
92 forcecopy test.db test.bu | |
93 } {} | |
94 | |
95 proc incr_change_counter {} { | |
96 hexio_write test.db 24 [ | |
97 hexio_render_int32 [expr [hexio_get_int [hexio_read test.db 24 4]] + 1] | |
98 ] | |
99 } | |
100 | |
101 proc restore_file {} { | |
102 db close | |
103 forcecopy test.bu test.db | |
104 sqlite3 db test.db | |
105 } | |
106 | |
107 #------------------------------------------------------------------------- | |
108 # The following tests, corruptD-1.1.*, focus on the page header field | |
109 # containing the offset of the first free block in a page. | |
110 # | |
111 do_test corruptD-1.1.1 { | |
112 incr_change_counter | |
113 hexio_write test.db [expr 1024+1] FFFF | |
114 catchsql { SELECT * FROM t1 ORDER BY rowid } | |
115 } {1 {database disk image is malformed}} | |
116 do_test corruptD-1.1.2 { | |
117 incr_change_counter | |
118 hexio_write test.db [expr 1024+1] [hexio_render_int32 1021] | |
119 catchsql { SELECT * FROM t1 ORDER BY rowid } | |
120 } {1 {database disk image is malformed}} | |
121 | |
122 #------------------------------------------------------------------------- | |
123 # The following tests, corruptD-1.2.*, focus on the offsets contained | |
124 # in the first 2 byte of each free-block on the free-list. | |
125 # | |
126 do_test corruptD-1.2.1 { | |
127 restore_file | |
128 } {} | |
129 do_test corruptD-1.2.2 { | |
130 } {} | |
131 | |
132 #------------------------------------------------------------------------- | |
133 # The following tests, corruptD-1.4.*, ... | |
134 # | |
135 | |
136 | |
137 #------------------------------------------------------------------------- | |
138 # The following tests, corruptD-1.5.*, focus on the offsets contained | |
139 # in the cell offset array. | |
140 # | |
141 # defragmentPage | |
142 # | |
143 | |
144 finish_test | |
OLD | NEW |