aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordrh <drh@noemail.net>2004-09-03 18:38:44 +0000
committerdrh <drh@noemail.net>2004-09-03 18:38:44 +0000
commit2e38c32b673501ec072c625331a0c991f193f30d (patch)
tree0deac32b7ec976f7a4d4be0f6082edcaa558e04f
parent2c7e56798b06d55650a19a08b3ad2889fe712ca5 (diff)
downloadsqlite-2e38c32b673501ec072c625331a0c991f193f30d.tar.gz
sqlite-2e38c32b673501ec072c625331a0c991f193f30d.zip
Modify btree.c so that is allocates big data structures using malloc()
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
-rw-r--r--manifest14
-rw-r--r--manifest.uuid2
-rw-r--r--src/btree.c226
-rw-r--r--test/memleak.test3
4 files changed, 148 insertions, 97 deletions
diff --git a/manifest b/manifest
index c24c0e048..a560c4e45 100644
--- 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
diff --git a/manifest.uuid b/manifest.uuid
index 0dac40e71..b8334d58f 100644
--- a/manifest.uuid
+++ b/manifest.uuid
@@ -1 +1 @@
-9e6645dd781cb8e422e371ca23766dc1b689481e \ No newline at end of file
+4595292f936bdbec10734f42682824e91ff71d11 \ No newline at end of file
diff --git a/src/btree.c b/src/btree.c
index 75343d1a2..354d36866 100644
--- a/src/btree.c
+++ b/src/btree.c
@@ -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
@@ -214,13 +214,13 @@
/* 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.
diff --git a/test/memleak.test b/test/memleak.test
index 8d77a4ab9..abc85a0a7 100644
--- a/test/memleak.test
+++ b/test/memleak.test
@@ -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