/ Check-in [997b6511]
Login

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

Overview
Comment:Add extra tests for database corruption inside the defragmentPage() routine, as dbfuzz2 has found ways for corruption to leak into that point. Add test cases in fuzzdata7.db.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 997b65117f8c12dba5fb85434fde9765cdb0d2a49cc3e31979abba3e21350086
User & Date: drh 2018-12-13 21:11:22
Context
2018-12-13
21:52
dbfuzz2 found a NEVER() that is sometimes true. check-in: 1201615c user: drh tags: trunk
21:11
Add extra tests for database corruption inside the defragmentPage() routine, as dbfuzz2 has found ways for corruption to leak into that point. Add test cases in fuzzdata7.db. check-in: 997b6511 user: drh tags: trunk
21:05
Fix a problem in sqlite3BtreeDelete() in which deleting an entry from a corrupt database can leave a btree page with zero cells. check-in: 682053d1 user: drh tags: trunk
15:52
Merge the dbtotxt enhancement from trunk. Closed-Leaf check-in: b386fce9 user: drh tags: dbfuzz2-cases
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/btree.c.

  1408   1408     /* This block handles pages with two or fewer free blocks and nMaxFrag
  1409   1409     ** or fewer fragmented bytes. In this case it is faster to move the
  1410   1410     ** two (or one) blocks of cells using memmove() and add the required
  1411   1411     ** offsets to each pointer in the cell-pointer array than it is to 
  1412   1412     ** reconstruct the entire page.  */
  1413   1413     if( (int)data[hdr+7]<=nMaxFrag ){
  1414   1414       int iFree = get2byte(&data[hdr+1]);
         1415  +
         1416  +    /* If the initial freeblock offset were out of bounds, that would
         1417  +    ** have been detected by btreeInitPage() when it was computing the
         1418  +    ** number of free bytes on the page. */
         1419  +    assert( iFree<=usableSize-4 );
  1415   1420       if( iFree ){
  1416   1421         int iFree2 = get2byte(&data[iFree]);
  1417         -
  1418         -      /* pageFindSlot() has already verified that free blocks are sorted
  1419         -      ** in order of offset within the page, and that no block extends
  1420         -      ** past the end of the page. Provided the two free slots do not 
  1421         -      ** overlap, this guarantees that the memmove() calls below will not
  1422         -      ** overwrite the usableSize byte buffer, even if the database page
  1423         -      ** is corrupt.  */
  1424         -      assert( iFree2==0 || iFree2>iFree );
  1425         -      assert( iFree+get2byte(&data[iFree+2]) <= usableSize );
  1426         -      assert( iFree2==0 || iFree2+get2byte(&data[iFree2+2]) <= usableSize );
  1427         -
         1422  +      if( iFree2>usableSize-4 ) return SQLITE_CORRUPT_PAGE(pPage);
  1428   1423         if( 0==iFree2 || (data[iFree2]==0 && data[iFree2+1]==0) ){
  1429   1424           u8 *pEnd = &data[cellOffset + nCell*2];
  1430   1425           u8 *pAddr;
  1431   1426           int sz2 = 0;
  1432   1427           int sz = get2byte(&data[iFree+2]);
  1433   1428           int top = get2byte(&data[hdr+5]);
  1434   1429           if( top>=iFree ){
  1435   1430             return SQLITE_CORRUPT_PAGE(pPage);
  1436   1431           }
  1437   1432           if( iFree2 ){
  1438         -          assert( iFree+sz<=iFree2 ); /* Verified by pageFindSlot() */
         1433  +          if( iFree+sz>iFree2 ) return SQLITE_CORRUPT_PAGE(pPage);
  1439   1434             sz2 = get2byte(&data[iFree2+2]);
  1440         -          assert( iFree+sz+sz2+iFree2-(iFree+sz) <= usableSize );
         1435  +          if( iFree2+sz2 > usableSize ) return SQLITE_CORRUPT_PAGE(pPage);
  1441   1436             memmove(&data[iFree+sz+sz2], &data[iFree+sz], iFree2-(iFree+sz));
  1442   1437             sz += sz2;
  1443   1438           }
  1444   1439           cbrk = top+sz;
  1445   1440           assert( cbrk+(iFree-top) <= usableSize );
  1446   1441           memmove(&data[cbrk], &data[top], iFree-top);
  1447   1442           for(pAddr=&data[cellOffset]; pAddr<pEnd; pAddr+=2){

Changes to test/fuzzdata7.db.

cannot compute difference between binary files