/ Check-in [2d58c0af]
Login

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

Overview
Comment:Change some assert()s that could fail if the database is corrupt to return SQLITE_CORRUPT instead. (CVS 2223)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 2d58c0afa769d49c8819ea4982bc20ae39516f97
User & Date: danielk1977 2005-01-17 02:12:19
Context
2005-01-17
03:40
Fix a memory leak that occurs as a result of an IO error. (CVS 2224) check-in: 1edfdcbf user: danielk1977 tags: trunk
02:12
Change some assert()s that could fail if the database is corrupt to return SQLITE_CORRUPT instead. (CVS 2223) check-in: 2d58c0af user: danielk1977 tags: trunk
01:33
Have sqlite3pager_get() return SQLITE_CORRUPT for a page number greater than 2^31. (CVS 2222) check-in: feb49d10 user: danielk1977 tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/btree.c.

5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
...
478
479
480
481
482
483
484
485


486
487
488
489
490
491
492
...
524
525
526
527
528
529
530

531
532
533
534
535
536
537
....
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
....
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656


1657
1658
1659
1660
1661
1662
1663
....
1679
1680
1681
1682
1683
1684
1685
1686
1687


1688
1689
1690
1691
1692

1693
1694
1695
1696
1697
1698
1699
....
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
....
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764



1765
1766
1767
1768
1769
1770
1771
....
1789
1790
1791
1792
1793
1794
1795
1796


1797
1798
1799
1800
1801
1802
1803
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** $Id: btree.c,v 1.239 2005/01/17 01:33:14 danielk1977 Exp $
**
** This file implements a external (disk-based) database using BTrees.
** For a detailed discussion of BTrees, refer to
**
**     Donald E. Knuth, THE ART OF COMPUTER PROGRAMMING, Volume 3:
**     "Sorting And Searching", pages 473-480. Addison-Wesley
**     Publishing Company, Reading, Massachusetts.
................................................................................
static int ptrmapPut(Btree *pBt, Pgno key, u8 eType, Pgno parent){
  u8 *pPtrmap;    /* The pointer map page */
  Pgno iPtrmap;   /* The pointer map page number */
  int offset;     /* Offset in pointer map page */
  int rc;

  assert( pBt->autoVacuum );
  assert( key!=0 );


  iPtrmap = PTRMAP_PAGENO(pBt->usableSize, key);
  rc = sqlite3pager_get(pBt->pPager, iPtrmap, (void **)&pPtrmap);
  if( rc!=SQLITE_OK ){
    return rc;
  }
  offset = PTRMAP_PTROFFSET(pBt->usableSize, key);

................................................................................
  }

  offset = PTRMAP_PTROFFSET(pBt->usableSize, key);
  if( pEType ) *pEType = pPtrmap[offset];
  if( pPgno ) *pPgno = get4byte(&pPtrmap[offset+1]);

  sqlite3pager_unref(pPtrmap);

  return SQLITE_OK;
}

#endif /* SQLITE_OMIT_AUTOVACUUM */

/*
** Given a btree page and a cell index (0 means the first cell on
................................................................................
  int isInitOrig = pPage->isInit;
  Pgno pgno = pPage->pgno;

  initPage(pPage, 0);
  nCell = pPage->nCell;

  for(i=0; i<nCell; i++){
    CellInfo info;
    u8 *pCell = findCell(pPage, i);

    rc = ptrmapPutOvflPtr(pPage, pCell);
    if( rc!=SQLITE_OK ){
      goto set_child_ptrmaps_out;
    }

................................................................................
**
** PTRMAP_OVERFLOW1: pPage is a btree-page. The pointer points at an overflow
**                   page pointed to by one of the cells on pPage.
**
** PTRMAP_OVERFLOW2: pPage is an overflow-page. The pointer points at the next
**                   overflow page in the list.
*/
static void modifyPagePointer(MemPage *pPage, Pgno iFrom, Pgno iTo, u8 eType){

  if( eType==PTRMAP_OVERFLOW2 ){
    /* The pointer is always the first 4 bytes of the page in this case.  */
    assert( get4byte(pPage->aData)==iFrom );


    put4byte(pPage->aData, iTo);
  }else{
    int isInitOrig = pPage->isInit;
    int i;
    int nCell;

    initPage(pPage, 0);
................................................................................
          put4byte(pCell, iTo);
          break;
        }
      }
    }
  
    if( i==nCell ){
      assert( eType==PTRMAP_BTREE );
      assert( get4byte(&pPage->aData[pPage->hdrOffset+8])==iFrom );


      put4byte(&pPage->aData[pPage->hdrOffset+8], iTo);
    }

    pPage->isInit = isInitOrig;
  }

}


/*
** Move the open database page pDbPage to location iFreePage in the 
** database. The pDbPage reference remains valid.
*/
................................................................................
    rc = setChildPtrmaps(pDbPage);
    if( rc!=SQLITE_OK ){
      return rc;
    }
  }else{
    Pgno nextOvfl = get4byte(pDbPage->aData);
    if( nextOvfl!=0 ){
      assert( nextOvfl<=sqlite3pager_pagecount(pPager) );
      rc = ptrmapPut(pBt, nextOvfl, PTRMAP_OVERFLOW2, iFreePage);
      if( rc!=SQLITE_OK ){
        return rc;
      }
    }
  }

................................................................................
      return rc;
    }
    rc = sqlite3pager_write(pPtrPage->aData);
    if( rc!=SQLITE_OK ){
      releasePage(pPtrPage);
      return rc;
    }
    modifyPagePointer(pPtrPage, iDbPage, iFreePage, eType);
    rc = ptrmapPut(pBt, iFreePage, eType, iPtrPage);
    releasePage(pPtrPage);



  }
  return rc;
}

/* Forward declaration required by autoVacuumCommit(). */
static int allocatePage(Btree *, MemPage **, Pgno *, Pgno, u8);

................................................................................
  MemPage *pFreeMemPage = 0; /* "" */

#ifndef NDEBUG
  int nRef = *sqlite3pager_stats(pPager);
#endif

  assert( pBt->autoVacuum );
  assert( 0==PTRMAP_ISPAGE(pgsz, sqlite3pager_pagecount(pPager)) );



  /* Figure out how many free-pages are in the database. If there are no
  ** free pages, then auto-vacuum is a no-op.
  */
  nFreeList = get4byte(&pBt->pPage1->aData[36]);
  if( nFreeList==0 ){
    *nTrunc = 0;







|







 







|
>
>







 







>







 







<







 







|
<


|
>
>







 







|
|
>
>





>







 







<







 







|
<

>
>
>







 







|
>
>







5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
...
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
...
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
....
1608
1609
1610
1611
1612
1613
1614

1615
1616
1617
1618
1619
1620
1621
....
1647
1648
1649
1650
1651
1652
1653
1654

1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
....
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
....
1739
1740
1741
1742
1743
1744
1745

1746
1747
1748
1749
1750
1751
1752
....
1760
1761
1762
1763
1764
1765
1766
1767

1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
....
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** $Id: btree.c,v 1.240 2005/01/17 02:12:19 danielk1977 Exp $
**
** This file implements a external (disk-based) database using BTrees.
** For a detailed discussion of BTrees, refer to
**
**     Donald E. Knuth, THE ART OF COMPUTER PROGRAMMING, Volume 3:
**     "Sorting And Searching", pages 473-480. Addison-Wesley
**     Publishing Company, Reading, Massachusetts.
................................................................................
static int ptrmapPut(Btree *pBt, Pgno key, u8 eType, Pgno parent){
  u8 *pPtrmap;    /* The pointer map page */
  Pgno iPtrmap;   /* The pointer map page number */
  int offset;     /* Offset in pointer map page */
  int rc;

  assert( pBt->autoVacuum );
  if( key==0 ){
    return SQLITE_CORRUPT;
  }
  iPtrmap = PTRMAP_PAGENO(pBt->usableSize, key);
  rc = sqlite3pager_get(pBt->pPager, iPtrmap, (void **)&pPtrmap);
  if( rc!=SQLITE_OK ){
    return rc;
  }
  offset = PTRMAP_PTROFFSET(pBt->usableSize, key);

................................................................................
  }

  offset = PTRMAP_PTROFFSET(pBt->usableSize, key);
  if( pEType ) *pEType = pPtrmap[offset];
  if( pPgno ) *pPgno = get4byte(&pPtrmap[offset+1]);

  sqlite3pager_unref(pPtrmap);
  if( *pEType<1 || *pEType>5 ) return SQLITE_CORRUPT;
  return SQLITE_OK;
}

#endif /* SQLITE_OMIT_AUTOVACUUM */

/*
** Given a btree page and a cell index (0 means the first cell on
................................................................................
  int isInitOrig = pPage->isInit;
  Pgno pgno = pPage->pgno;

  initPage(pPage, 0);
  nCell = pPage->nCell;

  for(i=0; i<nCell; i++){

    u8 *pCell = findCell(pPage, i);

    rc = ptrmapPutOvflPtr(pPage, pCell);
    if( rc!=SQLITE_OK ){
      goto set_child_ptrmaps_out;
    }

................................................................................
**
** PTRMAP_OVERFLOW1: pPage is a btree-page. The pointer points at an overflow
**                   page pointed to by one of the cells on pPage.
**
** PTRMAP_OVERFLOW2: pPage is an overflow-page. The pointer points at the next
**                   overflow page in the list.
*/
static int modifyPagePointer(MemPage *pPage, Pgno iFrom, Pgno iTo, u8 eType){

  if( eType==PTRMAP_OVERFLOW2 ){
    /* The pointer is always the first 4 bytes of the page in this case.  */
    if( get4byte(pPage->aData)!=iFrom ){
      return SQLITE_CORRUPT;
    }
    put4byte(pPage->aData, iTo);
  }else{
    int isInitOrig = pPage->isInit;
    int i;
    int nCell;

    initPage(pPage, 0);
................................................................................
          put4byte(pCell, iTo);
          break;
        }
      }
    }
  
    if( i==nCell ){
      if( eType!=PTRMAP_BTREE || 
          get4byte(&pPage->aData[pPage->hdrOffset+8])!=iFrom ){
        return SQLITE_CORRUPT;
      }
      put4byte(&pPage->aData[pPage->hdrOffset+8], iTo);
    }

    pPage->isInit = isInitOrig;
  }
  return SQLITE_OK;
}


/*
** Move the open database page pDbPage to location iFreePage in the 
** database. The pDbPage reference remains valid.
*/
................................................................................
    rc = setChildPtrmaps(pDbPage);
    if( rc!=SQLITE_OK ){
      return rc;
    }
  }else{
    Pgno nextOvfl = get4byte(pDbPage->aData);
    if( nextOvfl!=0 ){

      rc = ptrmapPut(pBt, nextOvfl, PTRMAP_OVERFLOW2, iFreePage);
      if( rc!=SQLITE_OK ){
        return rc;
      }
    }
  }

................................................................................
      return rc;
    }
    rc = sqlite3pager_write(pPtrPage->aData);
    if( rc!=SQLITE_OK ){
      releasePage(pPtrPage);
      return rc;
    }
    rc = modifyPagePointer(pPtrPage, iDbPage, iFreePage, eType);

    releasePage(pPtrPage);
    if( rc==SQLITE_OK ){
      rc = ptrmapPut(pBt, iFreePage, eType, iPtrPage);
    }
  }
  return rc;
}

/* Forward declaration required by autoVacuumCommit(). */
static int allocatePage(Btree *, MemPage **, Pgno *, Pgno, u8);

................................................................................
  MemPage *pFreeMemPage = 0; /* "" */

#ifndef NDEBUG
  int nRef = *sqlite3pager_stats(pPager);
#endif

  assert( pBt->autoVacuum );
  if( PTRMAP_ISPAGE(pgsz, sqlite3pager_pagecount(pPager)) ){
    return SQLITE_CORRUPT;
  }

  /* Figure out how many free-pages are in the database. If there are no
  ** free pages, then auto-vacuum is a no-op.
  */
  nFreeList = get4byte(&pBt->pPage1->aData[36]);
  if( nFreeList==0 ){
    *nTrunc = 0;