1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-07-30 19:03:16 +03:00

Better detection of corruption in the %_stat and %_docsize shadow tables

of FTS3.

FossilOrigin-Name: 1e449687881f4d388e54a0e51bcabba41ab10cf7e596ff65e31e88a23c70d497
This commit is contained in:
drh
2019-11-17 02:41:06 +00:00
parent fd6bf04bba
commit feb5dcf1a6
7 changed files with 109 additions and 19 deletions

View File

@ -1038,11 +1038,15 @@ static int fts3MatchinfoSelectDoctotal(
Fts3Table *pTab,
sqlite3_stmt **ppStmt,
sqlite3_int64 *pnDoc,
const char **paLen
const char **paLen,
const char **ppEnd
){
sqlite3_stmt *pStmt;
const char *a;
const char *pEnd;
sqlite3_int64 nDoc;
int n;
if( !*ppStmt ){
int rc = sqlite3Fts3SelectDoctotal(pTab, ppStmt);
@ -1051,12 +1055,23 @@ static int fts3MatchinfoSelectDoctotal(
pStmt = *ppStmt;
assert( sqlite3_data_count(pStmt)==1 );
n = sqlite3_column_bytes(pStmt, 0);
if( n==0 ){
return FTS_CORRUPT_VTAB;
}
a = sqlite3_column_blob(pStmt, 0);
a += sqlite3Fts3GetVarint(a, &nDoc);
if( nDoc==0 ) return FTS_CORRUPT_VTAB;
if( a==0 ){
return SQLITE_NOMEM;
}
pEnd = a + n;
a += sqlite3Fts3GetVarintBounded(a, pEnd, &nDoc);
if( nDoc==0 || a>pEnd ){
return FTS_CORRUPT_VTAB;
}
*pnDoc = (u32)nDoc;
if( paLen ) *paLen = a;
if( ppEnd ) *ppEnd = pEnd;
return SQLITE_OK;
}
@ -1237,7 +1252,7 @@ static int fts3MatchinfoValues(
case FTS3_MATCHINFO_NDOC:
if( bGlobal ){
sqlite3_int64 nDoc = 0;
rc = fts3MatchinfoSelectDoctotal(pTab, &pSelect, &nDoc, 0);
rc = fts3MatchinfoSelectDoctotal(pTab, &pSelect, &nDoc, 0, 0);
pInfo->aMatchinfo[0] = (u32)nDoc;
}
break;
@ -1246,14 +1261,19 @@ static int fts3MatchinfoValues(
if( bGlobal ){
sqlite3_int64 nDoc; /* Number of rows in table */
const char *a; /* Aggregate column length array */
const char *pEnd; /* First byte past end of length array */
rc = fts3MatchinfoSelectDoctotal(pTab, &pSelect, &nDoc, &a);
rc = fts3MatchinfoSelectDoctotal(pTab, &pSelect, &nDoc, &a, &pEnd);
if( rc==SQLITE_OK ){
int iCol;
for(iCol=0; iCol<pInfo->nCol; iCol++){
u32 iVal;
sqlite3_int64 nToken;
a += sqlite3Fts3GetVarint(a, &nToken);
if( a>pEnd ){
rc = SQLITE_CORRUPT_VTAB;
break;
}
iVal = (u32)(((u32)(nToken&0xffffffff)+nDoc/2)/nDoc);
pInfo->aMatchinfo[iCol] = iVal;
}
@ -1267,9 +1287,14 @@ static int fts3MatchinfoValues(
if( rc==SQLITE_OK ){
int iCol;
const char *a = sqlite3_column_blob(pSelectDocsize, 0);
const char *pEnd = a + sqlite3_column_bytes(pSelectDocsize, 0);
for(iCol=0; iCol<pInfo->nCol; iCol++){
sqlite3_int64 nToken;
a += sqlite3Fts3GetVarint(a, &nToken);
a += sqlite3Fts3GetVarintBounded(a, pEnd, &nToken);
if( a>pEnd ){
rc = SQLITE_CORRUPT_VTAB;
break;
}
pInfo->aMatchinfo[iCol] = (u32)nToken;
}
}
@ -1300,7 +1325,7 @@ static int fts3MatchinfoValues(
if( rc!=SQLITE_OK ) break;
if( bGlobal ){
if( pCsr->pDeferred ){
rc = fts3MatchinfoSelectDoctotal(pTab, &pSelect, &pInfo->nDoc, 0);
rc = fts3MatchinfoSelectDoctotal(pTab, &pSelect, &pInfo->nDoc,0,0);
if( rc!=SQLITE_OK ) break;
}
rc = fts3ExprIterate(pExpr, fts3ExprGlobalHitsCb,(void*)pInfo);