]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Modify btree.c so that is allocates big data structures using malloc()
authordrh <drh@noemail.net>
Fri, 3 Sep 2004 18:38:44 +0000 (18:38 +0000)
committerdrh <drh@noemail.net>
Fri, 3 Sep 2004 18:38:44 +0000 (18:38 +0000)
instead of allocating from the stack.  Stack allocations cause problems
for embedded systems and pthreads implementations that only allocate a
limited amount of stack space. (CVS 1937)

FossilOrigin-Name: 4595292f936bdbec10734f42682824e91ff71d11

manifest
manifest.uuid
src/btree.c
test/memleak.test

index c24c0e048d434ac0fd6a1af5b2e0e0cb42efba93..a560c4e45981f78d4faef70149fa731c95d3ea4b 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C More\stests\sof\ssqlite3_step()\sand\sSQLITE_BUSY\sadded.\s(CVS\s1936)
-D 2004-09-03T00:27:57
+C Modify\sbtree.c\sso\sthat\sis\sallocates\sbig\sdata\sstructures\susing\smalloc()\ninstead\sof\sallocating\sfrom\sthe\sstack.\s\sStack\sallocations\scause\sproblems\nfor\sembedded\ssystems\sand\spthreads\simplementations\sthat\sonly\sallocate\sa\nlimited\samount\sof\sstack\sspace.\s(CVS\s1937)
+D 2004-09-03T18:38:45
 F Makefile.in 65a7c43fcaf9a710d62f120b11b6e435eeb4a450
 F Makefile.linux-gcc a9e5a0d309fa7c38e7c14d3ecf7690879d3a5457
 F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd
@@ -28,7 +28,7 @@ F sqlite3.def 84215604aa7b547d75e0f7b437966e7ad18fa8b2
 F sqlite3.pc.in 985b9bf34192a549d7d370e0f0b6b34a4f61369a
 F src/attach.c 0bd4f11da6999665da30625665a4096ba7898de6
 F src/auth.c 60db23b98bb94c8b0178180faaf49dc116674217
-F src/btree.c 598e7eccfa93194851f570c0ea146f6efe098ac3
+F src/btree.c 91a6f5e90c6e7a15cc9af4257866a03c1614442e
 F src/btree.h 94dfec0a1722d33359b23e7e310f2b64ffedf029
 F src/build.c 35275654d9c5ce6c1c0c78e391f85e6915a8a66b
 F src/date.c edff4aa851eeca8abbc737dc3933a2f0671156ce
@@ -139,7 +139,7 @@ F test/lock2.test 2213590d442147d09fd2334c905a755586c1c398
 F test/main.test 1430a4b5bd3a6d5e0294966b742d80a551f87211
 F test/malloc.test 769b240d89a7ef3320d88919fdb6765f9395a51f
 F test/memdb.test b8a13fa79f006bd087bbcf135ce8eb62056a6027
-F test/memleak.test a7efa33c7adc2762add028a4cc70a6bb04fe573e
+F test/memleak.test f1fa233f8295dd1d955a00d5e5ee857850f27f29
 F test/minmax.test c0f92d3f7b11656221735385f2c8b1878bbbdaf6
 F test/misc1.test 1a20ea722dff15155e93948dc4ac3e8d80fec386
 F test/misc2.test 703734f5817215ca54e364833b3bf5ff36fcc21e
@@ -248,7 +248,7 @@ F www/tclsqlite.tcl 560ecd6a916b320e59f2917317398f3d59b7cc25
 F www/vdbe.tcl 59288db1ac5c0616296b26dce071c36cb611dfe9
 F www/version3.tcl 092a01f5ef430d2c4acc0ae558d74c4bb89638a0
 F www/whentouse.tcl a8335bce47cc2fddb07f19052cb0cb4d9129a8e4
-P 45d7158878a9648708d8ed47944707169a7f7f1c
-R 14f7ba7cd5cb5bab38c50df92d09018d
+P 9e6645dd781cb8e422e371ca23766dc1b689481e
+R f084bc97486f0a01c7a5a8e06138356c
 U drh
-Z 97faa8433bbaa30accc2ea468a82795b
+Z 4d667560618f87c860d31b44d3368e4d
index 0dac40e7166152f490870d87cbf62885eb3899f5..b8334d58fcbfadae8a8ebeaad4081b2502ec1fa2 100644 (file)
@@ -1 +1 @@
-9e6645dd781cb8e422e371ca23766dc1b689481e
\ No newline at end of file
+4595292f936bdbec10734f42682824e91ff71d11
\ No newline at end of file
index 75343d1a261e9ee32a0d3ffc7a9169864f9891d9..354d36866df37ecc08980af516bcc58757a1a9be 100644 (file)
@@ -9,7 +9,7 @@
 **    May you share freely, never taking more than you give.
 **
 *************************************************************************
-** $Id: btree.c,v 1.185 2004/09/01 16:12:25 drh Exp $
+** $Id: btree.c,v 1.186 2004/09/03 18:38:45 drh Exp $
 **
 ** This file implements a external (disk-based) database using BTrees.
 ** For a detailed discussion of BTrees, refer to
 /* The following value is the maximum cell size assuming a maximum page
 ** size give above.
 */
-#define MX_CELL_SIZE  (SQLITE_MAX_PAGE_SIZE-8)
+#define MX_CELL_SIZE(pBt)  (pBt->pageSize-8)
 
 /* The maximum number of cells on a single page of the database.  This
 ** assumes a minimum cell size of 3 bytes.  Such small cells will be
 ** exceedingly rare, but they are possible.
 */
-#define MX_CELL ((SQLITE_MAX_PAGE_SIZE-8)/3)
+#define MX_CELL(pBt) ((pBt->pageSize-8)/3)
 
 /* Forward declarations */
 typedef struct MemPage MemPage;
@@ -527,8 +527,10 @@ static void _pageIntegrity(MemPage *pPage){
   int i, j, idx, c, pc, hdr, nFree;
   int cellOffset;
   int nCell, cellLimit;
-  u8 used[SQLITE_MAX_PAGE_SIZE];
+  u8 *used;
 
+  used = sqliteMallocRaw( pPage->pBt->pageSize );
+  if( used==0 ) return;
   usableSize = pPage->pBt->usableSize;
   assert( pPage->aData==&((unsigned char*)pPage)[-pPage->pBt->pageSize] );
   hdr = pPage->hdrOffset;
@@ -589,6 +591,7 @@ static void _pageIntegrity(MemPage *pPage){
     if( used[i]==0 ) nFree++;
   }
   assert( nFree==data[hdr+7] );
+  sqliteFree(used);
 }
 #define pageIntegrity(X) _pageIntegrity(X)
 #else
@@ -600,7 +603,7 @@ static void _pageIntegrity(MemPage *pPage){
 ** beginning of the page and all free space is collected 
 ** into one big FreeBlk at the end of the page.
 */
-static void defragmentPage(MemPage *pPage){
+static int defragmentPage(MemPage *pPage){
   int i;                     /* Loop counter */
   int pc;                    /* Address of a i-th cell */
   int addr;                  /* Offset of first byte after cell pointer array */
@@ -610,13 +613,15 @@ static void defragmentPage(MemPage *pPage){
   int cellOffset;            /* Offset to the cell pointer array */
   int brk;                   /* Offset to the cell content area */
   int nCell;                 /* Number of cells on the page */
-  unsigned char *data;               /* The page data */
-  unsigned char temp[SQLITE_MAX_PAGE_SIZE];  /* Temp area for cell content */
+  unsigned char *data;       /* The page data */
+  unsigned char *temp;       /* Temp area for cell content */
 
   assert( sqlite3pager_iswriteable(pPage->aData) );
   assert( pPage->pBt!=0 );
   assert( pPage->pBt->usableSize <= SQLITE_MAX_PAGE_SIZE );
   assert( pPage->nOverflow==0 );
+  temp = sqliteMalloc( pPage->pBt->pageSize );
+  if( temp==0 ) return SQLITE_NOMEM;
   data = pPage->aData;
   hdr = pPage->hdrOffset;
   cellOffset = pPage->cellOffset;
@@ -643,6 +648,8 @@ static void defragmentPage(MemPage *pPage){
   data[hdr+7] = 0;
   addr = cellOffset+2*nCell;
   memset(&data[addr], 0, brk-addr);
+  sqliteFree(temp);
+  return SQLITE_OK;
 }
 
 /*
@@ -702,7 +709,7 @@ static int allocateSpace(MemPage *pPage, int nByte){
   nCell = get2byte(&data[hdr+3]);
   cellOffset = pPage->cellOffset;
   if( nFrag>=60 || cellOffset + 2*nCell > top - nByte ){
-    defragmentPage(pPage);
+    if( defragmentPage(pPage) ) return 0;
     top = get2byte(&data[hdr+5]);
   }
   top -= nByte;
@@ -819,15 +826,17 @@ static int initPage(
   int i;             /* Loop counter */
   int hdr;           /* Offset to beginning of page header */
   u8 *data;          /* Equal to pPage->aData */
+  Btree *pBt;        /* The main btree structure */
   int usableSize;    /* Amount of usable space on each page */
   int cellOffset;    /* Offset from start of page to first cell pointer */
   int nFree;         /* Number of unused bytes on the page */
   int top;           /* First byte of the cell content area */
 
-  assert( pPage->pBt!=0 );
-  assert( pParent==0 || pParent->pBt==pPage->pBt );
+  pBt = pPage->pBt;
+  assert( pBt!=0 );
+  assert( pParent==0 || pParent->pBt==pBt );
   assert( pPage->pgno==sqlite3pager_pagenumber(pPage->aData) );
-  assert( pPage->aData == &((unsigned char*)pPage)[-pPage->pBt->pageSize] );
+  assert( pPage->aData == &((unsigned char*)pPage)[-pBt->pageSize] );
   if( pPage->pParent!=pParent && (pPage->pParent!=0 || pPage->isInit) ){
     /* The parent page should never change unless the file is corrupt */
     return SQLITE_CORRUPT; /* bkpt-CORRUPT */
@@ -842,11 +851,11 @@ static int initPage(
   decodeFlags(pPage, data[hdr]);
   pPage->nOverflow = 0;
   pPage->idxShift = 0;
-  usableSize = pPage->pBt->usableSize;
+  usableSize = pBt->usableSize;
   pPage->cellOffset = cellOffset = hdr + 12 - 4*pPage->leaf;
   top = get2byte(&data[hdr+5]);
   pPage->nCell = get2byte(&data[hdr+3]);
-  if( pPage->nCell>MX_CELL ){
+  if( pPage->nCell>MX_CELL(pBt) ){
     /* To many cells for a single page.  The page must be corrupt */
     return SQLITE_CORRUPT; /* bkpt-CORRUPT */
   }
@@ -1218,7 +1227,7 @@ static int lockBtree(Btree *pBt){
   if( pBt->minLocal>pBt->maxLocal || pBt->maxLocal<0 ){
     goto page1_init_failed;
   }
-  assert( pBt->maxLeaf + 23 <= MX_CELL_SIZE );
+  assert( pBt->maxLeaf + 23 <= MX_CELL_SIZE(pBt) );
   pBt->pPage1 = pPage1;
   pBt->pageSizeFixed = 1;
   return SQLITE_OK;
@@ -2916,6 +2925,7 @@ static int balance_nonroot(MemPage *pPage){
   int pageFlags;               /* Value of pPage->aData[0] */
   int subtotal;                /* Subtotal of bytes in cells on one page */
   int iSpace = 0;              /* First unused byte of aSpace[] */
+  int mxCellPerPage;           /* Maximum number of cells in one page */
   MemPage *apOld[NB];          /* pPage and up to two siblings */
   Pgno pgnoOld[NB];            /* Page numbers for each page in apOld[] */
   MemPage *apCopy[NB];         /* Private copies of apOld[] pages */
@@ -2925,10 +2935,10 @@ static int balance_nonroot(MemPage *pPage){
   u8 *apDiv[NB];               /* Divider cells in pParent */
   int cntNew[NB+2];            /* Index in aCell[] of cell after i-th page */
   int szNew[NB+2];             /* Combined size of cells place on i-th page */
-  u8 *apCell[(MX_CELL+2)*NB];  /* All cells from pages being balanced */
-  int szCell[(MX_CELL+2)*NB];  /* Local size of all cells */
-  u8 aCopy[NB][SQLITE_MAX_PAGE_SIZE+sizeof(MemPage)];  /* Space for apCopy[] */
-  u8 aSpace[SQLITE_MAX_PAGE_SIZE*5];   /* Space to copies of divider cells */
+  u8 **apCell;                 /* All cells begin balanced */
+  int *szCell;                 /* Local size of all cells in apCell[] */
+  u8 *aCopy[NB];               /* Space for holding data of apCopy[] */
+  u8 *aSpace;                  /* Space to hold copies of dividers cells */
 
   /* 
   ** Find the parent page.
@@ -2940,6 +2950,25 @@ static int balance_nonroot(MemPage *pPage){
   sqlite3pager_write(pParent->aData);
   assert( pParent );
   TRACE(("BALANCE: begin page %d child of %d\n", pPage->pgno, pParent->pgno));
+
+  /*
+  ** Allocate space for memory structures
+  */
+  mxCellPerPage = MX_CELL(pBt);
+  apCell = sqliteMallocRaw( 
+       (mxCellPerPage+2)*NB*(sizeof(u8*)+sizeof(int))
+     + sizeof(MemPage)*NB
+     + pBt->pageSize*(5+NB)
+  );
+  if( apCell==0 ){
+    return SQLITE_NOMEM;
+  }
+  szCell = (int*)&apCell[(mxCellPerPage+2)*NB];
+  aCopy[0] = (u8*)&szCell[(mxCellPerPage+2)*NB];
+  for(i=1; i<NB; i++){
+    aCopy[i] = &aCopy[i-1][pBt->pageSize+sizeof(MemPage)];
+  }
+  aSpace = &aCopy[NB-1][pBt->pageSize+sizeof(MemPage)];
   
   /*
   ** Find the cell in the parent page whose left child points back
@@ -3010,7 +3039,7 @@ static int balance_nonroot(MemPage *pPage){
   ** process of being overwritten.
   */
   for(i=0; i<nOld; i++){
-    MemPage *p = apCopy[i] = (MemPage*)&aCopy[i+1][-(int)sizeof(MemPage)];
+    MemPage *p = apCopy[i] = (MemPage*)&aCopy[i][pBt->pageSize];
     p->aData = &((u8*)p)[-pBt->pageSize];
     memcpy(p->aData, apOld[i]->aData, pBt->pageSize + sizeof(MemPage));
     p->aData = &((u8*)p)[-pBt->pageSize];
@@ -3057,7 +3086,7 @@ static int balance_nonroot(MemPage *pPage){
         szCell[nCell] = sz;
         pTemp = &aSpace[iSpace];
         iSpace += sz;
-        assert( iSpace<=sizeof(aSpace) );
+        assert( iSpace<=pBt->pageSize*5 );
         memcpy(pTemp, apDiv[i], sz);
         apCell[nCell] = pTemp+leafCorrection;
         dropCell(pParent, nxDiv, sz);
@@ -3241,13 +3270,13 @@ static int balance_nonroot(MemPage *pPage){
         pCell = &aSpace[iSpace];
         fillInCell(pParent, pCell, 0, info.nKey, 0, 0, &sz);
         iSpace += sz;
-        assert( iSpace<=sizeof(aSpace) );
+        assert( iSpace<=pBt->pageSize*5 );
         pTemp = 0;
       }else{
         pCell -= 4;
         pTemp = &aSpace[iSpace];
         iSpace += sz;
-        assert( iSpace<=sizeof(aSpace) );
+        assert( iSpace<=pBt->pageSize*5 );
       }
       insertCell(pParent, nxDiv, pCell, sz, pTemp);
       put4byte(findOverflowCell(pParent,nxDiv), pNew->pgno);
@@ -3290,6 +3319,7 @@ static int balance_nonroot(MemPage *pPage){
   ** Cleanup before returning.
   */
 balance_cleanup:
+  sqliteFree(apCell);
   for(i=0; i<nOld; i++){
     releasePage(apOld[i]);
   }
@@ -3310,12 +3340,19 @@ balance_cleanup:
 static int balance_shallower(MemPage *pPage){
   MemPage *pChild;             /* The only child page of pPage */
   Pgno pgnoChild;              /* Page number for pChild */
-  int rc;                      /* Return code from subprocedures */
-  u8 *apCell[(MX_CELL+2)*NB];  /* All cells from pages being balanced */
-  int szCell[(MX_CELL+2)*NB];  /* Local size of all cells */
+  int rc = SQLITE_OK;          /* Return code from subprocedures */
+  Btree *pBt;                  /* The main BTree structure */
+  int mxCellPerPage;           /* Maximum number of cells per page */
+  u8 **apCell;                 /* All cells from pages being balanced */
+  int *szCell;                 /* Local size of all cells */
 
   assert( pPage->pParent==0 );
   assert( pPage->nCell==0 );
+  pBt = pPage->pBt;
+  mxCellPerPage = MX_CELL(pBt);
+  apCell = sqliteMallocRaw( mxCellPerPage*(sizeof(u8*)+sizeof(int)) );
+  if( apCell==0 ) return SQLITE_NOMEM;
+  szCell = (int*)&apCell[mxCellPerPage];
   if( pPage->leaf ){
     /* The table is completely empty */
     TRACE(("BALANCE: empty table %d\n", pPage->pgno));
@@ -3336,10 +3373,10 @@ static int balance_shallower(MemPage *pPage){
     assert( pgnoChild>0 );
     assert( pgnoChild<=sqlite3pager_pagecount(pPage->pBt->pPager) );
     rc = getPage(pPage->pBt, pgnoChild, &pChild);
-    if( rc ) return rc;
+    if( rc ) goto end_shallow_balance;
     if( pPage->pgno==1 ){
       rc = initPage(pChild, pPage);
-      if( rc ) return rc;
+      if( rc ) goto end_shallow_balance;
       assert( pChild->nOverflow==0 );
       if( pChild->nFree>=100 ){
         /* The child information will fit on the root page, so do the
@@ -3371,7 +3408,9 @@ static int balance_shallower(MemPage *pPage){
     reparentChildPages(pPage);
     releasePage(pChild);
   }
-  return SQLITE_OK;
+end_shallow_balance:
+  sqliteFree(apCell);
+  return rc;
 }
 
 
@@ -3492,7 +3531,7 @@ int sqlite3BtreeInsert(
   MemPage *pPage;
   Btree *pBt = pCur->pBt;
   unsigned char *oldCell;
-  unsigned char newCell[MX_CELL_SIZE];
+  unsigned char *newCell = 0;
 
   if( pCur->status ){
     return pCur->status;  /* A rollback destroyed this cursor */
@@ -3519,10 +3558,12 @@ int sqlite3BtreeInsert(
   assert( pPage->isInit );
   rc = sqlite3pager_write(pPage->aData);
   if( rc ) return rc;
+  newCell = sqliteMallocRaw( MX_CELL_SIZE(pBt) );
+  if( newCell==0 ) return SQLITE_NOMEM;
   rc = fillInCell(pPage, newCell, pKey, nKey, pData, nData, &szNew);
-  if( rc ) return rc;
+  if( rc ) goto end_insert;
   assert( szNew==cellSizePtr(pPage, newCell) );
-  assert( szNew<=sizeof(newCell) );
+  assert( szNew<=MX_CELL_SIZE(pBt) );
   if( loc==0 && pCur->isValid ){
     int szOld;
     assert( pCur->idx>=0 && pCur->idx<pPage->nCell );
@@ -3532,7 +3573,7 @@ int sqlite3BtreeInsert(
     }
     szOld = cellSizePtr(pPage, oldCell);
     rc = clearCell(pPage, oldCell);
-    if( rc ) return rc;
+    if( rc ) goto end_insert;
     dropCell(pPage, pCur->idx, szOld);
   }else if( loc<0 && pPage->nCell>0 ){
     assert( pPage->leaf );
@@ -3546,6 +3587,8 @@ int sqlite3BtreeInsert(
   /* sqlite3BtreePageDump(pCur->pBt, pCur->pgnoRoot, 1); */
   /* fflush(stdout); */
   moveToRoot(pCur);
+end_insert:
+  sqliteFree(newCell);
   return rc;
 }
 
@@ -3597,7 +3640,7 @@ int sqlite3BtreeDelete(BtCursor *pCur){
     unsigned char *pNext;
     int szNext;
     int notUsed;
-    unsigned char tempCell[MX_CELL_SIZE];
+    unsigned char *tempCell;
     assert( !pPage->leafData );
     getTempCursor(pCur, &leafCur);
     rc = sqlite3BtreeNext(&leafCur, &notUsed);
@@ -3614,10 +3657,13 @@ int sqlite3BtreeDelete(BtCursor *pCur){
     dropCell(pPage, pCur->idx, cellSizePtr(pPage, pCell));
     pNext = findCell(leafCur.pPage, leafCur.idx);
     szNext = cellSizePtr(leafCur.pPage, pNext);
-    assert( sizeof(tempCell)>=szNext+4 );
+    assert( MX_CELL_SIZE(pBt)>=szNext+4 );
+    tempCell = sqliteMallocRaw( MX_CELL_SIZE(pBt) );
+    if( tempCell==0 ) return SQLITE_NOMEM;
     insertCell(pPage, pCur->idx, pNext-4, szNext+4, tempCell);
     put4byte(findOverflowCell(pPage, pCur->idx), pgnoChild);
     rc = balance(pPage);
+    sqliteFree(tempCell);
     if( rc ) return rc;
     dropCell(leafCur.pPage, leafCur.idx, szNext);
     rc = balance(leafCur.pPage);
@@ -4013,7 +4059,18 @@ struct IntegrityCk {
 /*
 ** Append a message to the error message string.
 */
-static void checkAppendMsg(IntegrityCk *pCheck, char *zMsg1, char *zMsg2){
+static void checkAppendMsg(
+  IntegrityCk *pCheck,
+  char *zMsg1,
+  const char *zFormat,
+  ...
+){
+  va_list ap;
+  char *zMsg2;
+  va_start(ap, zFormat);
+  zMsg2 = sqlite3VMPrintf(zFormat, ap);
+  va_end(ap);
+  if( zMsg1==0 ) zMsg1 = "";
   if( pCheck->zErrMsg ){
     char *zOld = pCheck->zErrMsg;
     pCheck->zErrMsg = 0;
@@ -4022,6 +4079,7 @@ static void checkAppendMsg(IntegrityCk *pCheck, char *zMsg1, char *zMsg2){
   }else{
     sqlite3SetString(&pCheck->zErrMsg, zMsg1, zMsg2, (char*)0);
   }
+  sqliteFree(zMsg2);
 }
 
 /*
@@ -4035,15 +4093,11 @@ static void checkAppendMsg(IntegrityCk *pCheck, char *zMsg1, char *zMsg2){
 static int checkRef(IntegrityCk *pCheck, int iPage, char *zContext){
   if( iPage==0 ) return 1;
   if( iPage>pCheck->nPage || iPage<0 ){
-    char zBuf[100];
-    sprintf(zBuf, "invalid page number %d", iPage);
-    checkAppendMsg(pCheck, zContext, zBuf);
+    checkAppendMsg(pCheck, zContext, "invalid page number %d", iPage);
     return 1;
   }
   if( pCheck->anRef[iPage]==1 ){
-    char zBuf[100];
-    sprintf(zBuf, "2nd reference to page %d", iPage);
-    checkAppendMsg(pCheck, zContext, zBuf);
+    checkAppendMsg(pCheck, zContext, "2nd reference to page %d", iPage);
     return 1;
   }
   return  (pCheck->anRef[iPage]++)>1;
@@ -4063,26 +4117,24 @@ static void checkList(
   int i;
   int expected = N;
   int iFirst = iPage;
-  char zMsg[100];
   while( N-- > 0 ){
     unsigned char *pOvfl;
     if( iPage<1 ){
-      sprintf(zMsg, "%d of %d pages missing from overflow list starting at %d",
+      checkAppendMsg(pCheck, zContext,
+         "%d of %d pages missing from overflow list starting at %d",
           N+1, expected, iFirst);
-      checkAppendMsg(pCheck, zContext, zMsg);
       break;
     }
     if( checkRef(pCheck, iPage, zContext) ) break;
     if( sqlite3pager_get(pCheck->pPager, (Pgno)iPage, (void**)&pOvfl) ){
-      sprintf(zMsg, "failed to get page %d", iPage);
-      checkAppendMsg(pCheck, zContext, zMsg);
+      checkAppendMsg(pCheck, zContext, "failed to get page %d", iPage);
       break;
     }
     if( isFreeList ){
       int n = get4byte(&pOvfl[4]);
       if( n>pCheck->pBt->usableSize/4-8 ){
-        sprintf(zMsg, "freelist leaf count too big on page %d", iPage);
-        checkAppendMsg(pCheck, zContext, zMsg);
+        checkAppendMsg(pCheck, zContext,
+           "freelist leaf count too big on page %d", iPage);
         N--;
       }else{
         for(i=0; i<n; i++){
@@ -4132,9 +4184,8 @@ static int checkTreePage(
   BtCursor cur;
   Btree *pBt;
   int maxLocal, usableSize;
-  char zMsg[100];
   char zContext[100];
-  char hit[SQLITE_MAX_PAGE_SIZE];
+  char *hit;
 
   /* Check that the page exists
   */
@@ -4143,14 +4194,13 @@ static int checkTreePage(
   if( iPage==0 ) return 0;
   if( checkRef(pCheck, iPage, zParentContext) ) return 0;
   if( (rc = getPage(pBt, (Pgno)iPage, &pPage))!=0 ){
-    sprintf(zMsg, "unable to get the page. error code=%d", rc);
-    checkAppendMsg(pCheck, zContext, zMsg);
+    checkAppendMsg(pCheck, zContext,
+       "unable to get the page. error code=%d", rc);
     return 0;
   }
   maxLocal = pPage->leafData ? pBt->maxLeaf : pBt->maxLocal;
   if( (rc = initPage(pPage, pParent))!=0 ){
-    sprintf(zMsg, "initPage() returns error code %d", rc);
-    checkAppendMsg(pCheck, zContext, zMsg);
+    checkAppendMsg(pCheck, zContext, "initPage() returns error code %d", rc);
     releasePage(pPage);
     return 0;
   }
@@ -4197,36 +4247,40 @@ static int checkTreePage(
   */
   data = pPage->aData;
   hdr = pPage->hdrOffset;
-  memset(hit, 0, usableSize);
-  memset(hit, 1, get2byte(&data[hdr+5]));
-  nCell = get2byte(&data[hdr+3]);
-  cellStart = hdr + 12 - 4*pPage->leaf;
-  for(i=0; i<nCell; i++){
-    int pc = get2byte(&data[cellStart+i*2]);
-    int size = cellSizePtr(pPage, &data[pc]);
-    int j;
-    for(j=pc+size-1; j>=pc; j--) hit[j]++;
-  }
-  for(cnt=0, i=get2byte(&data[hdr+1]); i>0 && i<usableSize && cnt<10000; cnt++){
-    int size = get2byte(&data[i+2]);
-    int j;
-    for(j=i+size-1; j>=i; j--) hit[j]++;
-    i = get2byte(&data[i]);
-  }
-  for(i=cnt=0; i<usableSize; i++){
-    if( hit[i]==0 ){
-      cnt++;
-    }else if( hit[i]>1 ){
-      sprintf(zMsg, "Multiple uses for byte %d of page %d", i, iPage);
-      checkAppendMsg(pCheck, zMsg, 0);
-      break;
+  hit = sqliteMalloc( usableSize );
+  if( hit ){
+    memset(hit, 1, get2byte(&data[hdr+5]));
+    nCell = get2byte(&data[hdr+3]);
+    cellStart = hdr + 12 - 4*pPage->leaf;
+    for(i=0; i<nCell; i++){
+      int pc = get2byte(&data[cellStart+i*2]);
+      int size = cellSizePtr(pPage, &data[pc]);
+      int j;
+      for(j=pc+size-1; j>=pc; j--) hit[j]++;
+    }
+    for(cnt=0, i=get2byte(&data[hdr+1]); i>0 && i<usableSize && cnt<10000; 
+           cnt++){
+      int size = get2byte(&data[i+2]);
+      int j;
+      for(j=i+size-1; j>=i; j--) hit[j]++;
+      i = get2byte(&data[i]);
+    }
+    for(i=cnt=0; i<usableSize; i++){
+      if( hit[i]==0 ){
+        cnt++;
+      }else if( hit[i]>1 ){
+        checkAppendMsg(pCheck, 0,
+          "Multiple uses for byte %d of page %d", i, iPage);
+        break;
+      }
+    }
+    if( cnt!=data[hdr+7] ){
+      checkAppendMsg(pCheck, 0, 
+          "Fragmented space is %d byte reported as %d on page %d",
+          cnt, data[hdr+7], iPage);
     }
   }
-  if( cnt!=data[hdr+7] ){
-    sprintf(zMsg, "Fragmented space is %d byte reported as %d on page %d",
-        cnt, data[hdr+7], iPage);
-    checkAppendMsg(pCheck, zMsg, 0);
-  }
+  sqliteFree(hit);
 
   releasePage(pPage);
   return depth+1;
@@ -4282,9 +4336,7 @@ char *sqlite3BtreeIntegrityCheck(Btree *pBt, int *aRoot, int nRoot){
   */
   for(i=1; i<=sCheck.nPage; i++){
     if( sCheck.anRef[i]==0 ){
-      char zBuf[100];
-      sprintf(zBuf, "Page %d is never used", i);
-      checkAppendMsg(&sCheck, zBuf, 0);
+      checkAppendMsg(&sCheck, 0, "Page %d is never used", i);
     }
   }
 
@@ -4292,12 +4344,10 @@ char *sqlite3BtreeIntegrityCheck(Btree *pBt, int *aRoot, int nRoot){
   */
   unlockBtreeIfUnused(pBt);
   if( nRef != *sqlite3pager_stats(pBt->pPager) ){
-    char zBuf[100];
-    sprintf(zBuf, 
+    checkAppendMsg(&sCheck, 0, 
       "Outstanding page count goes from %d to %d during this analysis",
       nRef, *sqlite3pager_stats(pBt->pPager)
     );
-    checkAppendMsg(&sCheck, zBuf, 0);
   }
 
   /* Clean  up and report errors.
index 8d77a4ab993ff6feabb68b8d4f9d26d65c19b3ba..abc85a0a7fe9d311a51d613d100f33f5bb3c5ac4 100644 (file)
@@ -10,7 +10,7 @@
 #***********************************************************************
 # This file runs all tests.
 #
-# $Id: memleak.test,v 1.6 2004/08/01 03:52:18 drh Exp $
+# $Id: memleak.test,v 1.7 2004/09/03 18:38:46 drh Exp $
 
 set testdir [file dirname $argv0]
 source $testdir/tester.tcl
@@ -41,6 +41,7 @@ set EXCLUDE {
   btree2.test
   trans.test
   crash.test
+  corrupt.test
 }
 if {[sqlite3 -has-codec]} {
   # lappend EXCLUDE