SQLite

Check-in [7e9e1b6123]
Login

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

Overview
Comment:A different approach to preventing buffer overreads when comparing a vector of values with a corrupt index record that spans at least one overflow page.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | avoid-buffer-overread
Files: files | file ages | folders
SHA1: 7e9e1b6123bc455dd7d1c894b6154ccd27acec18
User & Date: dan 2015-05-27 14:21:05.738
Context
2015-05-27
15:42
A different approach to preventing buffer overreads when comparing a vector of values with a corrupt index record that spans at least one overflow page. (check-in: 95eaa49f4e user: drh tags: trunk)
14:21
A different approach to preventing buffer overreads when comparing a vector of values with a corrupt index record that spans at least one overflow page. (Closed-Leaf check-in: 7e9e1b6123 user: dan tags: avoid-buffer-overread)
2015-05-26
20:31
Avoid a buffer overread when comparing against a corrupt record that spans at least one overflow page. (check-in: 62a5b3633a user: dan tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/btree.c.
4947
4948
4949
4950
4951
4952
4953
4954



4955
4956
4957
4958
4959
4960
4961





4962
4963
4964
4965
4966
4967
4968
4969
4970
4971
4972
4973
4974
4975
4976
          ** fits entirely on the main b-tree page.  */
          testcase( pCell+nCell+2==pPage->aDataEnd );
          c = xRecordCompare(nCell, (void*)&pCell[2], pIdxKey);
        }else{
          /* The record flows over onto one or more overflow pages. In
          ** this case the whole cell needs to be parsed, a buffer allocated
          ** and accessPayload() used to retrieve the record into the
          ** buffer before VdbeRecordCompare() can be called. An extra



          ** byte of zeroed padding is allocated at the end of the buffer,
          ** as this stops the record-compare routines from reading past
          ** the end of the buffer if the record is corrupt.  */
          void *pCellKey;
          u8 * const pCellBody = pCell - pPage->childPtrSize;
          btreeParseCellPtr(pPage, pCellBody, &pCur->info);
          nCell = (int)pCur->info.nKey;





          pCellKey = sqlite3Malloc( nCell+1 );
          if( pCellKey==0 ){
            rc = SQLITE_NOMEM;
            goto moveto_finish;
          }
          pCur->aiIdx[pCur->iPage] = (u16)idx;
          rc = accessPayload(pCur, 0, nCell, (unsigned char*)pCellKey, 2);
          ((unsigned char *)pCellKey)[nCell] = 0;
          if( rc ){
            sqlite3_free(pCellKey);
            goto moveto_finish;
          }
          c = xRecordCompare(nCell, pCellKey, pIdxKey);
          sqlite3_free(pCellKey);
        }







|
>
>
>
|
<
|




>
>
>
>
>
|






<







4947
4948
4949
4950
4951
4952
4953
4954
4955
4956
4957
4958

4959
4960
4961
4962
4963
4964
4965
4966
4967
4968
4969
4970
4971
4972
4973
4974
4975

4976
4977
4978
4979
4980
4981
4982
          ** fits entirely on the main b-tree page.  */
          testcase( pCell+nCell+2==pPage->aDataEnd );
          c = xRecordCompare(nCell, (void*)&pCell[2], pIdxKey);
        }else{
          /* The record flows over onto one or more overflow pages. In
          ** this case the whole cell needs to be parsed, a buffer allocated
          ** and accessPayload() used to retrieve the record into the
          ** buffer before VdbeRecordCompare() can be called. 
          **
          ** If the record is corrupt, the xRecordCompare routine may read
          ** up to two varints past the end of the buffer. An extra 18 
          ** bytes of padding is allocated at the end of the buffer in

          ** case this happens.  */
          void *pCellKey;
          u8 * const pCellBody = pCell - pPage->childPtrSize;
          btreeParseCellPtr(pPage, pCellBody, &pCur->info);
          nCell = (int)pCur->info.nKey;
          testcase( nCell<0 );
          if( nCell<2 ){
            rc = SQLITE_CORRUPT_BKPT;
            goto moveto_finish;
          }
          pCellKey = sqlite3Malloc( nCell+18 );
          if( pCellKey==0 ){
            rc = SQLITE_NOMEM;
            goto moveto_finish;
          }
          pCur->aiIdx[pCur->iPage] = (u16)idx;
          rc = accessPayload(pCur, 0, nCell, (unsigned char*)pCellKey, 2);

          if( rc ){
            sqlite3_free(pCellKey);
            goto moveto_finish;
          }
          c = xRecordCompare(nCell, pCellKey, pIdxKey);
          sqlite3_free(pCellKey);
        }