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# We must have the page_size pragma for these tests to work.
28#
29ifcapable !pager_pragmas {
30  finish_test
31  return
32}
33
34# Return the offset to the first (trunk) page of the freelist.  Return
35# zero of the freelist is empty.
36#
37proc freelist_trunk_offset {filename} {
38  if {[hexio_read $filename 36 4]==0} {return 0}
39  set pgno [hexio_get_int [hexio_read $filename 32 4]]
40  return [expr {($pgno-1)*[hexio_get_int [hexio_read $filename 16 2]]}]
41}
42
43# This procedure looks at the first trunk page of the freelist and
44# corrupts that page by overwriting up to N entries with duplicates
45# of the first entry.
46#
47proc corrupt_freelist {filename N} {
48  set offset [freelist_trunk_offset $filename]
49  if {$offset==0} {error "Freelist is empty"}
50  set cnt [hexio_get_int [hexio_read $filename [expr {$offset+4}] 4]]
51  set pgno [hexio_read $filename [expr {$offset+8}] 4]
52  for {set i 12} {$N>0 && $i<8+4*$cnt} {incr i 4; incr N -1} {
53    hexio_write $filename [expr {$offset+$i}] $pgno
54  }
55}
56
57# Create a database to work with.  Make sure there are plenty of
58# entries on the freelist.
59#
60do_test corrupt9-1.1 {
61  execsql {
62    PRAGMA auto_vacuum=NONE;
63    PRAGMA page_size=1024;
64    CREATE TABLE t1(x);
65    INSERT INTO t1(x) VALUES(1);
66    INSERT INTO t1(x) VALUES(2);
67    INSERT INTO t1(x) SELECT x+2 FROM t1;
68    INSERT INTO t1(x) SELECT x+4 FROM t1;
69    INSERT INTO t1(x) SELECT x+8 FROM t1;
70    INSERT INTO t1(x) SELECT x+16 FROM t1;
71    INSERT INTO t1(x) SELECT x+32 FROM t1;
72    INSERT INTO t1(x) SELECT x+64 FROM t1;
73    INSERT INTO t1(x) SELECT x+128 FROM t1;
74    INSERT INTO t1(x) SELECT x+256 FROM t1;
75    CREATE TABLE t2(a,b);
76    INSERT INTO t2 SELECT x, x*x FROM t1;
77    CREATE INDEX i1 ON t1(x);
78    CREATE INDEX i2 ON t2(b,a);
79    DROP INDEX i2;
80  }
81  expr {[file size test.db]>1024*24}
82} {1}
83integrity_check corrupt9-1.2
84
85# Corrupt the freelist by adding duplicate entries to the freelist.
86# Make sure the corruption is detected.
87#
88db close
89file copy -force test.db test.db-template
90
91corrupt_freelist test.db 1
92sqlite3 db test.db
93do_test corrupt9-2.1 {
94  set x [db eval {PRAGMA integrity_check}]
95  expr {$x!="ok"}
96} {1}
97do_test corrupt9-2.2 {
98  catchsql {
99    CREATE INDEX i2 ON t2(b,a);
100    REINDEX;
101  }
102} {1 {database disk image is malformed}}
103
104
105db close
106file copy -force test.db-template test.db
107corrupt_freelist test.db 2
108sqlite3 db test.db
109do_test corrupt9-3.1 {
110  set x [db eval {PRAGMA integrity_check}]
111  expr {$x!="ok"}
112} {1}
113do_test corrupt9-3.2 {
114  catchsql {
115    CREATE INDEX i2 ON t2(b,a);
116    REINDEX;
117  }
118} {1 {database disk image is malformed}}
119
120db close
121file copy -force test.db-template test.db
122corrupt_freelist test.db 3
123sqlite3 db test.db
124do_test corrupt9-4.1 {
125  set x [db eval {PRAGMA integrity_check}]
126  expr {$x!="ok"}
127} {1}
128do_test corrupt9-4.2 {
129  catchsql {
130    CREATE INDEX i2 ON t2(b,a);
131    REINDEX;
132  }
133} {1 {database disk image is malformed}}
134 
135
136finish_test
137