Index: src/alter.c ================================================================== --- src/alter.c +++ src/alter.c @@ -773,10 +773,11 @@ assert( pNew->nCol>0 ); nAlloc = (((pNew->nCol-1)/8)*8)+8; assert( nAlloc>=pNew->nCol && nAlloc%8==0 && nAlloc-pNew->nCol<8 ); pNew->aCol = (Column*)sqlite3DbMallocZero(db, sizeof(Column)*nAlloc); pNew->zName = sqlite3MPrintf(db, "sqlite_altertab_%s", pTab->zName); + sqlite3MemLink(pNew, pNew->zName); if( !pNew->aCol || !pNew->zName ){ db->mallocFailed = 1; goto exit_begin_add_column; } memcpy(pNew->aCol, pTab->aCol, sizeof(Column)*pNew->nCol); Index: src/analyze.c ================================================================== --- src/analyze.c +++ src/analyze.c @@ -484,32 +484,10 @@ if( *z==' ' ) z++; } return 0; } -/* -** If the Index.aSample variable is not NULL, delete the aSample[] array -** and its contents. -*/ -void sqlite3DeleteIndexSamples(Index *pIdx){ -#ifdef SQLITE_ENABLE_STAT2 - if( pIdx->aSample ){ - int j; - for(j=0; jaSample[j]; - if( p->eType==SQLITE_TEXT || p->eType==SQLITE_BLOB ){ - sqlite3_free(p->u.z); - } - } - sqlite3DbFree(0, pIdx->aSample); - pIdx->aSample = 0; - } -#else - UNUSED_PARAMETER(pIdx); -#endif -} - /* ** Load the content of the sqlite_stat1 and sqlite_stat2 tables. The ** contents of sqlite_stat1 are used to populate the Index.aiRowEst[] ** arrays. The contents of sqlite_stat2 are used to populate the ** Index.aSample[] arrays. @@ -540,11 +518,15 @@ /* Clear any prior statistics */ for(i=sqliteHashFirst(&db->aDb[iDb].pSchema->idxHash);i;i=sqliteHashNext(i)){ Index *pIdx = sqliteHashData(i); sqlite3DefaultRowEst(pIdx); - sqlite3DeleteIndexSamples(pIdx); + if( pIdx->aSample ){ + sqlite3MemUnlink(pIdx, pIdx->aSample); + sqlite3DbFree(db, pIdx->aSample); + pIdx->aSample = 0; + } } /* Check to make sure the sqlite_stat1 table exists */ sInfo.db = db; sInfo.zDatabase = db->aDb[iDb].zName; @@ -586,24 +568,24 @@ Index *pIdx = sqlite3FindIndex(db, zIndex, sInfo.zDatabase); if( pIdx ){ int iSample = sqlite3_column_int(pStmt, 1); if( iSample=0 ){ int eType = sqlite3_column_type(pStmt, 2); + IndexSample *aSample = pIdx->aSample; - if( pIdx->aSample==0 ){ + if( aSample==0 ){ static const int sz = sizeof(IndexSample)*SQLITE_INDEX_SAMPLES; - pIdx->aSample = (IndexSample *)sqlite3Malloc(sz); - if( pIdx->aSample==0 ){ + pIdx->aSample = aSample = sqlite3DbMallocZeroChild(0, sz, pIdx); + if( aSample==0 ){ db->mallocFailed = 1; break; } - memset(pIdx->aSample, 0, sz); } - - assert( pIdx->aSample ); + + assert( aSample ); { - IndexSample *pSample = &pIdx->aSample[iSample]; + IndexSample *pSample = &aSample[iSample]; pSample->eType = (u8)eType; if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){ pSample->u.r = sqlite3_column_double(pStmt, 2); }else if( eType==SQLITE_TEXT || eType==SQLITE_BLOB ){ const char *z = (const char *)( @@ -617,13 +599,14 @@ } pSample->nByte = (u8)n; if( n < 1){ pSample->u.z = 0; }else{ - pSample->u.z = sqlite3Malloc(n); - if( pSample->u.z ){ - memcpy(pSample->u.z, z, n); + char *zSample; + pSample->u.z = zSample = sqlite3DbMallocRawChild(0,n,aSample); + if( zSample ){ + memcpy(zSample, z, n); }else{ db->mallocFailed = 1; break; } } Index: src/btree.c ================================================================== --- src/btree.c +++ src/btree.c @@ -2002,11 +2002,11 @@ assert( !pBt->pCursor ); sqlite3PagerClose(pBt->pPager); if( pBt->xFreeSchema && pBt->pSchema ){ pBt->xFreeSchema(pBt->pSchema); } - sqlite3_free(pBt->pSchema); + sqlite3DbFree(0, pBt->pSchema); freeTempSpace(pBt); sqlite3_free(pBt); } #ifndef SQLITE_OMIT_SHARED_CACHE @@ -7747,10 +7747,11 @@ i = PENDING_BYTE_PAGE(pBt); if( i<=sCheck.nPage ){ sCheck.anRef[i] = 1; } sqlite3StrAccumInit(&sCheck.errMsg, zErr, sizeof(zErr), 20000); + sCheck.errMsg.useMalloc = 2; /* Check the integrity of the freelist */ checkList(&sCheck, 1, get4byte(&pBt->pPage1->aData[32]), get4byte(&pBt->pPage1->aData[36]), "Main freelist: "); @@ -7884,11 +7885,11 @@ */ void *sqlite3BtreeSchema(Btree *p, int nBytes, void(*xFree)(void *)){ BtShared *pBt = p->pBt; sqlite3BtreeEnter(p); if( !pBt->pSchema && nBytes ){ - pBt->pSchema = sqlite3MallocZero(nBytes); + pBt->pSchema = sqlite3DbMallocZero(0, nBytes); pBt->xFreeSchema = xFree; } sqlite3BtreeLeave(p); return pBt->pSchema; } Index: src/build.c ================================================================== --- src/build.c +++ src/build.c @@ -344,14 +344,10 @@ /* ** Reclaim the memory used by an index */ static void freeIndex(sqlite3 *db, Index *p){ -#ifndef SQLITE_OMIT_ANALYZE - sqlite3DeleteIndexSamples(p); -#endif - sqlite3DbFree(db, p->zColAff); sqlite3DbFree(db, p); } /* ** Remove the given index from the index hash table, and free @@ -476,13 +472,10 @@ assert( pTable!=0 ); if( (pCol = pTable->aCol)!=0 ){ for(i=0; inCol; i++, pCol++){ sqlite3DbFree(db, pCol->zName); sqlite3ExprDelete(db, pCol->pDflt); - sqlite3DbFree(db, pCol->zDflt); - sqlite3DbFree(db, pCol->zType); - sqlite3DbFree(db, pCol->zColl); } sqlite3DbFree(db, pTable->aCol); } pTable->aCol = 0; pTable->nCol = 0; @@ -521,12 +514,10 @@ sqlite3FkDelete(db, pTable); /* Delete the Table structure itself. */ sqliteResetColumnNames(db, pTable); - sqlite3DbFree(db, pTable->zName); - sqlite3DbFree(db, pTable->zColAff); sqlite3SelectDelete(db, pTable->pSelect); #ifndef SQLITE_OMIT_CHECK sqlite3ExprDelete(db, pTable->pCheck); #endif sqlite3VtabClear(db, pTable); @@ -811,10 +802,11 @@ pParse->rc = SQLITE_NOMEM; pParse->nErr++; goto begin_table_error; } pTable->zName = zName; + sqlite3MemLink(pTable, zName); pTable->iPKey = -1; pTable->pSchema = db->aDb[iDb].pSchema; pTable->nRef = 1; assert( pParse->pNewTable==0 ); pParse->pNewTable = pTable; @@ -943,11 +935,11 @@ return; } } if( (p->nCol & 0x7)==0 ){ Column *aNew; - aNew = sqlite3DbRealloc(db,p->aCol,(p->nCol+8)*sizeof(p->aCol[0])); + aNew = sqlite3DbRealloc(db, p->aCol, (p->nCol+8)*sizeof(p->aCol[0])); if( aNew==0 ){ sqlite3DbFree(db, z); return; } p->aCol = aNew; @@ -1054,10 +1046,11 @@ p = pParse->pNewTable; if( p==0 || NEVER(p->nCol<1) ) return; pCol = &p->aCol[p->nCol-1]; assert( pCol->zType==0 ); pCol->zType = sqlite3NameFromToken(pParse->db, pType); + sqlite3MemLink(p->aCol, pCol->zType); pCol->affinity = sqlite3AffinityType(pCol->zType); } /* ** The expression is the default value for the most recently added column @@ -1084,13 +1077,13 @@ ** tokens that point to volatile memory. The 'span' of the expression ** is required by pragma table_info. */ sqlite3ExprDelete(db, pCol->pDflt); pCol->pDflt = sqlite3ExprDup(db, pSpan->pExpr, EXPRDUP_REDUCE); - sqlite3DbFree(db, pCol->zDflt); pCol->zDflt = sqlite3DbStrNDup(db, (char*)pSpan->zStart, (int)(pSpan->zEnd - pSpan->zStart)); + sqlite3MemLink(p->aCol, pCol->zDflt); } } sqlite3ExprDelete(db, pSpan->pExpr); } @@ -1209,10 +1202,11 @@ if( !zColl ) return; if( sqlite3LocateCollSeq(pParse, zColl) ){ Index *pIdx; p->aCol[i].zColl = zColl; + sqlite3MemLink(p->aCol, zColl); /* If the column is declared as " PRIMARY KEY COLLATE ", ** then an index may have been created on this column before the ** collation type was added. Correct this if it is the case. */ @@ -1365,11 +1359,11 @@ zSep = "\n "; zSep2 = ",\n "; zEnd = "\n)"; } n += 35 + 6*p->nCol; - zStmt = sqlite3Malloc( n ); + zStmt = sqlite3DbMallocRaw(0, n); if( zStmt==0 ){ db->mallocFailed = 1; return 0; } sqlite3_snprintf(n, zStmt, "CREATE TABLE "); @@ -2811,14 +2805,11 @@ pIndex = 0; } /* Clean up before exiting */ exit_create_index: - if( pIndex ){ - sqlite3_free(pIndex->zColAff); - sqlite3DbFree(db, pIndex); - } + sqlite3DbFree(db, pIndex); sqlite3ExprListDelete(db, pList); sqlite3SrcListDelete(db, pTblName); sqlite3DbFree(db, zName); return pRet; } Index: src/callback.c ================================================================== --- src/callback.c +++ src/callback.c @@ -437,11 +437,11 @@ Schema *sqlite3SchemaGet(sqlite3 *db, Btree *pBt){ Schema * p; if( pBt ){ p = (Schema *)sqlite3BtreeSchema(pBt, sizeof(Schema), sqlite3SchemaFree); }else{ - p = (Schema *)sqlite3MallocZero(sizeof(Schema)); + p = (Schema *)sqlite3DbMallocZero(0, sizeof(Schema)); } if( !p ){ db->mallocFailed = 1; }else if ( 0==p->file_format ){ sqlite3HashInit(&p->tblHash); Index: src/func.c ================================================================== --- src/func.c +++ src/func.c @@ -1008,18 +1008,18 @@ nOut += nRep - nPattern; testcase( nOut-1==db->aLimit[SQLITE_LIMIT_LENGTH] ); testcase( nOut-2==db->aLimit[SQLITE_LIMIT_LENGTH] ); if( nOut-1>db->aLimit[SQLITE_LIMIT_LENGTH] ){ sqlite3_result_error_toobig(context); - sqlite3DbFree(db, zOut); + sqlite3_free(zOut); return; } zOld = zOut; zOut = sqlite3_realloc(zOut, (int)nOut); if( zOut==0 ){ sqlite3_result_error_nomem(context); - sqlite3DbFree(db, zOld); + sqlite3_free(zOld); return; } memcpy(&zOut[j], zRep, nRep); j += nRep; i += nPattern-1; @@ -1376,11 +1376,11 @@ pAccum = (StrAccum*)sqlite3_aggregate_context(context, sizeof(*pAccum)); if( pAccum ){ sqlite3 *db = sqlite3_context_db_handle(context); int firstTerm = pAccum->useMalloc==0; - pAccum->useMalloc = 1; + pAccum->useMalloc = 2; pAccum->mxAlloc = db->aLimit[SQLITE_LIMIT_LENGTH]; if( !firstTerm ){ if( argc==2 ){ zSep = (char*)sqlite3_value_text(argv[1]); nSep = sqlite3_value_bytes(argv[1]); Index: src/insert.c ================================================================== --- src/insert.c +++ src/insert.c @@ -65,11 +65,11 @@ ** up. */ int n; Table *pTab = pIdx->pTable; sqlite3 *db = sqlite3VdbeDb(v); - pIdx->zColAff = (char *)sqlite3Malloc(pIdx->nColumn+2); + pIdx->zColAff = (char *)sqlite3DbMallocRawChild(0, pIdx->nColumn+2, pIdx); if( !pIdx->zColAff ){ db->mallocFailed = 1; return 0; } for(n=0; nnColumn; n++){ @@ -107,16 +107,15 @@ if( !pTab->zColAff ){ char *zColAff; int i; sqlite3 *db = sqlite3VdbeDb(v); - zColAff = (char *)sqlite3Malloc(pTab->nCol+1); + zColAff = (char *)sqlite3DbMallocRawChild(0, pTab->nCol+1, pTab); if( !zColAff ){ db->mallocFailed = 1; return; } - for(i=0; inCol; i++){ zColAff[i] = pTab->aCol[i].affinity; } zColAff[pTab->nCol] = '\0'; Index: src/loadext.c ================================================================== --- src/loadext.c +++ src/loadext.c @@ -374,32 +374,28 @@ } handle = sqlite3OsDlOpen(pVfs, zFile); if( handle==0 ){ if( pzErrMsg ){ - zErrmsg = sqlite3StackAllocZero(db, nMsg); + *pzErrMsg = zErrmsg = sqlite3_malloc(nMsg); if( zErrmsg ){ sqlite3_snprintf(nMsg, zErrmsg, "unable to open shared library [%s]", zFile); sqlite3OsDlError(pVfs, nMsg-1, zErrmsg); - *pzErrMsg = sqlite3DbStrDup(0, zErrmsg); - sqlite3StackFree(db, zErrmsg); } } return SQLITE_ERROR; } xInit = (int(*)(sqlite3*,char**,const sqlite3_api_routines*)) sqlite3OsDlSym(pVfs, handle, zProc); if( xInit==0 ){ if( pzErrMsg ){ - zErrmsg = sqlite3StackAllocZero(db, nMsg); + *pzErrMsg = zErrmsg = sqlite3_malloc(nMsg); if( zErrmsg ){ sqlite3_snprintf(nMsg, zErrmsg, "no entry point [%s] in shared library [%s]", zProc,zFile); sqlite3OsDlError(pVfs, nMsg-1, zErrmsg); - *pzErrMsg = sqlite3DbStrDup(0, zErrmsg); - sqlite3StackFree(db, zErrmsg); } sqlite3OsDlClose(pVfs, handle); } return SQLITE_ERROR; }else if( xInit(db, &zErrmsg, &sqlite3Apis) ){ Index: src/malloc.c ================================================================== --- src/malloc.c +++ src/malloc.c @@ -13,10 +13,90 @@ ** Memory allocation functions used throughout sqlite. */ #include "sqliteInt.h" #include +/* +** There are two general-purpose memory allocators: +** +** Simple: +** +** sqlite3_malloc +** sqlite3_free +** sqlite3_realloc +** sqlite3Malloc +** sqlite3MallocSize +** sqlite3_mprintf +** +** Enhanced: +** +** sqlite3DbMallocRaw +** sqlite3DbMallocZero +** sqlite3DbFree +** sqlite3DbRealloc +** sqlite3MPrintf +** sqlite3DbMalloc +** +** All external allocations use the simple memory allocator. +** The enhanced allocator is used internally only, and is not +** available to extensions or applications. +** +** The enhanced allocator is a wrapper around the simple allocator that +** adds the following capabilities: +** +** (1) Access to lookaside memory associated with a database connection. +** +** (2) The ability to link allocations into a hierarchy with automatic +** deallocation of all elements of the subhierarchy whenever any +** element within the hierarchy is deallocated. +** +** The two allocators are incompatible in the sense that allocations that +** originate from the simple allocator must be deallocated using the simple +** deallocator and allocations that originate from the enhanced allocator must +** be deallocated using the enhanced deallocator. You cannot check-out +** memory from one allocator then return it to the other. +*/ + +/* +** The automatic hierarchical deallocation feature of the enhanced allocator +** is implemented by adding an instance of the following structure to the +** header of each enhanced allocation. +** +** In order to preserve alignment, this structure must be a multiple of +** 8 bytes in size. +*/ +typedef struct EMemHdr EMemHdr; +struct EMemHdr { + EMemHdr *pEChild; /* List of children of this node */ + EMemHdr *pESibling; /* Other nodes that are children of the same parent */ +#ifdef SQLITE_MEMDEBUG + u32 iEMemMagic; /* Magic number for sanity checking */ + u32 isAChild; /* True if this allocate is a child of another */ +#endif +}; + +/* +** Macros for querying and setting debugging fields of the EMemHdr object. +*/ +#ifdef SQLITE_MEMDEBUG +# define isValidEMem(E) ((E)->iEMemMagic==0xc0a43fad) +# define setValidEMem(E) (E)->iEMemMagic = 0xc0a43fad +# define clearValidEMem(E) (E)->iEMemMagic = 0x12345678 +# define isChildEMem(E) ((E)->isAChild!=0) +# define notChildEMem(E) ((E)->isAChild==0) +# define setChildEMem(E) (E)->isAChild = 1 +# define clearChildEMem(E) (E)->isAChild = 0 +#else +# define isValidEMem(E) 1 +# define setValidEMem(E) +# define clearValidEMem(E) +# define isChildEMem(E) 1 +# define notChildEMem(E) 1 +# define setChildEMem(E) +# define clearChildEMem(E) +#endif + /* ** This routine runs when the memory allocator sees that the ** total memory allocation is about to exceed the soft heap ** limit. */ @@ -30,10 +110,14 @@ } /* ** Set the soft heap-size limit for the library. Passing a zero or ** negative value indicates no limit. +** +** If the total amount of memory allocated (by all threads) exceeds +** the soft heap limit, then sqlite3_release_memory() is invoked to +** try to free up some memory before proceeding. */ void sqlite3_soft_heap_limit(int n){ sqlite3_uint64 iLimit; int overage; if( n<0 ){ @@ -366,10 +450,11 @@ if( p ){ if( sqlite3GlobalConfig.pScratch==0 || p=(void*)mem0.aScratchFree ){ assert( sqlite3MemdebugHasType(p, MEMTYPE_SCRATCH) ); + assert( sqlite3MemdebugNoType(p, ~MEMTYPE_SCRATCH) ); sqlite3MemdebugSetType(p, MEMTYPE_HEAP); if( sqlite3GlobalConfig.bMemstat ){ int iSize = sqlite3MallocSize(p); sqlite3_mutex_enter(mem0.mutex); sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_OVERFLOW, -iSize); @@ -415,31 +500,42 @@ #endif /* ** Return the size of a memory allocation previously obtained from ** sqlite3Malloc() or sqlite3_malloc(). +** +** The size returned is the usable size and does not include any +** bookkeeping overhead or sentinals at the end of the allocation. */ int sqlite3MallocSize(void *p){ assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) ); + assert( sqlite3MemdebugNoType(p, MEMTYPE_RECURSIVE) ); return sqlite3GlobalConfig.m.xSize(p); } -int sqlite3DbMallocSize(sqlite3 *db, void *p){ +int sqlite3DbMallocSize(sqlite3 *db, void *pObj){ + EMemHdr *p = (EMemHdr*)pObj; assert( db==0 || sqlite3_mutex_held(db->mutex) ); + if( p ){ + p--; + assert( isValidEMem(p) ); + } if( isLookaside(db, p) ){ - return db->lookaside.sz; + return db->lookaside.sz - sizeof(EMemHdr); }else{ + assert( sqlite3MemdebugHasType(p, MEMTYPE_RECURSIVE) ); assert( sqlite3MemdebugHasType(p, db ? (MEMTYPE_DB|MEMTYPE_HEAP) : MEMTYPE_HEAP) ); - return sqlite3GlobalConfig.m.xSize(p); + return sqlite3GlobalConfig.m.xSize(p) - sizeof(EMemHdr); } } /* ** Free memory previously obtained from sqlite3Malloc(). */ void sqlite3_free(void *p){ if( p==0 ) return; + assert( sqlite3MemdebugNoType(p, MEMTYPE_RECURSIVE) ); assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) ); if( sqlite3GlobalConfig.bMemstat ){ sqlite3_mutex_enter(mem0.mutex); sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, -sqlite3MallocSize(p)); sqlite3GlobalConfig.m.xFree(p); @@ -449,29 +545,51 @@ } } /* ** Free memory that might be associated with a particular database -** connection. +** connection. All child allocations are also freed. +** +** pObj must be a top-level allocation in the heirarchy. It is not +** allowed to delete a child allocation since that would leave a +** dangling child pointer in the parent. */ -void sqlite3DbFree(sqlite3 *db, void *p){ +void sqlite3DbFree(sqlite3 *db, void *pObj){ + EMemHdr *p = (EMemHdr*)pObj; assert( db==0 || sqlite3_mutex_held(db->mutex) ); - if( isLookaside(db, p) ){ - LookasideSlot *pBuf = (LookasideSlot*)p; - pBuf->pNext = db->lookaside.pFree; - db->lookaside.pFree = pBuf; - db->lookaside.nOut--; - }else{ - assert( sqlite3MemdebugHasType(p, - db ? (MEMTYPE_DB|MEMTYPE_HEAP) : MEMTYPE_HEAP) ); - sqlite3MemdebugSetType(p, MEMTYPE_HEAP); - sqlite3_free(p); + if( p ) p--; + assert( p==0 || notChildEMem(p) ); /* pObj is not child allocation */ + while( p ){ + EMemHdr *pNext = p->pESibling; + assert( isValidEMem(p) ); /* pObj and all siblings are valid */ + if( p->pEChild ){ + clearChildEMem(p->pEChild); + sqlite3DbFree(db, (void*)&p->pEChild[1]); + } + if( isLookaside(db, p) ){ + LookasideSlot *pBuf = (LookasideSlot*)p; + clearValidEMem(p); + pBuf->pNext = db->lookaside.pFree; + db->lookaside.pFree = pBuf; + db->lookaside.nOut--; + }else{ + assert( sqlite3MemdebugHasType(p, MEMTYPE_RECURSIVE) ); + assert( sqlite3MemdebugHasType(p, + db ? (MEMTYPE_DB|MEMTYPE_HEAP) : MEMTYPE_HEAP) ); + sqlite3MemdebugSetType(p, MEMTYPE_HEAP); + clearValidEMem(p); + sqlite3_free(p); + } + p = pNext; } } /* -** Change the size of an existing memory allocation +** Change the size of an existing memory allocation. +** +** This is the same as sqlite3_realloc() except that it assumes that +** the memory subsystem has already been initialized. */ void *sqlite3Realloc(void *pOld, int nBytes){ int nOld, nNew; void *pNew; if( pOld==0 ){ @@ -495,10 +613,11 @@ if( sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED)+nNew-nOld >= mem0.alarmThreshold ){ sqlite3MallocAlarm(nNew-nOld); } assert( sqlite3MemdebugHasType(pOld, MEMTYPE_HEAP) ); + assert( sqlite3MemdebugNoType(pOld, ~MEMTYPE_HEAP) ); pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nNew); if( pNew==0 && mem0.alarmCallback ){ sqlite3MallocAlarm(nBytes); pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nNew); } @@ -535,20 +654,35 @@ } return p; } /* -** Allocate and zero memory. If the allocation fails, make +** Allocate and zero memory. If the allocation fails, set ** the mallocFailed flag in the connection pointer. */ void *sqlite3DbMallocZero(sqlite3 *db, int n){ void *p = sqlite3DbMallocRaw(db, n); if( p ){ memset(p, 0, n); } return p; } + +/* +** Allocate and zero memory child memory. If the allocation fails, set +** the mallocFailed flag in the connection pointer. +*/ +void *sqlite3DbMallocZeroChild(sqlite3 *db, int n, void *pParent){ + void *p = sqlite3DbMallocRaw(db, n); + if( p ){ + memset(p, 0, n); + sqlite3MemLink(pParent, p); + } + return p; +} + + /* ** Allocate and zero memory. If the allocation fails, make ** the mallocFailed flag in the connection pointer. ** @@ -565,12 +699,13 @@ ** ** In other words, if a subsequent malloc (ex: "b") worked, it is assumed ** that all prior mallocs (ex: "a") worked too. */ void *sqlite3DbMallocRaw(sqlite3 *db, int n){ - void *p; + EMemHdr *p; assert( db==0 || sqlite3_mutex_held(db->mutex) ); + n += sizeof(EMemHdr); #ifndef SQLITE_OMIT_LOOKASIDE if( db ){ LookasideSlot *pBuf; if( db->mallocFailed ){ return 0; @@ -580,60 +715,92 @@ db->lookaside.pFree = pBuf->pNext; db->lookaside.nOut++; if( db->lookaside.nOut>db->lookaside.mxOut ){ db->lookaside.mxOut = db->lookaside.nOut; } - return (void*)pBuf; + p = (EMemHdr*)pBuf; + goto finish_emalloc_raw; } } #else if( db && db->mallocFailed ){ return 0; } #endif p = sqlite3Malloc(n); - if( !p && db ){ - db->mallocFailed = 1; + if( !p ){ + if( db ) db->mallocFailed = 1; + return 0; } - sqlite3MemdebugSetType(p, - (db && db->lookaside.bEnabled) ? MEMTYPE_DB : MEMTYPE_HEAP); + sqlite3MemdebugSetType(p, MEMTYPE_RECURSIVE | + ((db && db->lookaside.bEnabled) ? MEMTYPE_DB : MEMTYPE_HEAP)); + +finish_emalloc_raw: + memset(p, 0, sizeof(EMemHdr)); + setValidEMem(p); + return (void*)&p[1]; +} + +/* +** A convenience wrapper around sqlite3DbMallocRaw() and sqlite3MemLink(). +*/ +void *sqlite3DbMallocRawChild(sqlite3 *db, int n, void *pParent){ + void *p = sqlite3DbMallocRaw(db, n); + sqlite3MemLink(pParent, p); return p; } /* ** Resize the block of memory pointed to by p to n bytes. If the ** resize fails, set the mallocFailed flag in the connection object. +** +** The pOld memory block must not be linked into an allocation hierarchy +** as a child. It is OK for the allocation to be the root of a hierarchy +** of allocations; the only restriction is that there must be no other +** allocations above the pOld allocation in the hierarchy. To resize +** an allocation that is a child within a hierarchy, first +** unlink the allocation, resize it, then relink it. */ -void *sqlite3DbRealloc(sqlite3 *db, void *p, int n){ - void *pNew = 0; +void *sqlite3DbRealloc(sqlite3 *db, void *pOld, int n){ + EMemHdr *p = (EMemHdr*)pOld; + EMemHdr *pNew = 0; assert( db!=0 ); assert( sqlite3_mutex_held(db->mutex) ); if( db->mallocFailed==0 ){ if( p==0 ){ return sqlite3DbMallocRaw(db, n); } + p--; + assert( isValidEMem(p) ); /* pOld obtained from extended allocator */ + assert( notChildEMem(p) ); /* pOld must not be a child allocation */ if( isLookaside(db, p) ){ - if( n<=db->lookaside.sz ){ - return p; + if( n+sizeof(EMemHdr)<=db->lookaside.sz ){ + return pOld; } pNew = sqlite3DbMallocRaw(db, n); if( pNew ){ - memcpy(pNew, p, db->lookaside.sz); - sqlite3DbFree(db, p); + memcpy(pNew-1, p, db->lookaside.sz); + setValidEMem(pNew-1); + sqlite3DbFree(db, pOld); } }else{ + assert( sqlite3MemdebugHasType(p, MEMTYPE_RECURSIVE) ); assert( sqlite3MemdebugHasType(p, MEMTYPE_DB|MEMTYPE_HEAP) ); sqlite3MemdebugSetType(p, MEMTYPE_HEAP); - pNew = sqlite3_realloc(p, n); + pNew = sqlite3_realloc(p, n+sizeof(EMemHdr)); if( !pNew ){ + sqlite3MemdebugSetType(p, MEMTYPE_RECURSIVE|MEMTYPE_HEAP); db->mallocFailed = 1; + }else{ + sqlite3MemdebugSetType(pNew, MEMTYPE_RECURSIVE | + (db->lookaside.bEnabled ? MEMTYPE_DB : MEMTYPE_HEAP)); + setValidEMem(pNew); + pNew++; } - sqlite3MemdebugSetType(pNew, - db->lookaside.bEnabled ? MEMTYPE_DB : MEMTYPE_HEAP); } } - return pNew; + return (void*)pNew; } /* ** Attempt to reallocate p. If the reallocation fails, then free p ** and set the mallocFailed flag in the database connection. @@ -679,10 +846,57 @@ memcpy(zNew, z, n); zNew[n] = 0; } return zNew; } + +/* +** Link extended allocation nodes such that deallocating the parent +** causes the child to be automatically deallocated. +*/ +void sqlite3MemLink(void *pParentObj, void *pChildObj){ + EMemHdr *pParent = (EMemHdr*)pParentObj; + EMemHdr *pChild = (EMemHdr*)pChildObj; + if( pParent && pChild ){ + pParent--; + assert( isValidEMem(pParent) ); /* pParentObj is an extended allocation */ + pChild--; + assert( isValidEMem(pChild) ); /* pChildObj is an extended allocation */ + assert( notChildEMem(pChild) ); /* pChildObj not a child of another obj */ + pChild->pESibling = pParent->pEChild; + pParent->pEChild = pChild; + setChildEMem(pChild); + } +} + +/* +** pChildObj is a child object of pParentObj due to a prior call +** to sqlite3MemLink(). This routine breaks that linkage, making +** pChildObj an independent node that is not a child of any other node. +*/ +void sqlite3MemUnlink(void *pParentObj, void *pChildObj){ + EMemHdr *pParent = (EMemHdr*)pParentObj; + EMemHdr *pChild = (EMemHdr*)pChildObj; + EMemHdr **pp; + + assert( pParentObj!=0 ); + assert( pChildObj!=0 ); + pParent--; + assert( isValidEMem(pParent) ); /* pParentObj is an extended allocation */ + pChild--; + assert( isValidEMem(pChild) ); /* pChildObj is an extended allocation */ + assert( isChildEMem(pChild) ); /* pChildObj a child of something */ + for(pp=&pParent->pEChild; (*pp)!=pChild; pp = &(*pp)->pESibling){ + assert( *pp ); /* pChildObj is a child of pParentObj */ + assert( isValidEMem(*pp) ); /* All children of pParentObj are valid */ + assert( isChildEMem(*pp) ); /* All children of pParentObj are children */ + } + *pp = pChild->pESibling; + pChild->pESibling = 0; + clearChildEMem(pChild); +} + /* ** Create a string from the zFromat argument and the va_list that follows. ** Store the string in memory obtained from sqliteMalloc() and make *pz ** point to that string. Index: src/mem2.c ================================================================== --- src/mem2.c +++ src/mem2.c @@ -399,23 +399,38 @@ int rc = 1; if( p ){ struct MemBlockHdr *pHdr; pHdr = sqlite3MemsysGetHeader(p); assert( pHdr->iForeGuard==FOREGUARD ); /* Allocation is valid */ - assert( (pHdr->eType & (pHdr->eType-1))==0 ); /* Only one type bit set */ if( (pHdr->eType&eType)==0 ){ - void **pBt; - pBt = (void**)pHdr; - pBt -= pHdr->nBacktraceSlots; - backtrace_symbols_fd(pBt, pHdr->nBacktrace, fileno(stderr)); - fprintf(stderr, "\n"); rc = 0; } } return rc; } +/* +** Return TRUE if the mask of type in eType matches no bits of the type of the +** allocation p. Also return true if p==NULL. +** +** This routine is designed for use within an assert() statement, to +** verify the type of an allocation. For example: +** +** assert( sqlite3MemdebugNoType(p, MEMTYPE_DB) ); +*/ +int sqlite3MemdebugNoType(void *p, u8 eType){ + int rc = 1; + if( p ){ + struct MemBlockHdr *pHdr; + pHdr = sqlite3MemsysGetHeader(p); + assert( pHdr->iForeGuard==FOREGUARD ); /* Allocation is valid */ + if( (pHdr->eType&eType)!=0 ){ + rc = 0; + } + } + return rc; +} /* ** Set the number of backtrace levels kept for each allocation. ** A value of zero turns off backtracing. The number is always rounded ** up to a multiple of 2. Index: src/notify.c ================================================================== --- src/notify.c +++ src/notify.c @@ -253,11 +253,11 @@ sqlite3BeginBenignMalloc(); assert( aArg==aDyn || (aDyn==0 && aArg==aStatic) ); assert( nArg<=(int)ArraySize(aStatic) || aArg==aDyn ); if( (!aDyn && nArg==(int)ArraySize(aStatic)) - || (aDyn && nArg==(int)(sqlite3DbMallocSize(db, aDyn)/sizeof(void*))) + || (aDyn && nArg==(int)(sqlite3MallocSize(aDyn)/sizeof(void*))) ){ /* The aArg[] array needs to grow. */ void **pNew = (void **)sqlite3Malloc(nArg*sizeof(void *)*2); if( pNew ){ memcpy(pNew, aArg, nArg*sizeof(void *)); Index: src/pragma.c ================================================================== --- src/pragma.c +++ src/pragma.c @@ -763,11 +763,11 @@ ){ invalidateTempStorage(pParse); } sqlite3_free(sqlite3_temp_directory); if( zRight[0] ){ - sqlite3_temp_directory = sqlite3DbStrDup(0, zRight); + sqlite3_temp_directory = sqlite3_mprintf("%s", zRight); }else{ sqlite3_temp_directory = 0; } #endif /* SQLITE_OMIT_WSD */ } Index: src/printf.c ================================================================== --- src/printf.c +++ src/printf.c @@ -770,11 +770,15 @@ p->tooBig = 1; return; }else{ p->nAlloc = (int)szNew; } - zNew = sqlite3DbMallocRaw(p->db, p->nAlloc ); + if( p->useMalloc==1 ){ + zNew = sqlite3DbMallocRaw(p->db, p->nAlloc ); + }else{ + zNew = sqlite3_malloc(p->nAlloc); + } if( zNew ){ memcpy(zNew, p->zText, p->nChar); sqlite3StrAccumReset(p); p->zText = zNew; }else{ @@ -795,11 +799,15 @@ */ char *sqlite3StrAccumFinish(StrAccum *p){ if( p->zText ){ p->zText[p->nChar] = 0; if( p->useMalloc && p->zText==p->zBase ){ - p->zText = sqlite3DbMallocRaw(p->db, p->nChar+1 ); + if( p->useMalloc==1 ){ + p->zText = sqlite3DbMallocRaw(p->db, p->nChar+1 ); + }else{ + p->zText = sqlite3_malloc(p->nChar+1); + } if( p->zText ){ memcpy(p->zText, p->zBase, p->nChar+1); }else{ p->mallocFailed = 1; } @@ -811,11 +819,15 @@ /* ** Reset an StrAccum string. Reclaim all malloced memory. */ void sqlite3StrAccumReset(StrAccum *p){ if( p->zText!=p->zBase ){ - sqlite3DbFree(p->db, p->zText); + if( p->useMalloc==1 ){ + sqlite3DbFree(p->db, p->zText); + }else{ + sqlite3_free(p->zText); + } } p->zText = 0; } /* @@ -893,10 +905,11 @@ StrAccum acc; #ifndef SQLITE_OMIT_AUTOINIT if( sqlite3_initialize() ) return 0; #endif sqlite3StrAccumInit(&acc, zBase, sizeof(zBase), SQLITE_MAX_LENGTH); + acc.useMalloc = 2; sqlite3VXPrintf(&acc, 0, zFormat, ap); z = sqlite3StrAccumFinish(&acc); return z; } Index: src/select.c ================================================================== --- src/select.c +++ src/select.c @@ -1266,15 +1266,17 @@ sNC.pSrcList = pSelect->pSrc; a = pSelect->pEList->a; for(i=0, pCol=aCol; izType = sqlite3DbStrDup(db, columnType(&sNC, p, 0, 0, 0)); + sqlite3MemLink(aCol, pCol->zType); pCol->affinity = sqlite3ExprAffinity(p); if( pCol->affinity==0 ) pCol->affinity = SQLITE_AFF_NONE; pColl = sqlite3ExprCollSeq(pParse, p); if( pColl ){ pCol->zColl = sqlite3DbStrDup(db, pColl->zName); + sqlite3MemLink(aCol, pCol->zColl); } } } /* @@ -3095,10 +3097,11 @@ sqlite3WalkSelect(pWalker, pSel); pFrom->pTab = pTab = sqlite3DbMallocZero(db, sizeof(Table)); if( pTab==0 ) return WRC_Abort; pTab->nRef = 1; pTab->zName = sqlite3MPrintf(db, "sqlite_subquery_%p_", (void*)pTab); + sqlite3MemLink(pTab, pTab->zName); while( pSel->pPrior ){ pSel = pSel->pPrior; } selectColumnsFromExprList(pParse, pSel->pEList, &pTab->nCol, &pTab->aCol); pTab->iPKey = -1; pTab->tabFlags |= TF_Ephemeral; #endif Index: src/sqliteInt.h ================================================================== --- src/sqliteInt.h +++ src/sqliteInt.h @@ -2323,11 +2323,11 @@ char *zText; /* The string collected so far */ int nChar; /* Length of the string so far */ int nAlloc; /* Amount of space allocated in zText */ int mxAlloc; /* Maximum allowed string length */ u8 mallocFailed; /* Becomes true if any memory allocation fails */ - u8 useMalloc; /* True if zText is enlargeable using realloc */ + u8 useMalloc; /* 0: none, 1: sqlite3DbMalloc, 2: sqlite3_malloc */ u8 tooBig; /* Becomes true if string size exceeds limits */ }; /* ** A pointer to this structure is used to communicate information @@ -2485,16 +2485,20 @@ void sqlite3MallocEnd(void); void *sqlite3Malloc(int); void *sqlite3MallocZero(int); void *sqlite3DbMallocZero(sqlite3*, int); void *sqlite3DbMallocRaw(sqlite3*, int); +void *sqlite3DbMallocZeroChild(sqlite3*, int, void *pParent); +void *sqlite3DbMallocRawChild(sqlite3*, int, void *pParent); char *sqlite3DbStrDup(sqlite3*,const char*); char *sqlite3DbStrNDup(sqlite3*,const char*, int); void *sqlite3Realloc(void*, int); void *sqlite3DbReallocOrFree(sqlite3 *, void *, int); void *sqlite3DbRealloc(sqlite3 *, void *, int); void sqlite3DbFree(sqlite3*, void*); +void sqlite3MemLink(void *pParent, void *pChild); +void sqlite3MemUnlink(void *pParent, void *pChild); int sqlite3MallocSize(void*); int sqlite3DbMallocSize(sqlite3*, void*); void *sqlite3ScratchMalloc(int); void sqlite3ScratchFree(void*); void *sqlite3PageMalloc(int); @@ -2906,11 +2910,10 @@ void sqlite3Analyze(Parse*, Token*, Token*); int sqlite3InvokeBusyHandler(BusyHandler*); int sqlite3FindDb(sqlite3*, Token*); int sqlite3FindDbName(sqlite3 *, const char *); int sqlite3AnalysisLoad(sqlite3*,int iDB); -void sqlite3DeleteIndexSamples(Index*); void sqlite3DefaultRowEst(Index*); void sqlite3RegisterLikeFunctions(sqlite3*, int); int sqlite3IsLikeFunction(sqlite3*,Expr*,int*,char*); void sqlite3MinimumFileFormat(Parse*, int, int); void sqlite3SchemaFree(void *); @@ -3116,10 +3119,14 @@ ** a single bit set. ** ** sqlite3MemdebugHasType() returns true if any of the bits in its second ** argument match the type set by the previous sqlite3MemdebugSetType(). ** sqlite3MemdebugHasType() is intended for use inside assert() statements. +** +** sqlite3MemdebugNoType() returns true if none of the bits in its second +** argument match the type set by the previous sqlite3MemdebugSetType(). +** ** For example: ** ** assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) ); ** ** Perhaps the most important point is the difference between MEMTYPE_HEAP @@ -3134,15 +3141,18 @@ ** play when the SQLITE_MEMDEBUG compile-time option is used. */ #ifdef SQLITE_MEMDEBUG void sqlite3MemdebugSetType(void*,u8); int sqlite3MemdebugHasType(void*,u8); + int sqlite3MemdebugNoType(void*,u8); #else # define sqlite3MemdebugSetType(X,Y) /* no-op */ # define sqlite3MemdebugHasType(X,Y) 1 +# define sqlite3MemdebugNoType(X,Y) 1 #endif -#define MEMTYPE_HEAP 0x01 /* General heap allocations */ -#define MEMTYPE_DB 0x02 /* Associated with a database connection */ -#define MEMTYPE_SCRATCH 0x04 /* Scratch allocations */ -#define MEMTYPE_PCACHE 0x08 /* Page cache allocations */ +#define MEMTYPE_HEAP 0x01 /* General heap allocations */ +#define MEMTYPE_DB 0x02 /* Associated with a database connection */ +#define MEMTYPE_SCRATCH 0x04 /* Scratch allocations */ +#define MEMTYPE_PCACHE 0x08 /* Page cache allocations */ +#define MEMTYPE_RECURSIVE 0x10 /* Experimental */ #endif /* _SQLITEINT_H_ */ Index: src/test4.c ================================================================== --- src/test4.c +++ src/test4.c @@ -140,11 +140,11 @@ Tcl_AppendResult(interp, "thread ", argv[1], " is already running", 0); return TCL_ERROR; } threadset[i].busy = 1; sqlite3_free(threadset[i].zFilename); - threadset[i].zFilename = sqlite3DbStrDup(0, argv[2]); + threadset[i].zFilename = sqlite3_mprintf("%s", argv[2]); threadset[i].opnum = 1; threadset[i].completed = 0; rc = pthread_create(&x, 0, thread_main, &threadset[i]); if( rc ){ Tcl_AppendResult(interp, "failed to create the thread", 0); @@ -474,11 +474,11 @@ return TCL_ERROR; } thread_wait(&threadset[i]); threadset[i].xOp = do_compile; sqlite3_free(threadset[i].zArg); - threadset[i].zArg = sqlite3DbStrDup(0, argv[2]); + threadset[i].zArg = sqlite3_mprintf("%s", argv[2]); threadset[i].opnum++; return TCL_OK; } /* Index: src/test5.c ================================================================== --- src/test5.c +++ src/test5.c @@ -153,11 +153,11 @@ pVal = sqlite3ValueNew(0); if( enc_from==SQLITE_UTF8 ){ z = Tcl_GetString(objv[1]); if( objc==5 ){ - z = sqlite3DbStrDup(0, z); + z = sqlite3_mprintf("%s", z); } sqlite3ValueSetStr(pVal, -1, z, enc_from, xDel); }else{ z = (char*)Tcl_GetByteArrayFromObj(objv[1], &len); if( objc==5 ){ Index: src/test7.c ================================================================== --- src/test7.c +++ src/test7.c @@ -162,11 +162,11 @@ Tcl_AppendResult(interp, "thread ", argv[1], " is already running", 0); return TCL_ERROR; } threadset[i].busy = 1; sqlite3_free(threadset[i].zFilename); - threadset[i].zFilename = sqlite3DbStrDup(0, argv[2]); + threadset[i].zFilename = sqlite3_mprintf("%s", argv[2]); threadset[i].opnum = 1; threadset[i].completed = 0; rc = pthread_create(&x, 0, client_main, &threadset[i]); if( rc ){ Tcl_AppendResult(interp, "failed to create the thread", 0); @@ -505,11 +505,11 @@ return TCL_ERROR; } client_wait(&threadset[i]); threadset[i].xOp = do_compile; sqlite3_free(threadset[i].zArg); - threadset[i].zArg = sqlite3DbStrDup(0, argv[2]); + threadset[i].zArg = sqlite3_mprintf("%s", argv[2]); threadset[i].opnum++; return TCL_OK; } /* Index: src/test8.c ================================================================== --- src/test8.c +++ src/test8.c @@ -483,11 +483,11 @@ pVtab->zLogName = sqlite3_mprintf("%s", argv[4]); zSql = sqlite3_mprintf("CREATE TABLE %Q(logmsg)", pVtab->zLogName); rc = sqlite3_exec(db, zSql, 0, 0, 0); sqlite3_free(zSql); if( rc!=SQLITE_OK ){ - *pzErr = sqlite3DbStrDup(0, sqlite3_errmsg(db)); + *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db)); } } if( *ppVtab && rc!=SQLITE_OK ){ echoDestructor(*ppVtab); Index: src/tokenize.c ================================================================== --- src/tokenize.c +++ src/tokenize.c @@ -494,11 +494,11 @@ pParse->aTableLock = 0; pParse->nTableLock = 0; } #endif #ifndef SQLITE_OMIT_VIRTUALTABLE - sqlite3DbFree(db, pParse->apVtabLock); + sqlite3_free(pParse->apVtabLock); #endif if( !IN_DECLARE_VTAB ){ /* If the pParse->declareVtab flag is set, do not delete any table ** structure built up in pParse->pNewTable. The calling code (see vtab.c) Index: src/vdbe.c ================================================================== --- src/vdbe.c +++ src/vdbe.c @@ -498,10 +498,24 @@ for(p=db->pSavepoint; p; p=p->pNext) n++; assert( n==(db->nSavepoint + db->isTransactionSavepoint) ); return 1; } #endif + +/* +** Transfer error message text from an sqlite3_vtab.zErrMsg (text stored +** in memory obtained from sqlite3_malloc) into a Vdbe.zErrMsg (text stored +** in memory obtained from sqlite3DbMalloc). +*/ +static void importVtabErrMsg(Vdbe *p, sqlite3_vtab *pVtab){ + sqlite3 *db = p->db; + sqlite3DbFree(db, p->zErrMsg); + p->zErrMsg = sqlite3DbStrDup(db, pVtab->zErrMsg); + sqlite3_free(pVtab->zErrMsg); + pVtab->zErrMsg = 0; +} + /* ** Execute as much of a VDBE program as we can then return. ** ** sqlite3VdbeMakeReady() must be called before this routine in order to @@ -4028,13 +4042,11 @@ }else if( pC->pVtabCursor ){ pVtab = pC->pVtabCursor->pVtab; pModule = pVtab->pModule; assert( pModule->xRowid ); rc = pModule->xRowid(pC->pVtabCursor, &v); - sqlite3DbFree(db, p->zErrMsg); - p->zErrMsg = pVtab->zErrMsg; - pVtab->zErrMsg = 0; + importVtabErrMsg(p, pVtab); #endif /* SQLITE_OMIT_VIRTUALTABLE */ }else{ assert( pC->pCursor!=0 ); rc = sqlite3VdbeCursorMoveto(pC); if( rc ) goto abort_due_to_error; @@ -5373,15 +5385,11 @@ */ case OP_VBegin: { VTable *pVTab; pVTab = pOp->p4.pVtab; rc = sqlite3VtabBegin(db, pVTab); - if( pVTab ){ - sqlite3DbFree(db, p->zErrMsg); - p->zErrMsg = pVTab->pVtab->zErrMsg; - pVTab->pVtab->zErrMsg = 0; - } + if( pVTab ) importVtabErrMsg(p, pVTab->pVtab); break; } #endif /* SQLITE_OMIT_VIRTUALTABLE */ #ifndef SQLITE_OMIT_VIRTUALTABLE @@ -5427,13 +5435,11 @@ pVtabCursor = 0; pVtab = pOp->p4.pVtab->pVtab; pModule = (sqlite3_module *)pVtab->pModule; assert(pVtab && pModule); rc = pModule->xOpen(pVtab, &pVtabCursor); - sqlite3DbFree(db, p->zErrMsg); - p->zErrMsg = pVtab->zErrMsg; - pVtab->zErrMsg = 0; + importVtabErrMsg(p, pVtab); if( SQLITE_OK==rc ){ /* Initialize sqlite3_vtab_cursor base class */ pVtabCursor->pVtab = pVtab; /* Initialise vdbe cursor object */ @@ -5506,13 +5512,11 @@ } p->inVtabMethod = 1; rc = pModule->xFilter(pVtabCursor, iQuery, pOp->p4.z, nArg, apArg); p->inVtabMethod = 0; - sqlite3DbFree(db, p->zErrMsg); - p->zErrMsg = pVtab->zErrMsg; - pVtab->zErrMsg = 0; + importVtabErrMsg(p, pVtab); if( rc==SQLITE_OK ){ res = pModule->xEof(pVtabCursor); } if( res ){ @@ -5558,13 +5562,11 @@ */ sqlite3VdbeMemMove(&sContext.s, pDest); MemSetTypeFlag(&sContext.s, MEM_Null); rc = pModule->xColumn(pCur->pVtabCursor, &sContext, pOp->p2); - sqlite3DbFree(db, p->zErrMsg); - p->zErrMsg = pVtab->zErrMsg; - pVtab->zErrMsg = 0; + importVtabErrMsg(p, pVtab); if( sContext.isError ){ rc = sContext.isError; } /* Copy the result of the function to the P3 register. We @@ -5613,13 +5615,11 @@ ** some other method is next invoked on the save virtual table cursor. */ p->inVtabMethod = 1; rc = pModule->xNext(pCur->pVtabCursor); p->inVtabMethod = 0; - sqlite3DbFree(db, p->zErrMsg); - p->zErrMsg = pVtab->zErrMsg; - pVtab->zErrMsg = 0; + importVtabErrMsg(p, pVtab); if( rc==SQLITE_OK ){ res = pModule->xEof(pCur->pVtabCursor); } if( !res ){ @@ -5645,13 +5645,11 @@ pName = &aMem[pOp->p1]; assert( pVtab->pModule->xRename ); REGISTER_TRACE(pOp->p1, pName); assert( pName->flags & MEM_Str ); rc = pVtab->pModule->xRename(pVtab, pName->z); - sqlite3DbFree(db, p->zErrMsg); - p->zErrMsg = pVtab->zErrMsg; - pVtab->zErrMsg = 0; + importVtabErrMsg(p, pVtab); break; } #endif @@ -5699,13 +5697,11 @@ sqlite3VdbeMemStoreType(pX); apArg[i] = pX; pX++; } rc = pModule->xUpdate(pVtab, nArg, apArg, &rowid); - sqlite3DbFree(db, p->zErrMsg); - p->zErrMsg = pVtab->zErrMsg; - pVtab->zErrMsg = 0; + importVtabErrMsg(p, pVtab); if( rc==SQLITE_OK && pOp->p1 ){ assert( nArg>1 && apArg[0] && (apArg[0]->flags&MEM_Null) ); db->lastRowid = rowid; } p->nChange++; Index: src/vdbeaux.c ================================================================== --- src/vdbeaux.c +++ src/vdbeaux.c @@ -579,17 +579,20 @@ static void freeP4(sqlite3 *db, int p4type, void *p4){ if( p4 ){ switch( p4type ){ case P4_REAL: case P4_INT64: - case P4_MPRINTF: case P4_DYNAMIC: case P4_KEYINFO: case P4_INTARRAY: case P4_KEYINFO_HANDOFF: { sqlite3DbFree(db, p4); break; + } + case P4_MPRINTF: { + sqlite3_free(p4); + break; } case P4_VDBEFUNC: { VdbeFunc *pVdbeFunc = (VdbeFunc *)p4; freeEphemeralFunction(db, pVdbeFunc->pFunc); sqlite3VdbeDeleteAuxData(pVdbeFunc, 0); @@ -737,11 +740,11 @@ KeyInfo *pKeyInfo; int nField, nByte; nField = ((KeyInfo*)zP4)->nField; nByte = sizeof(*pKeyInfo) + (nField-1)*sizeof(pKeyInfo->aColl[0]) + nField; - pKeyInfo = sqlite3Malloc( nByte ); + pKeyInfo = sqlite3DbMallocRaw(0, nByte); pOp->p4.pKeyInfo = pKeyInfo; if( pKeyInfo ){ u8 *aSortOrder; memcpy((char*)pKeyInfo, zP4, nByte - nField); aSortOrder = pKeyInfo->aSortOrder; Index: src/vtab.c ================================================================== --- src/vtab.c +++ src/vtab.c @@ -464,11 +464,11 @@ if( SQLITE_OK!=rc ){ if( zErr==0 ){ *pzErr = sqlite3MPrintf(db, "vtable constructor failed: %s", zModuleName); }else { *pzErr = sqlite3MPrintf(db, "%s", zErr); - sqlite3DbFree(db, zErr); + sqlite3_free(zErr); } sqlite3DbFree(db, pVTable); }else if( ALWAYS(pVTable->pVtab) ){ /* Justification of ALWAYS(): A correct vtab constructor must allocate ** the sqlite3_vtab object if successful. */ @@ -671,11 +671,11 @@ pParse->pNewTable->aCol = 0; } db->pVTab = 0; }else{ sqlite3Error(db, SQLITE_ERROR, zErr); - sqlite3DbFree(db, zErr); + sqlite3_free(zErr); rc = SQLITE_ERROR; } pParse->declareVtab = 0; if( pParse->pVdbe ){ @@ -766,12 +766,12 @@ int (*x)(sqlite3_vtab *); sqlite3_vtab *pVtab = aVTrans[i]->pVtab; if( pVtab && (x = pVtab->pModule->xSync)!=0 ){ rc = x(pVtab); sqlite3DbFree(db, *pzErrmsg); - *pzErrmsg = pVtab->zErrMsg; - pVtab->zErrMsg = 0; + *pzErrmsg = sqlite3DbStrDup(db, pVtab->zErrMsg); + sqlite3_free(pVtab->zErrMsg); } } db->aVTrans = aVTrans; return rc; } Index: src/where.c ================================================================== --- src/where.c +++ src/where.c @@ -2023,11 +2023,11 @@ sqlite3ErrorMsg(pParse, "%s", sqlite3ErrStr(rc)); }else{ sqlite3ErrorMsg(pParse, "%s", pVtab->zErrMsg); } } - sqlite3DbFree(pParse->db, pVtab->zErrMsg); + sqlite3_free(pVtab->zErrMsg); pVtab->zErrMsg = 0; for(i=0; inConstraint; i++){ if( !p->aConstraint[i].usable && p->aConstraintUsage[i].argvIndex>0 ){ sqlite3ErrorMsg(pParse, @@ -3803,14 +3803,11 @@ } sqlite3DbFree(db, pInfo); } if( pWInfo->a[i].plan.wsFlags & WHERE_TEMP_INDEX ){ Index *pIdx = pWInfo->a[i].plan.u.pIdx; - if( pIdx ){ - sqlite3DbFree(db, pIdx->zColAff); - sqlite3DbFree(db, pIdx); - } + sqlite3DbFree(db, pIdx); } } whereClauseClear(pWInfo->pWC); sqlite3DbFree(db, pWInfo); }