OLD | NEW |
1 | 1 |
2 # 2007 Aug 13 | 2 # 2007 Aug 13 |
3 # | 3 # |
4 # The author disclaims copyright to this source code. In place of | 4 # The author disclaims copyright to this source code. In place of |
5 # a legal notice, here is a blessing: | 5 # a legal notice, here is a blessing: |
6 # | 6 # |
7 # May you do good and not evil. | 7 # May you do good and not evil. |
8 # May you find forgiveness for yourself and forgive others. | 8 # May you find forgiveness for yourself and forgive others. |
9 # May you share freely, never taking more than you give. | 9 # May you share freely, never taking more than you give. |
10 # | 10 # |
(...skipping 16 matching lines...) Expand all Loading... |
27 } | 27 } |
28 | 28 |
29 db close | 29 db close |
30 | 30 |
31 for {set ii 0} {$ii < 10} {incr ii} { | 31 for {set ii 0} {$ii < 10} {incr ii} { |
32 for {set jj 50} {$jj < 100} {incr jj} { | 32 for {set jj 50} {$jj < 100} {incr jj} { |
33 | 33 |
34 # Set up the database so that it is an auto-vacuum database | 34 # Set up the database so that it is an auto-vacuum database |
35 # containing a single table (root page 3) with a single row. | 35 # containing a single table (root page 3) with a single row. |
36 # The row has an overflow page (page 4). | 36 # The row has an overflow page (page 4). |
37 file delete -force test.db test.db-journal | 37 forcedelete test.db test.db-journal |
38 sqlite3 db test.db | 38 sqlite3 db test.db |
39 set c [string repeat 3 1500] | 39 set c [string repeat 3 1500] |
40 db eval { | 40 db eval { |
41 pragma auto_vacuum = 1; | 41 pragma auto_vacuum = 1; |
42 CREATE TABLE t1(a, b, c); | 42 CREATE TABLE t1(a, b, c); |
43 INSERT INTO t1 VALUES('1111111111', '2222222222', $c); | 43 INSERT INTO t1 VALUES('1111111111', '2222222222', $c); |
44 } | 44 } |
45 db close | 45 db close |
46 | 46 |
47 do_test crash5-$ii.$jj.1 { | 47 do_test crash5-$ii.$jj.1 { |
48 crashsql -delay 1 -file test.db-journal -seed $ii -tclbody [join [list \ | 48 crashsql -delay 1 -file test.db-journal -seed $ii -tclbody [join [list \ |
49 [list set iFail $jj] { | 49 [list set iFail $jj] { |
50 sqlite3_crashparams 0 [file join [pwd] test.db-journal] | 50 sqlite3_crashparams 0 [file join [get_pwd] test.db-journal] |
51 | 51 |
52 # Begin a transaction and evaluate a "CREATE INDEX" statement | 52 # Begin a transaction and evaluate a "CREATE INDEX" statement |
53 # with the iFail'th malloc() set to fail. This operation will | 53 # with the iFail'th malloc() set to fail. This operation will |
54 # have to move the current contents of page 4 (the overflow | 54 # have to move the current contents of page 4 (the overflow |
55 # page) to make room for the new root page. The bug is that | 55 # page) to make room for the new root page. The bug is that |
56 # if malloc() fails at a particular point in sqlite3PagerMovepage(), | 56 # if malloc() fails at a particular point in sqlite3PagerMovepage(), |
57 # sqlite mistakenly thinks that the page being moved (page 4) has | 57 # sqlite mistakenly thinks that the page being moved (page 4) has |
58 # been safely synced into the journal. If the page is written | 58 # been safely synced into the journal. If the page is written |
59 # to later in the transaction, it may be written out to the database | 59 # to later in the transaction, it may be written out to the database |
60 # before the relevant part of the journal has been synced. | 60 # before the relevant part of the journal has been synced. |
61 # | 61 # |
62 db eval BEGIN | 62 db eval BEGIN |
63 sqlite3_memdebug_fail $iFail -repeat 0 | 63 sqlite3_memdebug_fail $iFail -repeat 0 |
64 catch {db eval { CREATE UNIQUE INDEX i1 ON t1(a); }} msg | 64 catch {db eval { CREATE UNIQUE INDEX i1 ON t1(a); }} msg |
65 # puts "$n $msg ac=[sqlite3_get_autocommit db]" | 65 # puts "$n $msg ac=[sqlite3_get_autocommit db]" |
66 | 66 |
67 # If the transaction is still active (it may not be if the malloc() | 67 # If the transaction is still active (it may not be if the malloc() |
68 # failure occured in the OS layer), write to the database. Make sure | 68 # failure occurred in the OS layer), write to the database. Make sure |
69 # page 4 is among those written. | 69 # page 4 is among those written. |
70 # | 70 # |
71 if {![sqlite3_get_autocommit db]} { | 71 if {![sqlite3_get_autocommit db]} { |
72 db eval { | 72 db eval { |
73 DELETE FROM t1; -- This will put page 4 on the free list. | 73 DELETE FROM t1; -- This will put page 4 on the free list. |
74 INSERT INTO t1 VALUES('111111111', '2222222222', '33333333'); | 74 INSERT INTO t1 VALUES('111111111', '2222222222', '33333333'); |
75 INSERT INTO t1 SELECT * FROM t1; -- 2 | 75 INSERT INTO t1 SELECT * FROM t1; -- 2 |
76 INSERT INTO t1 SELECT * FROM t1; -- 4 | 76 INSERT INTO t1 SELECT * FROM t1; -- 4 |
77 INSERT INTO t1 SELECT * FROM t1; -- 8 | 77 INSERT INTO t1 SELECT * FROM t1; -- 8 |
78 INSERT INTO t1 SELECT * FROM t1; -- 16 | 78 INSERT INTO t1 SELECT * FROM t1; -- 16 |
79 INSERT INTO t1 SELECT * FROM t1; -- 32 | 79 INSERT INTO t1 SELECT * FROM t1; -- 32 |
80 INSERT INTO t1 SELECT * FROM t1 WHERE rowid%2; -- 48 | 80 INSERT INTO t1 SELECT * FROM t1 WHERE rowid%2; -- 48 |
81 } | 81 } |
82 } | 82 } |
83 | 83 |
84 # If the right malloc() failed during the 'CREATE INDEX' above and | 84 # If the right malloc() failed during the 'CREATE INDEX' above and |
85 # the transaction was not rolled back, then the sqlite cache now | 85 # the transaction was not rolled back, then the sqlite cache now |
86 # has a dirty page 4 that it incorrectly believes is already safely | 86 # has a dirty page 4 that it incorrectly believes is already safely |
87 # in the synced part of the journal file. When | 87 # in the synced part of the journal file. When |
88 # sqlite3_release_memory() is called sqlite tries to free memory | 88 # sqlite3_release_memory() is called sqlite tries to free memory |
89 # by writing page 4 out to the db file. If it crashes later on, | 89 # by writing page 4 out to the db file. If it crashes later on, |
90 # before syncing the journal... Corruption! | 90 # before syncing the journal... Corruption! |
91 # | 91 # |
92 sqlite3_crashparams 1 [file join [pwd] test.db-journal] | 92 sqlite3_crashparams 1 [file join [get_pwd] test.db-journal] |
93 sqlite3_release_memory 8092 | 93 sqlite3_release_memory 8092 |
94 }]] {} | 94 }]] {} |
95 expr 1 | 95 expr 1 |
96 } {1} | 96 } {1} |
97 | 97 |
98 sqlite3 db test.db | 98 sqlite3 db test.db |
99 do_test crash5-$ii.$jj.2 { | 99 do_test crash5-$ii.$jj.2 { |
100 db eval {pragma integrity_check} | 100 db eval {pragma integrity_check} |
101 } {ok} | 101 } {ok} |
102 do_test crash5-$ii.$jj.3 { | 102 do_test crash5-$ii.$jj.3 { |
103 db eval {SELECT * FROM t1} | 103 db eval {SELECT * FROM t1} |
104 } [list 1111111111 2222222222 $::c] | 104 } [list 1111111111 2222222222 $::c] |
105 db close | 105 db close |
106 } | 106 } |
107 } | 107 } |
108 | 108 |
109 | 109 |
110 finish_test | 110 finish_test |
OLD | NEW |