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: |
5ba983432069714afebbb2f0ef22d41b |
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
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