xref: /sqlite-3.40.0/test/corrupt9.test (revision 09fe6143)
1# 2008 July 9
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# This file implements regression tests for SQLite library.
12#
13# This file implements tests to make sure SQLite does not crash or
14# segfault if it sees a corrupt database file.  It specifically focuses
15# on corruption in the form of duplicate entries on the freelist.
16#
17# $Id: corrupt9.test,v 1.3 2009/06/04 02:47:04 shane Exp $
18
19set testdir [file dirname $argv0]
20source $testdir/tester.tcl
21
22# Do not use a codec for tests in this file, as the database file is
23# manipulated directly using tcl scripts (using the [hexio_write] command).
24#
25do_not_use_codec
26
27# These tests deal with corrupt database files
28#
29database_may_be_corrupt
30
31# We must have the page_size pragma for these tests to work.
32#
33ifcapable !pager_pragmas {
34  finish_test
35  return
36}
37
38# Return the offset to the first (trunk) page of the freelist.  Return
39# zero of the freelist is empty.
40#
41proc freelist_trunk_offset {filename} {
42  if {[hexio_read $filename 36 4]==0} {return 0}
43  set pgno [hexio_get_int [hexio_read $filename 32 4]]
44  return [expr {($pgno-1)*[hexio_get_int [hexio_read $filename 16 2]]}]
45}
46
47# This procedure looks at the first trunk page of the freelist and
48# corrupts that page by overwriting up to N entries with duplicates
49# of the first entry.
50#
51proc corrupt_freelist {filename N} {
52  set offset [freelist_trunk_offset $filename]
53  if {$offset==0} {error "Freelist is empty"}
54  set cnt [hexio_get_int [hexio_read $filename [expr {$offset+4}] 4]]
55  set pgno [hexio_read $filename [expr {$offset+8}] 4]
56  for {set i 12} {$N>0 && $i<8+4*$cnt} {incr i 4; incr N -1} {
57    hexio_write $filename [expr {$offset+$i}] $pgno
58  }
59}
60
61# Create a database to work with.  Make sure there are plenty of
62# entries on the freelist.
63#
64do_test corrupt9-1.1 {
65  execsql {
66    PRAGMA auto_vacuum=NONE;
67    PRAGMA page_size=1024;
68    CREATE TABLE t1(x);
69    INSERT INTO t1(x) VALUES(1);
70    INSERT INTO t1(x) VALUES(2);
71    INSERT INTO t1(x) SELECT x+2 FROM t1;
72    INSERT INTO t1(x) SELECT x+4 FROM t1;
73    INSERT INTO t1(x) SELECT x+8 FROM t1;
74    INSERT INTO t1(x) SELECT x+16 FROM t1;
75    INSERT INTO t1(x) SELECT x+32 FROM t1;
76    INSERT INTO t1(x) SELECT x+64 FROM t1;
77    INSERT INTO t1(x) SELECT x+128 FROM t1;
78    INSERT INTO t1(x) SELECT x+256 FROM t1;
79    CREATE TABLE t2(a,b);
80    INSERT INTO t2 SELECT x, x*x FROM t1;
81    CREATE INDEX i1 ON t1(x);
82    CREATE INDEX i2 ON t2(b,a);
83    DROP INDEX i2;
84  }
85  expr {[file size test.db]>1024*24}
86} {1}
87integrity_check corrupt9-1.2
88
89# Corrupt the freelist by adding duplicate entries to the freelist.
90# Make sure the corruption is detected.
91#
92db close
93forcecopy test.db test.db-template
94
95corrupt_freelist test.db 1
96sqlite3 db test.db
97do_test corrupt9-2.1 {
98  set x [db eval {PRAGMA integrity_check}]
99  expr {$x!="ok"}
100} {1}
101do_test corrupt9-2.2 {
102  catchsql {
103    CREATE INDEX i2 ON t2(b,a);
104    REINDEX;
105  }
106} {1 {database disk image is malformed}}
107
108
109db close
110forcecopy test.db-template test.db
111corrupt_freelist test.db 2
112sqlite3 db test.db
113do_test corrupt9-3.1 {
114  set x [db eval {PRAGMA integrity_check}]
115  expr {$x!="ok"}
116} {1}
117do_test corrupt9-3.2 {
118  catchsql {
119    CREATE INDEX i2 ON t2(b,a);
120    REINDEX;
121  }
122} {1 {database disk image is malformed}}
123
124db close
125forcecopy test.db-template test.db
126corrupt_freelist test.db 3
127sqlite3 db test.db
128do_test corrupt9-4.1 {
129  set x [db eval {PRAGMA integrity_check}]
130  expr {$x!="ok"}
131} {1}
132do_test corrupt9-4.2 {
133  catchsql {
134    CREATE INDEX i2 ON t2(b,a);
135    REINDEX;
136  }
137} {1 {database disk image is malformed}}
138
139
140finish_test
141