diff options
author | dan <Dan Kennedy> | 2023-04-17 11:41:42 +0000 |
---|---|---|
committer | dan <Dan Kennedy> | 2023-04-17 11:41:42 +0000 |
commit | 48824f23cbc68b60f337127578bb2c5c7712b340 (patch) | |
tree | 68e17548e8afeb257dc69cd7bc651b3b0f3e4346 /ext | |
parent | 5c45a9fbaf071975b672a8eed76cd0ac659ca331 (diff) | |
download | sqlite-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.c | 90 | ||||
-rw-r--r-- | ext/fts5/test/fts5secure4.test | 14 |
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. |