/ Check-in [57deb1b4]
Login

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

Overview
Comment:Size and performance optimization in btreeInitPage() in the freeblock validation step.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 57deb1b412e0c328528f2b4d697e326bfd028dca
User & Date: drh 2016-12-12 01:30:01
Context
2016-12-12
01:53
Updates to the tokenizer for EBCDIC. No changes for standard builds. check-in: 4fc6580f user: drh tags: trunk
01:30
Size and performance optimization in btreeInitPage() in the freeblock validation step. check-in: 57deb1b4 user: drh tags: trunk
00:58
Change the order of comparison for divider cell overflow in balance non-root to avoid a (harmless) reference to an uninitialized variable. check-in: f9f2e23b user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/btree.c.

  1739   1739     assert( pPage->pBt->db!=0 );
  1740   1740     assert( sqlite3_mutex_held(pPage->pBt->mutex) );
  1741   1741     assert( pPage->pgno==sqlite3PagerPagenumber(pPage->pDbPage) );
  1742   1742     assert( pPage == sqlite3PagerGetExtra(pPage->pDbPage) );
  1743   1743     assert( pPage->aData == sqlite3PagerGetData(pPage->pDbPage) );
  1744   1744   
  1745   1745     if( !pPage->isInit ){
  1746         -    u16 pc;            /* Address of a freeblock within pPage->aData[] */
         1746  +    u32 pc;            /* Address of a freeblock within pPage->aData[] */
  1747   1747       u8 hdr;            /* Offset to beginning of page header */
  1748   1748       u8 *data;          /* Equal to pPage->aData */
  1749   1749       BtShared *pBt;        /* The main btree structure */
  1750   1750       int usableSize;    /* Amount of usable space on each page */
  1751   1751       u16 cellOffset;    /* Offset from start of page to first cell pointer */
  1752   1752       int nFree;         /* Number of unused bytes on the page */
  1753   1753       int top;           /* First byte of the cell content area */
................................................................................
  1819   1819   
  1820   1820       /* Compute the total free space on the page
  1821   1821       ** EVIDENCE-OF: R-23588-34450 The two-byte integer at offset 1 gives the
  1822   1822       ** start of the first freeblock on the page, or is zero if there are no
  1823   1823       ** freeblocks. */
  1824   1824       pc = get2byte(&data[hdr+1]);
  1825   1825       nFree = data[hdr+7] + top;  /* Init nFree to non-freeblock free space */
  1826         -    while( pc>0 ){
  1827         -      u16 next, size;
  1828         -      if( pc<iCellFirst || pc>iCellLast ){
         1826  +    if( pc>0 ){
         1827  +      u32 next, size;
         1828  +      if( pc<iCellFirst ){
  1829   1829           /* EVIDENCE-OF: R-55530-52930 In a well-formed b-tree page, there will
  1830   1830           ** always be at least one cell before the first freeblock.
  1831         -        **
  1832         -        ** Or, the freeblock is off the end of the page
  1833   1831           */
  1834   1832           return SQLITE_CORRUPT_BKPT; 
  1835   1833         }
  1836         -      next = get2byte(&data[pc]);
  1837         -      size = get2byte(&data[pc+2]);
  1838         -      if( (next>0 && next<=pc+size+3) || pc+size>usableSize ){
  1839         -        /* Free blocks must be in ascending order. And the last byte of
  1840         -        ** the free-block must lie on the database page.  */
  1841         -        return SQLITE_CORRUPT_BKPT; 
         1834  +      while( 1 ){
         1835  +        if( pc>iCellLast ){
         1836  +          return SQLITE_CORRUPT_BKPT; /* Freeblock off the end of the page */
         1837  +        }
         1838  +        next = get2byte(&data[pc]);
         1839  +        size = get2byte(&data[pc+2]);
         1840  +        nFree = nFree + size;
         1841  +        if( next<=pc+size+3 ) break;
         1842  +        pc = next;
  1842   1843         }
  1843         -      nFree = nFree + size;
  1844         -      pc = next;
         1844  +      if( next>0 ){
         1845  +        return SQLITE_CORRUPT_BKPT;  /* Freeblock not in ascending order */
         1846  +      }
         1847  +      if( pc+size>usableSize ){
         1848  +        return SQLITE_CORRUPT_BKPT;  /* Last freeblock extends past page end */
         1849  +      }
  1845   1850       }
  1846   1851   
  1847   1852       /* At this point, nFree contains the sum of the offset to the start
  1848   1853       ** of the cell-content area plus the number of free bytes within
  1849   1854       ** the cell-content area. If this is greater than the usable-size
  1850   1855       ** of the page, then the page must be corrupted. This check also
  1851   1856       ** serves to verify that the offset to the start of the cell-content