aboutsummaryrefslogtreecommitdiff
path: root/ext
diff options
context:
space:
mode:
authordan <Dan Kennedy>2023-04-17 11:41:42 +0000
committerdan <Dan Kennedy>2023-04-17 11:41:42 +0000
commit48824f23cbc68b60f337127578bb2c5c7712b340 (patch)
tree68e17548e8afeb257dc69cd7bc651b3b0f3e4346 /ext
parent5c45a9fbaf071975b672a8eed76cd0ac659ca331 (diff)
downloadsqlite-48824f23cbc68b60f337127578bb2c5c7712b340.tar.gz
sqlite-48824f23cbc68b60f337127578bb2c5c7712b340.zip
Fix problems handling corrupt records in new fts5 code.
FossilOrigin-Name: 2f63d4a8bac6dc72197df32efd84c148adbc4794943088dff08da57b15dd7900
Diffstat (limited to 'ext')
-rw-r--r--ext/fts5/fts5_index.c90
-rw-r--r--ext/fts5/test/fts5secure4.test14
2 files changed, 62 insertions, 42 deletions
diff --git a/ext/fts5/fts5_index.c b/ext/fts5/fts5_index.c
index b93957bbd..c51d82be9 100644
--- a/ext/fts5/fts5_index.c
+++ b/ext/fts5/fts5_index.c
@@ -4509,16 +4509,16 @@ static void fts5IndexCrisismerge(
){
const int nCrisis = p->pConfig->nCrisisMerge;
Fts5Structure *pStruct = *ppStruct;
- int iLvl = 0;
-
- assert( p->rc!=SQLITE_OK || pStruct->nLevel>0 );
- while( p->rc==SQLITE_OK && pStruct->aLevel[iLvl].nSeg>=nCrisis ){
- fts5IndexMergeLevel(p, &pStruct, iLvl, 0);
- assert( p->rc!=SQLITE_OK || pStruct->nLevel>(iLvl+1) );
- fts5StructurePromote(p, iLvl+1, pStruct);
- iLvl++;
+ if( pStruct && pStruct->nLevel>0 ){
+ int iLvl = 0;
+ while( p->rc==SQLITE_OK && pStruct->aLevel[iLvl].nSeg>=nCrisis ){
+ fts5IndexMergeLevel(p, &pStruct, iLvl, 0);
+ assert( p->rc!=SQLITE_OK || pStruct->nLevel>(iLvl+1) );
+ fts5StructurePromote(p, iLvl+1, pStruct);
+ iLvl++;
+ }
+ *ppStruct = pStruct;
}
- *ppStruct = pStruct;
}
static int fts5IndexReturn(Fts5Index *p){
@@ -4823,17 +4823,21 @@ static void fts5FlushSecureDelete(
nPrefix = MIN(nPrefix, nPrefix2);
nSuffix = (nPrefix2 + nSuffix2) - nPrefix;
- if( iKey!=1 ){
- iOff += sqlite3Fts5PutVarint(&aPg[iOff], nPrefix);
- }
- iOff += sqlite3Fts5PutVarint(&aPg[iOff], nSuffix);
- if( nPrefix2>nPrefix ){
- memcpy(&aPg[iOff], &zTerm[nPrefix], nPrefix2-nPrefix);
- iOff += (nPrefix2-nPrefix);
+ if( (iKeyOff+nSuffix)>iPgIdx || (iNextOff+nSuffix2)>iPgIdx ){
+ p->rc = FTS5_CORRUPT;
+ }else{
+ if( iKey!=1 ){
+ iOff += sqlite3Fts5PutVarint(&aPg[iOff], nPrefix);
+ }
+ iOff += sqlite3Fts5PutVarint(&aPg[iOff], nSuffix);
+ if( nPrefix2>nPrefix ){
+ memcpy(&aPg[iOff], &zTerm[nPrefix], nPrefix2-nPrefix);
+ iOff += (nPrefix2-nPrefix);
+ }
+ memmove(&aPg[iOff], &aPg[iNextOff], nSuffix2);
+ iOff += nSuffix2;
+ iNextOff += nSuffix2;
}
- memmove(&aPg[iOff], &aPg[iNextOff], nSuffix2);
- iOff += nSuffix2;
- iNextOff += nSuffix2;
}
}else if( iStart==4 ){
assert_nc( pSeg->iLeafPgno>pSeg->iTermLeafPgno );
@@ -4878,33 +4882,35 @@ static void fts5FlushSecureDelete(
}
}
- nMove = nPg - iNextOff;
- memmove(&aPg[iOff], &aPg[iNextOff], nMove);
- iPgIdx -= (iNextOff - iOff);
- nPg = iPgIdx;
- fts5PutU16(&aPg[2], iPgIdx);
-
- nShift = iNextOff - iOff;
- for(iIdx=0, iKeyOff=0, iPrevKeyOff=0; iIdx<nIdx; /* no-op */){
- u32 iVal = 0;
- iIdx += fts5GetVarint32(&aIdx[iIdx], iVal);
- iKeyOff += iVal;
- if( iKeyOff!=iDelKeyOff ){
- if( iKeyOff>iOff ){
- iKeyOff -= nShift;
- nShift = 0;
+ if( p->rc==SQLITE_OK ){
+ nMove = nPg - iNextOff;
+ memmove(&aPg[iOff], &aPg[iNextOff], nMove);
+ iPgIdx -= (iNextOff - iOff);
+ nPg = iPgIdx;
+ fts5PutU16(&aPg[2], iPgIdx);
+
+ nShift = iNextOff - iOff;
+ for(iIdx=0, iKeyOff=0, iPrevKeyOff=0; iIdx<nIdx; /* no-op */){
+ u32 iVal = 0;
+ iIdx += fts5GetVarint32(&aIdx[iIdx], iVal);
+ iKeyOff += iVal;
+ if( iKeyOff!=iDelKeyOff ){
+ if( iKeyOff>iOff ){
+ iKeyOff -= nShift;
+ nShift = 0;
+ }
+ nPg += sqlite3Fts5PutVarint(&aPg[nPg], iKeyOff - iPrevKeyOff);
+ iPrevKeyOff = iKeyOff;
}
- nPg += sqlite3Fts5PutVarint(&aPg[nPg], iKeyOff - iPrevKeyOff);
- iPrevKeyOff = iKeyOff;
}
- }
- if( iPgIdx==nPg && nIdx>0 && pSeg->iLeafPgno!=1 ){
- fts5SecureDeleteIdxEntry(p, iSegid, pSeg->iLeafPgno);
- }
+ if( iPgIdx==nPg && nIdx>0 && pSeg->iLeafPgno!=1 ){
+ fts5SecureDeleteIdxEntry(p, iSegid, pSeg->iLeafPgno);
+ }
- assert_nc( nPg>4 || fts5GetU16(aPg)==0 );
- fts5DataWrite(p, FTS5_SEGMENT_ROWID(iSegid, pSeg->iLeafPgno), aPg, nPg);
+ assert_nc( nPg>4 || fts5GetU16(aPg)==0 );
+ fts5DataWrite(p, FTS5_SEGMENT_ROWID(iSegid,pSeg->iLeafPgno), aPg,nPg);
+ }
sqlite3_free(aIdx);
}
}
diff --git a/ext/fts5/test/fts5secure4.test b/ext/fts5/test/fts5secure4.test
index c2fd36995..7cfc5a73e 100644
--- a/ext/fts5/test/fts5secure4.test
+++ b/ext/fts5/test/fts5secure4.test
@@ -69,6 +69,20 @@ do_execsql_test 1.9 {
INSERT INTO y1(y1) VALUES('integrity-check');
}
+do_execsql_test 1.10 {
+ CREATE VIRTUAL TABLE w1 USING fts5(ww, content="");
+ INSERT INTO w1(rowid, ww) VALUES(123, '');
+}
+do_catchsql_test 1.11 {
+ INSERT INTO w1(w1, rowid, ww) VALUES('delete', 123, 'xyz');
+} {1 {database disk image is malformed}}
+do_catchsql_test 1.12 {
+ DROP TABLE w1;
+ CREATE VIRTUAL TABLE w1 USING fts5(ww, content="");
+ INSERT INTO w1(rowid, ww) VALUES(123, '');
+ DELETE FROM w1_data WHERE id>10;
+ INSERT INTO w1(w1, rowid, ww) VALUES('delete', 123, 'xyz');
+} {1 {database disk image is malformed}}
#-------------------------------------------------------------------------
# Test using secure-delete with detail=none or detail=col.