Index: src/vdbe.c ================================================================== --- src/vdbe.c +++ src/vdbe.c @@ -2435,14 +2435,14 @@ ** all valid. */ assert( p2nHdrParsed ); assert( rc==SQLITE_OK ); assert( sqlite3VdbeCheckMemInvariants(pDest) ); + VdbeMemReleaseExtern(pDest); if( pC->szRow>=aOffset[p2+1] ){ /* This is the common case where the desired content fits on the original ** page - where the content is not on an overflow page */ - VdbeMemReleaseExtern(pDest); sqlite3VdbeSerialGet(pC->aRow+aOffset[p2], aType[p2], pDest); }else{ /* This branch happens only when content is on overflow pages */ t = aType[p2]; if( ((pOp->p5 & (OPFLAG_LENGTHARG|OPFLAG_TYPEOFARG))!=0 Index: src/vdbeaux.c ================================================================== --- src/vdbeaux.c +++ src/vdbeaux.c @@ -3304,10 +3304,11 @@ Mem c1; Mem c2; c1.db = c2.db = pMem1->db; c1.flags = c2.flags = 0; c1.zMalloc = c2.zMalloc = 0; + c1.xDel = c2.xDel = 0; sqlite3VdbeMemShallowCopy(&c1, pMem1, MEM_Ephem); sqlite3VdbeMemShallowCopy(&c2, pMem2, MEM_Ephem); v1 = sqlite3ValueText((sqlite3_value*)&c1, pColl->enc); n1 = v1==0 ? 0 : c1.n; v2 = sqlite3ValueText((sqlite3_value*)&c2, pColl->enc); Index: src/vdbemem.c ================================================================== --- src/vdbemem.c +++ src/vdbemem.c @@ -308,13 +308,17 @@ } return rc; } /* -** If the memory cell contains a string value that must be freed by -** invoking an external callback, free it now. Calling this function -** does not free any Mem.zMalloc buffer. +** If the memory cell contains a value that must be freed by +** invoking an external callback, then free it now. +** +** This routine does NOT do any of the following: +** (1) Set the Mem.flags field to a rational value. +** (2) Free memory held by Mem.zMalloc +** The caller is expected to take care of setting Mem.flags appropriately. ** ** The VdbeMemReleaseExtern() macro invokes this routine if only if there ** is work for this routine to do. */ void sqlite3VdbeMemReleaseExternal(Mem *p){ @@ -338,12 +342,12 @@ /* ** Release memory held by the Mem p, both external memory cleared ** by p->xDel and memory in p->zMalloc. ** ** This is a helper routine invoked by sqlite3VdbeMemRelease() in -** the uncommon case when there really is memory in p that is -** need of freeing. +** the uncommon case when there really is memory in p that needs +** to be freeing. */ static SQLITE_NOINLINE void vdbeMemRelease(Mem *p){ if( VdbeMemDynamic(p) ){ sqlite3VdbeMemReleaseExternal(p); } @@ -353,13 +357,15 @@ } p->z = 0; } /* -** Release any memory held by the Mem. This may leave the Mem in an -** inconsistent state, for example with (Mem.z==0) and -** (Mem.flags==MEM_Str). +** Release any memory held by the Mem. This may leave the Mem.flags in an +** inconsistent state, for example with (Mem.z==0) and (Mem.flags==MEM_Str). +** +** This routine releases both the Mem.xDel space and the Mem.zMalloc space. +** Use sqlite3VdbeMemReleaseExternal() to release just the Mem.xDel space. */ void sqlite3VdbeMemRelease(Mem *p){ assert( sqlite3VdbeCheckMemInvariants(p) ); if( VdbeMemDynamic(p) || p->zMalloc ){ vdbeMemRelease(p); @@ -731,11 +737,11 @@ void sqlite3VdbeMemShallowCopy(Mem *pTo, const Mem *pFrom, int srcType){ assert( (pFrom->flags & MEM_RowSet)==0 ); assert( pTo->db==pFrom->db ); VdbeMemReleaseExtern(pTo); memcpy(pTo, pFrom, MEMCELLSIZE); - pTo->xDel = 0; + assert( pTo->xDel==0 ); if( (pFrom->flags&MEM_Static)==0 ){ pTo->flags &= ~(MEM_Dyn|MEM_Static|MEM_Ephem); assert( srcType==MEM_Ephem || srcType==MEM_Static ); pTo->flags |= srcType; } @@ -751,11 +757,11 @@ assert( pTo->db==pFrom->db ); assert( (pFrom->flags & MEM_RowSet)==0 ); VdbeMemReleaseExtern(pTo); memcpy(pTo, pFrom, MEMCELLSIZE); pTo->flags &= ~MEM_Dyn; - pTo->xDel = 0; + assert( pTo->xDel==0 ); if( pTo->flags&(MEM_Str|MEM_Blob) ){ if( 0==(pFrom->flags&MEM_Static) ){ pTo->flags |= MEM_Ephem; rc = sqlite3VdbeMemMakeWriteable(pTo); @@ -904,10 +910,11 @@ char *zData; /* Data from the btree layer */ u32 available = 0; /* Number of bytes available on the local btree page */ int rc = SQLITE_OK; /* Return code */ assert( sqlite3BtreeCursorIsValid(pCur) ); + assert( pMem->xDel==0 ); /* Note: the calls to BtreeKeyFetch() and DataFetch() below assert() ** that both the BtShared and database handle mutexes are held. */ assert( (pMem->flags & MEM_RowSet)==0 ); if( key ){ @@ -920,23 +927,26 @@ if( offset+amt<=available ){ sqlite3VdbeMemRelease(pMem); pMem->z = &zData[offset]; pMem->flags = MEM_Blob|MEM_Ephem; pMem->n = (int)amt; - }else if( SQLITE_OK==(rc = sqlite3VdbeMemGrow(pMem, amt+2, 0)) ){ - if( key ){ - rc = sqlite3BtreeKey(pCur, offset, amt, pMem->z); - }else{ - rc = sqlite3BtreeData(pCur, offset, amt, pMem->z); - } - if( rc==SQLITE_OK ){ - pMem->z[amt] = 0; - pMem->z[amt+1] = 0; - pMem->flags = MEM_Blob|MEM_Term; - pMem->n = (int)amt; - }else{ - sqlite3VdbeMemRelease(pMem); + }else{ + pMem->flags = MEM_Null; + if( SQLITE_OK==(rc = sqlite3VdbeMemGrow(pMem, amt+2, 0)) ){ + if( key ){ + rc = sqlite3BtreeKey(pCur, offset, amt, pMem->z); + }else{ + rc = sqlite3BtreeData(pCur, offset, amt, pMem->z); + } + if( rc==SQLITE_OK ){ + pMem->z[amt] = 0; + pMem->z[amt+1] = 0; + pMem->flags = MEM_Blob|MEM_Term; + pMem->n = (int)amt; + }else{ + sqlite3VdbeMemRelease(pMem); + } } } return rc; }