/ Check-in [360c57bb]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Fix some cases in the fts5 code where a corrupt database could cause a buffer overread.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | fts5
Files: files | file ages | folders
SHA1: 360c57bbb8bad6cc84af140f61e0282fa06462b4
User & Date: dan 2015-06-26 18:50:29
Context
2015-06-26
19:33
Merge latest trunk changes with this branch. check-in: 2a1af0f2 user: dan tags: fts5
18:50
Fix some cases in the fts5 code where a corrupt database could cause a buffer overread. check-in: 360c57bb user: dan tags: fts5
17:10
Merge changes to get FTS5 working with MSVC. check-in: 954231d2 user: mistachkin tags: fts5
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to ext/fts5/fts5_index.c.

  1843   1843         }else{
  1844   1844           iOff = 0;
  1845   1845           /* Next entry is not on the current page */
  1846   1846           while( iOff==0 ){
  1847   1847             fts5SegIterNextPage(p, pIter);
  1848   1848             pLeaf = pIter->pLeaf;
  1849   1849             if( pLeaf==0 ) break;
  1850         -          if( (iOff = fts5GetU16(&pLeaf->p[0])) ){
         1850  +          if( (iOff = fts5GetU16(&pLeaf->p[0])) && iOff<pLeaf->n ){
  1851   1851               iOff += sqlite3Fts5GetVarint(&pLeaf->p[iOff], (u64*)&pIter->iRowid);
  1852   1852               pIter->iLeafOffset = iOff;
  1853   1853             }
  1854   1854             else if( (iOff = fts5GetU16(&pLeaf->p[2])) ){
  1855   1855               pIter->iLeafOffset = iOff;
  1856   1856               bNewTerm = 1;
         1857  +          }
         1858  +          if( iOff>=pLeaf->n ){
         1859  +            p->rc = FTS5_CORRUPT;
         1860  +            return;
  1857   1861             }
  1858   1862           }
  1859   1863         }
  1860   1864   
  1861   1865         /* Check if the iterator is now at EOF. If so, return early. */
  1862   1866         if( pIter->pLeaf ){
  1863   1867           if( bNewTerm ){
................................................................................
  2021   2025     Fts5StructureSegment *pSeg,     /* Description of segment */
  2022   2026     Fts5SegIter *pIter              /* Object to populate */
  2023   2027   ){
  2024   2028     int iPg = 1;
  2025   2029     int h;
  2026   2030     int bGe = (flags & FTS5INDEX_QUERY_SCAN);
  2027   2031     int bDlidx = 0;                 /* True if there is a doclist-index */
         2032  +  Fts5Data *pLeaf;
  2028   2033   
  2029   2034     assert( bGe==0 || (flags & FTS5INDEX_QUERY_DESC)==0 );
  2030   2035     assert( pTerm && nTerm );
  2031   2036     memset(pIter, 0, sizeof(*pIter));
  2032   2037     pIter->pSeg = pSeg;
  2033   2038   
  2034   2039     /* This block sets stack variable iPg to the leaf page number that may
................................................................................
  2059   2064       iPg = pSeg->pgnoFirst;
  2060   2065       bDlidx = 0;
  2061   2066     }
  2062   2067   
  2063   2068     pIter->iLeafPgno = iPg - 1;
  2064   2069     fts5SegIterNextPage(p, pIter);
  2065   2070   
  2066         -  if( pIter->pLeaf ){
         2071  +  if( (pLeaf = pIter->pLeaf) ){
  2067   2072       int res;
  2068         -    pIter->iLeafOffset = fts5GetU16(&pIter->pLeaf->p[2]);
  2069         -    fts5SegIterLoadTerm(p, pIter, 0);
  2070         -    fts5SegIterLoadNPos(p, pIter);
  2071         -    do {
  2072         -      res = fts5BufferCompareBlob(&pIter->term, pTerm, nTerm);
  2073         -      if( res>=0 ) break;
  2074         -      fts5SegIterNext(p, pIter, 0);
  2075         -    }while( pIter->pLeaf && p->rc==SQLITE_OK );
         2073  +    pIter->iLeafOffset = fts5GetU16(&pLeaf->p[2]);
         2074  +    if( pIter->iLeafOffset<4 || pIter->iLeafOffset>=pLeaf->n ){
         2075  +      p->rc = FTS5_CORRUPT;
         2076  +    }else{
         2077  +      fts5SegIterLoadTerm(p, pIter, 0);
         2078  +      fts5SegIterLoadNPos(p, pIter);
         2079  +      do {
         2080  +        res = fts5BufferCompareBlob(&pIter->term, pTerm, nTerm);
         2081  +        if( res>=0 ) break;
         2082  +        fts5SegIterNext(p, pIter, 0);
         2083  +      }while( pIter->pLeaf && p->rc==SQLITE_OK );
  2076   2084   
  2077         -    if( bGe==0 && res ){
  2078         -      /* Set iterator to point to EOF */
  2079         -      fts5DataRelease(pIter->pLeaf);
  2080         -      pIter->pLeaf = 0;
         2085  +      if( bGe==0 && res ){
         2086  +        /* Set iterator to point to EOF */
         2087  +        fts5DataRelease(pIter->pLeaf);
         2088  +        pIter->pLeaf = 0;
         2089  +      }
  2081   2090       }
  2082   2091     }
  2083   2092   
  2084   2093     if( p->rc==SQLITE_OK && bGe==0 ){
  2085   2094       pIter->flags |= FTS5_SEGITER_ONETERM;
  2086   2095       if( pIter->pLeaf ){
  2087   2096         if( flags & FTS5INDEX_QUERY_DESC ){
................................................................................
  2521   2530     int bSkipEmpty,                 /* True to ignore delete-keys */
  2522   2531     int flags,                      /* FTS5INDEX_QUERY_XXX flags */
  2523   2532     const u8 *pTerm, int nTerm,     /* Term to seek to (or NULL/0) */
  2524   2533     int iLevel,                     /* Level to iterate (-1 for all) */
  2525   2534     int nSegment,                   /* Number of segments to merge (iLevel>=0) */
  2526   2535     Fts5MultiSegIter **ppOut        /* New object */
  2527   2536   ){
  2528         -  int nSeg;                       /* Number of segment-iters in use */
         2537  +  int nSeg = 0;                   /* Number of segment-iters in use */
  2529   2538     int iIter = 0;                  /* */
  2530   2539     int iSeg;                       /* Used to iterate through segments */
  2531   2540     Fts5StructureLevel *pLvl;
  2532   2541     Fts5MultiSegIter *pNew;
  2533   2542   
  2534   2543     assert( (pTerm==0 && nTerm==0) || iLevel<0 );
  2535   2544   
................................................................................
  4924   4933           /* Check that the leaf page indicated by the iterator really does
  4925   4934           ** contain the rowid suggested by the same. */
  4926   4935           iKey = FTS5_SEGMENT_ROWID(iSegid, 0, iPrevLeaf);
  4927   4936           pLeaf = fts5DataRead(p, iKey);
  4928   4937           if( pLeaf ){
  4929   4938             i64 iRowid;
  4930   4939             int iRowidOff = fts5GetU16(&pLeaf->p[0]);
  4931         -          fts5GetVarint(&pLeaf->p[iRowidOff], (u64*)&iRowid);
  4932         -          if( iRowid!=fts5DlidxIterRowid(pDlidx) ) p->rc = FTS5_CORRUPT;
         4940  +          if( iRowidOff>=pLeaf->n ){
         4941  +            p->rc = FTS5_CORRUPT;
         4942  +          }else{
         4943  +            fts5GetVarint(&pLeaf->p[iRowidOff], (u64*)&iRowid);
         4944  +            if( iRowid!=fts5DlidxIterRowid(pDlidx) ) p->rc = FTS5_CORRUPT;
         4945  +          }
  4933   4946             fts5DataRelease(pLeaf);
  4934   4947           }
  4935   4948         }
  4936   4949   
  4937   4950         for(iPg=iPrevLeaf+1; iPg<=(iter.iLeaf + iter.nEmpty); iPg++){
  4938   4951           iKey = FTS5_SEGMENT_ROWID(iSegid, 0, iPg);
  4939   4952           pLeaf = fts5DataRead(p, iKey);