Index: ext/fts5/fts5_index.c ================================================================== --- ext/fts5/fts5_index.c +++ ext/fts5/fts5_index.c @@ -1845,17 +1845,21 @@ /* Next entry is not on the current page */ while( iOff==0 ){ fts5SegIterNextPage(p, pIter); pLeaf = pIter->pLeaf; if( pLeaf==0 ) break; - if( (iOff = fts5GetU16(&pLeaf->p[0])) ){ + if( (iOff = fts5GetU16(&pLeaf->p[0])) && iOffn ){ iOff += sqlite3Fts5GetVarint(&pLeaf->p[iOff], (u64*)&pIter->iRowid); pIter->iLeafOffset = iOff; } else if( (iOff = fts5GetU16(&pLeaf->p[2])) ){ pIter->iLeafOffset = iOff; bNewTerm = 1; + } + if( iOff>=pLeaf->n ){ + p->rc = FTS5_CORRUPT; + return; } } } /* Check if the iterator is now at EOF. If so, return early. */ @@ -2023,10 +2027,11 @@ ){ int iPg = 1; int h; int bGe = (flags & FTS5INDEX_QUERY_SCAN); int bDlidx = 0; /* True if there is a doclist-index */ + Fts5Data *pLeaf; assert( bGe==0 || (flags & FTS5INDEX_QUERY_DESC)==0 ); assert( pTerm && nTerm ); memset(pIter, 0, sizeof(*pIter)); pIter->pSeg = pSeg; @@ -2061,25 +2066,29 @@ } pIter->iLeafPgno = iPg - 1; fts5SegIterNextPage(p, pIter); - if( pIter->pLeaf ){ + if( (pLeaf = pIter->pLeaf) ){ int res; - pIter->iLeafOffset = fts5GetU16(&pIter->pLeaf->p[2]); - fts5SegIterLoadTerm(p, pIter, 0); - fts5SegIterLoadNPos(p, pIter); - do { - res = fts5BufferCompareBlob(&pIter->term, pTerm, nTerm); - if( res>=0 ) break; - fts5SegIterNext(p, pIter, 0); - }while( pIter->pLeaf && p->rc==SQLITE_OK ); - - if( bGe==0 && res ){ - /* Set iterator to point to EOF */ - fts5DataRelease(pIter->pLeaf); - pIter->pLeaf = 0; + pIter->iLeafOffset = fts5GetU16(&pLeaf->p[2]); + if( pIter->iLeafOffset<4 || pIter->iLeafOffset>=pLeaf->n ){ + p->rc = FTS5_CORRUPT; + }else{ + fts5SegIterLoadTerm(p, pIter, 0); + fts5SegIterLoadNPos(p, pIter); + do { + res = fts5BufferCompareBlob(&pIter->term, pTerm, nTerm); + if( res>=0 ) break; + fts5SegIterNext(p, pIter, 0); + }while( pIter->pLeaf && p->rc==SQLITE_OK ); + + if( bGe==0 && res ){ + /* Set iterator to point to EOF */ + fts5DataRelease(pIter->pLeaf); + pIter->pLeaf = 0; + } } } if( p->rc==SQLITE_OK && bGe==0 ){ pIter->flags |= FTS5_SEGITER_ONETERM; @@ -2523,11 +2532,11 @@ const u8 *pTerm, int nTerm, /* Term to seek to (or NULL/0) */ int iLevel, /* Level to iterate (-1 for all) */ int nSegment, /* Number of segments to merge (iLevel>=0) */ Fts5MultiSegIter **ppOut /* New object */ ){ - int nSeg; /* Number of segment-iters in use */ + int nSeg = 0; /* Number of segment-iters in use */ int iIter = 0; /* */ int iSeg; /* Used to iterate through segments */ Fts5StructureLevel *pLvl; Fts5MultiSegIter *pNew; @@ -4926,12 +4935,16 @@ iKey = FTS5_SEGMENT_ROWID(iSegid, 0, iPrevLeaf); pLeaf = fts5DataRead(p, iKey); if( pLeaf ){ i64 iRowid; int iRowidOff = fts5GetU16(&pLeaf->p[0]); - fts5GetVarint(&pLeaf->p[iRowidOff], (u64*)&iRowid); - if( iRowid!=fts5DlidxIterRowid(pDlidx) ) p->rc = FTS5_CORRUPT; + if( iRowidOff>=pLeaf->n ){ + p->rc = FTS5_CORRUPT; + }else{ + fts5GetVarint(&pLeaf->p[iRowidOff], (u64*)&iRowid); + if( iRowid!=fts5DlidxIterRowid(pDlidx) ) p->rc = FTS5_CORRUPT; + } fts5DataRelease(pLeaf); } } for(iPg=iPrevLeaf+1; iPg<=(iter.iLeaf + iter.nEmpty); iPg++){