/ Check-in [5ba98343]
Login

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

Overview
Comment:Strengthen the new balance_nonroot() code against various corrupt database problems.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 5ba983432069714afebbb2f0ef22d41be52f7a4c
User & Date: drh 2015-06-24 12:07:40
Context
2015-06-24
12:24
Prevent an infinite loop while searching a corrupt freelist. check-in: 4e5424fe user: drh tags: trunk
12:07
Strengthen the new balance_nonroot() code against various corrupt database problems. check-in: 5ba98343 user: drh tags: trunk
10:46
Adjustment to a malloc test so that it accepts a narrow range of values to account for variations in malloc subsystems. check-in: e0195070 user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/btree.c.

  1435   1435     assert( gap<=65536 );
  1436   1436     /* EVIDENCE-OF: R-29356-02391 If the database uses a 65536-byte page size
  1437   1437     ** and the reserved space is zero (the usual value for reserved space)
  1438   1438     ** then the cell content offset of an empty page wants to be 65536.
  1439   1439     ** However, that integer is too large to be stored in a 2-byte unsigned
  1440   1440     ** integer, so a value of 0 is used in its place. */
  1441   1441     top = get2byteNotZero(&data[hdr+5]);
  1442         -  if( gap>top || NEVER((u32)top>pPage->pBt->usableSize) ){
  1443         -    /* The NEVER() is because a oversize "top" value will be blocked from
  1444         -    ** reaching this point by btreeInitPage() or btreeGetUnusedPage() */
         1442  +  if( gap>top || (u32)top>pPage->pBt->usableSize ){
  1445   1443       return SQLITE_CORRUPT_BKPT;
  1446   1444     }
  1447   1445   
  1448   1446     /* If there is enough space between gap and top for one more cell pointer
  1449   1447     ** array entry offset, and if the freelist is not empty, then search the
  1450   1448     ** freelist looking for a free slot big enough to satisfy the request.
  1451   1449     */
................................................................................
  7188   7186             sz = 0;
  7189   7187           }
  7190   7188         }
  7191   7189         szNew[i+1] -= sz;
  7192   7190       }
  7193   7191       if( cntNew[i]>=b.nCell ){
  7194   7192         k = i+1;
  7195         -    }else if( cntNew[i] - (i>0 ? cntNew[i-1] : 0) <= 0 ){
         7193  +    }else if( cntNew[i] <= (i>0 ? cntNew[i-1] : 0) ){
  7196   7194         rc = SQLITE_CORRUPT_BKPT;
  7197   7195         goto balance_cleanup;
  7198   7196       }
  7199   7197     }
  7200   7198   
  7201   7199     /*
  7202   7200     ** The packing computed by the previous block is biased toward the siblings
................................................................................
  7214   7212       int szLeft = szNew[i-1]; /* Size of sibling on the left */
  7215   7213       int r;              /* Index of right-most cell in left sibling */
  7216   7214       int d;              /* Index of first cell to the left of right sibling */
  7217   7215   
  7218   7216       r = cntNew[i-1] - 1;
  7219   7217       d = r + 1 - leafData;
  7220   7218       (void)cachedCellSize(&b, d);
  7221         -    while(1){
         7219  +    do{
  7222   7220         assert( d<nMaxCells );
  7223   7221         assert( r<nMaxCells );
  7224   7222         (void)cachedCellSize(&b, r);
  7225   7223         if( szRight!=0
  7226   7224          && (bBulk || szRight+b.szCell[d]+2 > szLeft-(b.szCell[r]+2)) ){
  7227   7225           break;
  7228   7226         }
  7229   7227         szRight += b.szCell[d] + 2;
  7230   7228         szLeft -= b.szCell[r] + 2;
  7231   7229         cntNew[i-1] = r;
  7232         -      if( cntNew[i-1] <= 0 ){
  7233         -        rc = SQLITE_CORRUPT_BKPT;
  7234         -        goto balance_cleanup;
  7235         -      }
  7236   7230         r--;
  7237   7231         d--;
  7238         -    }
         7232  +    }while( r>=0 );
  7239   7233       szNew[i] = szRight;
  7240   7234       szNew[i-1] = szLeft;
         7235  +    if( cntNew[i-1] <= (i>1 ? cntNew[i-2] : 0) ){
         7236  +      rc = SQLITE_CORRUPT_BKPT;
         7237  +      goto balance_cleanup;
         7238  +    }
  7241   7239     }
  7242   7240   
  7243   7241     /* Sanity check:  For a non-corrupt database file one of the follwing
  7244   7242     ** must be true:
  7245   7243     **    (1) We found one or more cells (cntNew[0])>0), or
  7246   7244     **    (2) pPage is a virtual root page.  A virtual root page is when
  7247   7245     **        the real root page is page 1 and we are the only child of