| # 2010 October 27 |
| # |
| # May you do good and not evil. |
| # May you find forgiveness for yourself and forgive others. |
| # May you share freely, never taking more than you give. |
| # |
| #*********************************************************************** |
| # Test that the FTS3 extension does not crash when it encounters a |
| # corrupt data structure on disk. |
| # |
| |
| |
| set testdir [file dirname $argv0] |
| source $testdir/tester.tcl |
| |
| # If SQLITE_ENABLE_FTS3 is not defined, omit this file. |
| ifcapable !fts3 { finish_test ; return } |
| |
| set ::testprefix fts3corrupt |
| |
| |
| # Test that a doclist with a length field that indicates that the doclist |
| # extends past the end of the node on which it resides is correctly identified |
| # as database corruption. |
| # |
| do_execsql_test 1.0 { |
| CREATE VIRTUAL TABLE t1 USING fts3; |
| INSERT INTO t1 VALUES('hello'); |
| } {} |
| do_test fts3corrupt-1.1 { |
| set blob [db one {SELECT root from t1_segdir}] |
| set blob [binary format a7ca* $blob 24 [string range $blob 8 end]] |
| execsql { UPDATE t1_segdir SET root = $blob } |
| } {} |
| do_test fts3corrupt-1.2 { |
| foreach w {a b c d e f g h i j k l m n o} { |
| execsql { INSERT INTO t1 VALUES($w) } |
| } |
| } {} |
| do_catchsql_test 1.3 { |
| INSERT INTO t1 VALUES('world'); |
| } {1 {database disk image is malformed}} |
| do_execsql_test 1.4 { |
| DROP TABLE t1; |
| } |
| |
| # This block of tests checks that corruption is correctly detected if the |
| # length field of a term on a leaf node indicates that the term extends past |
| # the end of the node on which it resides. There are two cases: |
| # |
| # 1. The first term on the node. |
| # 2. The second or subsequent term on the node (prefix compressed term). |
| # |
| do_execsql_test 2.0 { |
| CREATE VIRTUAL TABLE t1 USING fts3; |
| BEGIN; |
| INSERT INTO t1 VALUES('hello'); |
| INSERT INTO t1 VALUES('hello'); |
| INSERT INTO t1 VALUES('hello'); |
| INSERT INTO t1 VALUES('hello'); |
| INSERT INTO t1 VALUES('hello'); |
| COMMIT; |
| } {} |
| do_test fts3corrupt-2.1 { |
| set blob [db one {SELECT root from t1_segdir}] |
| set blob [binary format a*a* "\x00\x7F" [string range $blob 2 end]] |
| execsql { UPDATE t1_segdir SET root = $blob } |
| } {} |
| do_catchsql_test 2.2 { |
| SELECT rowid FROM t1 WHERE t1 MATCH 'hello' |
| } {1 {database disk image is malformed}} |
| |
| do_execsql_test 3.0 { |
| DROP TABLE t1; |
| CREATE VIRTUAL TABLE t1 USING fts3; |
| BEGIN; |
| INSERT INTO t1 VALUES('hello'); |
| INSERT INTO t1 VALUES('world'); |
| COMMIT; |
| } {} |
| do_test fts3corrupt-3.1 { |
| set blob [db one {SELECT quote(root) from t1_segdir}] |
| set blob [binary format a11a*a* $blob "\x7F" [string range $blob 12 end]] |
| execsql { UPDATE t1_segdir SET root = $blob } |
| } {} |
| do_catchsql_test 3.2 { |
| SELECT rowid FROM t1 WHERE t1 MATCH 'world' |
| } {1 {database disk image is malformed}} |
| |
| |
| do_execsql_test 4.0 { |
| DROP TABLE t1; |
| CREATE VIRTUAL TABLE t1 USING fts3; |
| INSERT INTO t1(t1) VALUES('nodesize=24'); |
| } |
| do_test fts3corrupt-4.1 { |
| execsql BEGIN |
| foreach s { |
| "amxtvoo adqwroyhz auq aithtir avniqnuynvf axp ahibayfynig agbicpm" |
| "ajdtebs anteaxr aieynenwmd awpl alo akxcrwow aoxftge aoqvgul" |
| "amcfvdr auz apu aebelm ahuxyz aqc asyafdb agulvhvqu" |
| "apepwfyz azkhdvkw aenyelxzbk aslnitbyet aycdsdcpgr aqzzdbc agfi axnypydou" |
| "aaqrzzcm apcxdxo atumltzj aevvivo aodknoft aqoyytoz alobx apldt" |
| } { |
| execsql { INSERT INTO t1 VALUES($s) } |
| } |
| execsql COMMIT |
| } {} |
| |
| do_catchsql_test 4.2 { |
| UPDATE t1_segdir SET root = X'FFFFFFFFFFFFFFFF'; |
| SELECT rowid FROM t1 WHERE t1 MATCH 'world'; |
| } {1 {database disk image is malformed}} |
| |
| set blob [binary format cca*cca*cca*cca*cca*cca*cca*cca*cca*cca*a* \ |
| 22 120 [string repeat a 120] \ |
| 22 120 [string repeat b 120] \ |
| 22 120 [string repeat c 120] \ |
| 22 120 [string repeat d 120] \ |
| 22 120 [string repeat e 120] \ |
| 22 120 [string repeat f 120] \ |
| 22 120 [string repeat g 120] \ |
| 22 120 [string repeat h 120] \ |
| 22 120 [string repeat i 120] \ |
| 22 120 [string repeat j 120] \ |
| "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" |
| ] |
| |
| do_catchsql_test 4.3 { |
| UPDATE t1_segdir SET root = $blob; |
| SELECT rowid FROM t1 WHERE t1 MATCH 'world'; |
| } {1 {database disk image is malformed}} |
| |
| # Test a special kind of corruption, where the %_stat table contains |
| # an invalid entry. At one point this could lead to a division-by-zero |
| # error in fts4. |
| # |
| do_execsql_test 5.0 { |
| DROP TABLE t1; |
| CREATE VIRTUAL TABLE t1 USING fts4; |
| } |
| do_test 5.1 { |
| db func nn nn |
| execsql BEGIN |
| execsql { INSERT INTO t1 VALUES('one') } |
| execsql { INSERT INTO t1 VALUES('two') } |
| execsql { INSERT INTO t1 VALUES('three') } |
| execsql { INSERT INTO t1 VALUES('four') } |
| execsql COMMIT |
| } {} |
| do_catchsql_test 5.2 { |
| UPDATE t1_stat SET value = X'0000'; |
| SELECT matchinfo(t1, 'nxa') FROM t1 WHERE t1 MATCH 't*'; |
| } {1 {database disk image is malformed}} |
| do_catchsql_test 5.3 { |
| UPDATE t1_stat SET value = NULL; |
| SELECT matchinfo(t1, 'nxa') FROM t1 WHERE t1 MATCH 't*'; |
| } {1 {database disk image is malformed}} |
| |
| |
| finish_test |
| |