Fix a buffer overread in fts3 that can occur if the database is corrupt.

FossilOrigin-Name: 84194c4195d7144ff7f9cedcdc74fdd908f3bfcd
This commit is contained in:
dan 2010-10-27 16:52:27 +00:00
parent 8c30711208
commit 8aaa252d8c
5 changed files with 78 additions and 17 deletions

View File

@ -916,9 +916,19 @@ static int fts3SegReaderNext(Fts3Table *p, Fts3SegReader *pReader){
pReader->nTerm = nPrefix+nSuffix;
pNext += nSuffix;
pNext += sqlite3Fts3GetVarint32(pNext, &pReader->nDoclist);
assert( pNext<&pReader->aNode[pReader->nNode] );
pReader->aDoclist = pNext;
pReader->pOffsetList = 0;
/* Check that the doclist does not appear to extend past the end of the
** b-tree node. And that the final byte of the doclist is either an 0x00
** or 0x01. If either of these statements is untrue, then the data structure
** is corrupt.
*/
if( &pReader->aDoclist[pReader->nDoclist]>&pReader->aNode[pReader->nNode]
|| (pReader->aDoclist[pReader->nDoclist-1]&0xFE)!=0
){
return SQLITE_CORRUPT;
}
return SQLITE_OK;
}

View File

@ -1,5 +1,5 @@
C In\sfts4,\sstore\sthe\stotal\snumber\sof\sbytes\sof\sfor\sall\srecords\sin\sthe\stable\sin\sthe\s%_stat\stable.
D 2010-10-27T10:55:54
C Fix\sa\sbuffer\soverread\sin\sfts3\sthat\scan\soccur\sif\sthe\sdatabase\sis\scorrupt.
D 2010-10-27T16:52:27
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in 2c8cefd962eca0147132c7cf9eaa4bb24c656f3f
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@ -73,7 +73,7 @@ F ext/fts3/fts3_snippet.c 300c12b7f0a2a6ae0491bb2d00e2d5ff9c28f685
F ext/fts3/fts3_tokenizer.c b4f2d01c24573852755bc92864816785dae39318
F ext/fts3/fts3_tokenizer.h 13ffd9fcb397fec32a05ef5cd9e0fa659bf3dbd3
F ext/fts3/fts3_tokenizer1.c 6e5cbaa588924ac578263a598e4fb9f5c9bb179d
F ext/fts3/fts3_write.c 943216b144447a1fbadef373cbd2b7eb3fd17a65
F ext/fts3/fts3_write.c a9189fa8719158b695f33e1490f56256308e2525
F ext/fts3/fts3speed.tcl b54caf6a18d38174f1a6e84219950d85e98bb1e9
F ext/fts3/mkfts3amal.tcl 252ecb7fe6467854f2aa237bf2c390b74e71f100
F ext/icu/README.txt bf8461d8cdc6b8f514c080e4e10dc3b2bbdfefa9
@ -431,10 +431,11 @@ F test/fts3ao.test b83f99f70e9eec85f27d75801a974b3f820e01f9
F test/fts3atoken.test 25c2070e1e8755d414bf9c8200427b277a9f99fa
F test/fts3b.test e93bbb653e52afde110ad53bbd793f14fe7a8984
F test/fts3c.test fc723a9cf10b397fdfc2b32e73c53c8b1ec02958
F test/fts3corrupt.test 8d2ef629be9eff997db32ec3f0f7b53b0c61d086
F test/fts3cov.test e0fb00d8b715ddae4a94c305992dfc3ef70353d7
F test/fts3d.test 95fb3c862cbc4297c93fceb9a635543744e9ef52
F test/fts3defer.test eab4f24c8402fb4e1e6aad44bcdfbe5bf42160b2
F test/fts3defer2.test 1a9f213ca79509b60d81460febc7e4e5b64af95c
F test/fts3defer2.test d3c7db6584aab06a2781b8de58747c33b23cb19c
F test/fts3e.test 1f6c6ac9cc8b772ca256e6b22aaeed50c9350851
F test/fts3expr.test 5e745b2b6348499d9ef8d59015de3182072c564c
F test/fts3expr2.test 18da930352e5693eaa163a3eacf96233b7290d1a
@ -879,7 +880,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
P 97c6b2616ddcce2337778c6ee88a973cc4fe999d
R 8864817f6f3963775cfdd60519bb3822
P 941647d121ac60e2eabc998cfe79b157fb918d7e
R 4228d3b4dbf28842cbc96083972fc4a8
U dan
Z 890501f0776b5167d933a1fceff6796c
Z 82331704b60d2b02d0a92d3a85b091f9

View File

@ -1 +1 @@
941647d121ac60e2eabc998cfe79b157fb918d7e
84194c4195d7144ff7f9cedcdc74fdd908f3bfcd

43
test/fts3corrupt.test Normal file
View File

@ -0,0 +1,43 @@
# 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
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}}
finish_test

View File

@ -36,15 +36,16 @@ do_execsql_test 1.1.2 "INSERT INTO t1 VALUES('[string repeat {a } 20000]')"
do_execsql_test 1.1.3 "INSERT INTO t1 VALUES('[string repeat {z } 20000]')"
do_execsql_test 1.1.4 {
INSERT INTO t1 VALUES('a b c d e f a x y');
INSERT INTO t1 VALUES('');
INSERT INTO t1 VALUES('');
INSERT INTO t1 VALUES('');
INSERT INTO t1 VALUES('');
INSERT INTO t1 VALUES('');
INSERT INTO t1(t1) VALUES('optimize');
UPDATE t1_segments
SET block = zeroblob(length(block))
WHERE length(block)>10000;
}
do_execsql_test 1.1.4 {
SELECT count(*) FROM t1_segments WHERE length(block)>10000;
UPDATE t1_segments
SET block = zeroblob(length(block)) WHERE length(block)>10000;
UPDATE t1_segments SET block = zeroblob(length(block)) WHERE length(block)>10000;
} {2}
do_execsql_test 1.2.1 {
@ -57,7 +58,7 @@ do_execsql_test 1.2.2 {
} [list \
{a b c d [e] [f] [a] x y} \
{0 1 8 1 0 0 10 1 0 2 12 1} \
[list 3 1 1 1 1 1 3 3 1 3 3 3 13336 9]
[list 3 1 1 1 1 1 8 8 1 8 8 8 5001 9]
]
do_execsql_test 1.2.3 {
@ -66,7 +67,7 @@ do_execsql_test 1.2.3 {
} [list \
{[a] b c d [e] [f] [a] x y} \
{0 2 0 1 0 1 8 1 0 0 10 1 0 2 12 1} \
[list 3 1 1 1 1 1 3 3 2 3 3 3 13336 9]
[list 3 1 1 1 1 1 8 8 2 8 8 8 5001 9]
]
do_execsql_test 1.3.1 { DROP TABLE t1 }
@ -104,6 +105,12 @@ do_execsql_test 2.3.1 {
INSERT INTO t3 VALUES('x b c d e f');
INSERT INTO t3 VALUES('d e f a b c');
INSERT INTO t3 VALUES('b c d e f');
INSERT INTO t3 VALUES('');
INSERT INTO t3 VALUES('');
INSERT INTO t3 VALUES('');
INSERT INTO t3 VALUES('');
INSERT INTO t3 VALUES('');
INSERT INTO t3 VALUES('');
}
do_execsql_test 2.3.2 "
INSERT INTO t3 VALUES('f e d c b [string repeat {a } 10000]')
@ -118,7 +125,7 @@ foreach {tn sql} {
execsql $sql
do_execsql_test 2.4.$tn {
SELECT docid, mit(matchinfo(t3)) FROM t3 WHERE t3 MATCH '"a b c"';
} {1 {1 1 1 4 4 5 2006 6} 3 {1 1 1 4 4 5 2006 6}}
} {1 {1 1 1 4 4 11 912 6} 3 {1 1 1 4 4 11 912 6}}
}