xref: /sqlite-3.40.0/test/fts3corrupt.test (revision 93a4b411)
1# 2010 October 27
2#
3#    May you do good and not evil.
4#    May you find forgiveness for yourself and forgive others.
5#    May you share freely, never taking more than you give.
6#
7#***********************************************************************
8# Test that the FTS3 extension does not crash when it encounters a
9# corrupt data structure on disk.
10#
11
12
13set testdir [file dirname $argv0]
14source $testdir/tester.tcl
15
16# If SQLITE_ENABLE_FTS3 is not defined, omit this file.
17ifcapable !fts3 { finish_test ; return }
18
19set ::testprefix fts3corrupt
20
21
22# Test that a doclist with a length field that indicates that the doclist
23# extends past the end of the node on which it resides is correctly identified
24# as database corruption.
25#
26sqlite3_db_config db DEFENSIVE 0
27do_execsql_test 1.0 {
28  CREATE VIRTUAL TABLE t1 USING fts3;
29  INSERT INTO t1 VALUES('hello');
30} {}
31do_test fts3corrupt-1.1 {
32  set blob [db one {SELECT root from t1_segdir}]
33  set blob [binary format a7ca* $blob 24 [string range $blob 8 end]]
34  execsql { UPDATE t1_segdir SET root = $blob }
35} {}
36do_test fts3corrupt-1.2 {
37  foreach w {a b c d e f g h i j k l m n o} {
38    execsql { INSERT INTO t1 VALUES($w) }
39  }
40} {}
41do_catchsql_test 1.3 {
42  INSERT INTO t1 VALUES('world');
43} {1 {database disk image is malformed}}
44do_test 1.3.1 { sqlite3_extended_errcode db } SQLITE_CORRUPT_VTAB
45do_execsql_test 1.4 {
46  DROP TABLE t1;
47}
48
49# This block of tests checks that corruption is correctly detected if the
50# length field of a term on a leaf node indicates that the term extends past
51# the end of the node on which it resides. There are two cases:
52#
53#   1. The first term on the node.
54#   2. The second or subsequent term on the node (prefix compressed term).
55#
56do_execsql_test 2.0 {
57  CREATE VIRTUAL TABLE t1 USING fts3;
58  BEGIN;
59    INSERT INTO t1 VALUES('hello');
60    INSERT INTO t1 VALUES('hello');
61    INSERT INTO t1 VALUES('hello');
62    INSERT INTO t1 VALUES('hello');
63    INSERT INTO t1 VALUES('hello');
64  COMMIT;
65} {}
66do_test fts3corrupt-2.1 {
67  set blob [db one {SELECT root from t1_segdir}]
68  set blob [binary format a*a* "\x00\x7F" [string range $blob 2 end]]
69  execsql { UPDATE t1_segdir SET root = $blob }
70} {}
71do_catchsql_test 2.2 {
72  SELECT rowid FROM t1 WHERE t1 MATCH 'hello'
73} {1 {database disk image is malformed}}
74do_test 2.2.1 { sqlite3_extended_errcode db } SQLITE_CORRUPT_VTAB
75
76do_execsql_test 3.0 {
77  DROP TABLE t1;
78  CREATE VIRTUAL TABLE t1 USING fts3;
79  BEGIN;
80    INSERT INTO t1 VALUES('hello');
81    INSERT INTO t1 VALUES('world');
82  COMMIT;
83} {}
84do_test fts3corrupt-3.1 {
85  set blob [db one {SELECT quote(root) from t1_segdir}]
86  set blob [binary format a11a*a* $blob "\x7F" [string range $blob 12 end]]
87  execsql { UPDATE t1_segdir SET root = $blob }
88} {}
89do_catchsql_test 3.2 {
90  SELECT rowid FROM t1 WHERE t1 MATCH 'world'
91} {1 {database disk image is malformed}}
92do_test 3.2.1 { sqlite3_extended_errcode db } SQLITE_CORRUPT_VTAB
93
94
95do_execsql_test 4.0 {
96  DROP TABLE t1;
97  CREATE VIRTUAL TABLE t1 USING fts3;
98  INSERT INTO t1(t1) VALUES('nodesize=24');
99}
100do_test fts3corrupt-4.1 {
101  execsql BEGIN
102  foreach s {
103     "amxtvoo adqwroyhz auq aithtir avniqnuynvf axp ahibayfynig agbicpm"
104     "ajdtebs anteaxr aieynenwmd awpl alo akxcrwow aoxftge aoqvgul"
105     "amcfvdr auz apu aebelm ahuxyz aqc asyafdb agulvhvqu"
106     "apepwfyz azkhdvkw aenyelxzbk aslnitbyet aycdsdcpgr aqzzdbc agfi axnypydou"
107     "aaqrzzcm apcxdxo atumltzj aevvivo aodknoft aqoyytoz alobx apldt"
108  } {
109    execsql { INSERT INTO t1 VALUES($s) }
110  }
111  execsql COMMIT
112} {}
113
114do_catchsql_test 4.2 {
115  UPDATE t1_segdir SET root = X'FFFFFFFFFFFFFFFF';
116  SELECT rowid FROM t1 WHERE t1 MATCH 'world';
117} {1 {database disk image is malformed}}
118do_test 4.2.1 { sqlite3_extended_errcode db } SQLITE_CORRUPT_VTAB
119
120set    blob [binary format cca*cca*cca*cca*cca*cca*cca*cca*cca*cca*a* \
121  22 120 [string repeat a 120]  \
122  22 120 [string repeat b 120]  \
123  22 120 [string repeat c 120]  \
124  22 120 [string repeat d 120]  \
125  22 120 [string repeat e 120]  \
126  22 120 [string repeat f 120]  \
127  22 120 [string repeat g 120]  \
128  22 120 [string repeat h 120]  \
129  22 120 [string repeat i 120]  \
130  22 120 [string repeat j 120]  \
131  "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
132]
133
134do_catchsql_test 4.3 {
135  UPDATE t1_segdir SET root = $blob;
136  SELECT rowid FROM t1 WHERE t1 MATCH 'world';
137} {1 {database disk image is malformed}}
138do_test 4.3.1 { sqlite3_extended_errcode db } SQLITE_CORRUPT_VTAB
139
140# Test a special kind of corruption, where the %_stat table contains
141# an invalid entry. At one point this could lead to a division-by-zero
142# error in fts4.
143#
144do_execsql_test 5.0 {
145  DROP TABLE t1;
146  CREATE VIRTUAL TABLE t1 USING fts4;
147}
148do_test 5.1 {
149  db func nn nn
150  execsql BEGIN
151  execsql { INSERT INTO t1 VALUES('one') }
152  execsql { INSERT INTO t1 VALUES('two') }
153  execsql { INSERT INTO t1 VALUES('three') }
154  execsql { INSERT INTO t1 VALUES('four') }
155  execsql COMMIT
156} {}
157do_catchsql_test 5.2 {
158  UPDATE t1_stat SET value = X'0000';
159  SELECT matchinfo(t1, 'nxa') FROM t1 WHERE t1 MATCH 't*';
160} {1 {database disk image is malformed}}
161do_test 5.2.1 { sqlite3_extended_errcode db } SQLITE_CORRUPT_VTAB
162do_catchsql_test 5.3 {
163  UPDATE t1_stat SET value = NULL;
164  SELECT matchinfo(t1, 'nxa') FROM t1 WHERE t1 MATCH 't*';
165} {1 {database disk image is malformed}}
166do_test 5.3.1 { sqlite3_extended_errcode db } SQLITE_CORRUPT_VTAB
167
168# 2019-11-18 https://bugs.chromium.org/p/chromium/issues/detail?id=1025467
169# bug1
170db close
171sqlite3 db :memory:
172do_catchsql_test 6.10 {
173  CREATE VIRTUAL TABLE f using fts3(a,b);
174  CREATE TABLE f_stat(id INTEGER PRIMARY KEY, value BLOB);
175  INSERT INTO f_segdir VALUES (2000, 0,0,0, '16', '');
176  INSERT INTO f_segdir VALUES (1999, 0,0,0, '0 18',
177                               x'000131030102000103323334050101010200');
178  INSERT INTO f_segments (blockid) values (16);
179  INSERT INTO f_segments values (0, x'');
180  INSERT INTO f_stat VALUES (1,x'cf0f01');
181  INSERT INTO f(f) VALUES ('merge=1');
182} {1 {database disk image is malformed}}
183
184# 2020-03-02 https://bugs.chromium.org/p/chromium/issues/detail?id=1057441
185# The ticket complains of use of an uninitialized value. That part is harmless.
186# The only reason to fix this is the failure to detect a subtly corrupt
187# inverted index.
188#
189reset_db
190do_catchsql_test 7.10 {
191  CREATE VIRTUAL TABLE f USING fts3(a,b);
192  INSERT INTO f_segdir VALUES (0,0,1,0,'0 0',x'01010101020101');
193  SELECT  matchinfo( f , 'pcx')  FROM f WHERE b MATCH x'c533';
194} {1 {database disk image is malformed}}
195
196reset_db
197sqlite3_fts3_may_be_corrupt 1
198do_execsql_test 8.1 {
199  CREATE VIRTUAL TABLE f USING fts3(a);
200  INSERT INTO f(f) VALUES('nodesize=24');
201  BEGIN;
202    INSERT INTO f VALUES('abcdefghijklmnopqrstuvwxyz0123456789');
203    INSERT INTO f VALUES('abcdefghijklmnopqrstuvwxyz0123456789');
204    INSERT INTO f VALUES('abcdefghijklmnopqrstuvwxyz0123456789');
205
206    INSERT INTO f VALUES('abcdefghijklmnopqrstuvwxyz012345678X');
207    INSERT INTO f VALUES('abcdefghijklmnopqrstuvwxyz012345678X');
208    INSERT INTO f VALUES('abcdefghijklmnopqrstuvwxyz012345678X');
209  COMMIT;
210  BEGIN;
211    INSERT INTO f VALUES('abcdefghijklmnopqrstuvwxyz0123456789');
212    INSERT INTO f VALUES('abcdefghijklmnopqrstuvwxyz0123456789');
213    INSERT INTO f VALUES('abcdefghijklmnopqrstuvwxyz0123456789');
214
215    INSERT INTO f VALUES('abcdefghijklmnopqrstuvwxyz012345678X');
216    INSERT INTO f VALUES('abcdefghijklmnopqrstuvwxyz012345678X');
217    INSERT INTO f VALUES('abcdefghijklmnopqrstuvwxyz012345678X');
218  COMMIT;
219
220  SELECT count(*) FROM f_segments;
221} {4}
222
223do_execsql_test 8.2 {
224  UPDATE f_segments SET block = (
225    SELECT block FROM f_segments WHERE blockid=1
226  ) WHERE blockid=2
227}
228
229do_catchsql_test 8.3 {
230  INSERT INTO f(f) VALUES('merge=2,2');
231} {1 {database disk image is malformed}}
232sqlite3_fts3_may_be_corrupt 0
233
234finish_test
235