From 414660066ee2f1670a9f09a11ab41533015b2f3a Mon Sep 17 00:00:00 2001 From: Ondrej Dubaj Date: Thu, 2 Jan 2020 15:04:42 +0100 Subject: [PATCH] More improvements to shadow table corruption detection in FTS3. --- ext/fts3/fts3.c | 4 ++++ ext/fts3/fts3Int.h | 10 ++++++++++ ext/fts3/fts3_write.c | 14 +++++++++++--- 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/ext/fts3/fts3.c b/ext/fts3/fts3.c index f6fb931..caa742f 100644 --- a/ext/fts3/fts3.c +++ b/ext/fts3/fts3.c @@ -1460,6 +1460,10 @@ static int fts3InitVtab( fts3DatabasePageSize(&rc, p); p->nNodeSize = p->nPgsz-35; +#if defined(SQLITE_DEBUG)||defined(SQLITE_TEST) + p->nMergeCount = FTS3_MERGE_COUNT; +#endif + /* Declare the table schema to SQLite. */ fts3DeclareVtab(&rc, p); diff --git a/ext/fts3/fts3Int.h b/ext/fts3/fts3Int.h index 077bad7..12392c0 100644 --- a/ext/fts3/fts3Int.h +++ b/ext/fts3/fts3Int.h @@ -287,9 +287,19 @@ struct Fts3Table { /* True to disable the incremental doclist optimization. This is controled ** by special insert command 'test-no-incr-doclist'. */ int bNoIncrDoclist; + + /* Number of segments in a level */ + int nMergeCount; #endif }; +/* Macro to find the number of segments to merge */ +#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST) +# define MergeCount(P) ((P)->nMergeCount) +#else +# define MergeCount(P) FTS3_MERGE_COUNT +#endif + /* ** When the core wants to read from the virtual table, it creates a ** virtual table cursor (an instance of the following structure) using diff --git a/ext/fts3/fts3_write.c b/ext/fts3/fts3_write.c index 8fc6589..e4b9640 100644 --- a/ext/fts3/fts3_write.c +++ b/ext/fts3/fts3_write.c @@ -1152,7 +1152,7 @@ static int fts3AllocateSegdirIdx( ** segment and allocate (newly freed) index 0 at level iLevel. Otherwise, ** if iNext is less than FTS3_MERGE_COUNT, allocate index iNext. */ - if( iNext>=FTS3_MERGE_COUNT ){ + if( iNext>=MergeCount(p) ){ fts3LogMerge(16, getAbsoluteLevel(p, iLangid, iIndex, iLevel)); rc = fts3SegmentMerge(p, iLangid, iIndex, iLevel); *piIdx = 0; @@ -4249,6 +4249,10 @@ static int fts3IncrmergeLoad( int i; int nHeight = (int)aRoot[0]; NodeWriter *pNode; + if( nHeight<1 || nHeight>FTS_MAX_APPENDABLE_HEIGHT ){ + sqlite3_reset(pSelect); + return FTS_CORRUPT_VTAB; + } pWriter->nLeafEst = (int)((iEnd - iStart) + 1)/FTS_MAX_APPENDABLE_HEIGHT; pWriter->iStart = iStart; @@ -4997,7 +5001,7 @@ static int fts3DoIncrmerge( const char *zParam /* Nul-terminated string containing "A,B" */ ){ int rc; - int nMin = (FTS3_MERGE_COUNT / 2); + int nMin = (MergeCount(p) / 2); int nMerge = 0; const char *z = zParam; @@ -5042,7 +5046,7 @@ static int fts3DoAutoincrmerge( int rc = SQLITE_OK; sqlite3_stmt *pStmt = 0; p->nAutoincrmerge = fts3Getint(&zParam); - if( p->nAutoincrmerge==1 || p->nAutoincrmerge>FTS3_MERGE_COUNT ){ + if( p->nAutoincrmerge==1 || p->nAutoincrmerge>MergeCount(p) ){ p->nAutoincrmerge = 8; } if( !p->bHasStat ){ @@ -5326,6 +5330,10 @@ static int fts3SpecialInsert(Fts3Table *p, sqlite3_value *pVal){ }else if( nVal>21 && 0==sqlite3_strnicmp(zVal, "test-no-incr-doclist=", 21) ){ p->bNoIncrDoclist = atoi(&zVal[21]); rc = SQLITE_OK; + }else if( nVal>11 && 0==sqlite3_strnicmp(zVal,"mergecount=",11) ){ + int v = atoi(&zVal[11]); + if( v>=4 && v<=FTS3_MERGE_COUNT && (v&1)==0 ) p->nMergeCount = v; + rc = SQLITE_OK; #endif }else{ rc = SQLITE_ERROR; -- 2.19.1