mirror of
https://github.com/sqlite/sqlite.git
synced 2025-11-14 00:22:38 +03:00
Ensure that all auxiliary data registered by calls to sqlite3_set_auxdata() is destroyed when the VM is halted. Partial fix for [406d3b2ef9].
FossilOrigin-Name: 71effa59c98d167e6e4b269e59ad5f468e664ac1
This commit is contained in:
@@ -612,13 +612,6 @@ static void freeP4(sqlite3 *db, int p4type, void *p4){
|
||||
if( db->pnBytesFreed==0 ) sqlite3_free(p4);
|
||||
break;
|
||||
}
|
||||
case P4_VDBEFUNC: {
|
||||
VdbeFunc *pVdbeFunc = (VdbeFunc *)p4;
|
||||
freeEphemeralFunction(db, pVdbeFunc->pFunc);
|
||||
if( db->pnBytesFreed==0 ) sqlite3VdbeDeleteAuxData(pVdbeFunc, 0);
|
||||
sqlite3DbFree(db, pVdbeFunc);
|
||||
break;
|
||||
}
|
||||
case P4_FUNCDEF: {
|
||||
freeEphemeralFunction(db, (FuncDef*)p4);
|
||||
break;
|
||||
@@ -1648,6 +1641,10 @@ static void closeAllCursors(Vdbe *p){
|
||||
p->pDelFrame = pDel->pParent;
|
||||
sqlite3VdbeFrameDelete(pDel);
|
||||
}
|
||||
|
||||
/* Delete any auxdata allocations made by the VM */
|
||||
sqlite3VdbeDeleteAuxData(p, -1, 0);
|
||||
assert( p->pAuxData==0 );
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2446,20 +2443,35 @@ int sqlite3VdbeFinalize(Vdbe *p){
|
||||
}
|
||||
|
||||
/*
|
||||
** Call the destructor for each auxdata entry in pVdbeFunc for which
|
||||
** the corresponding bit in mask is clear. Auxdata entries beyond 31
|
||||
** are always destroyed. To destroy all auxdata entries, call this
|
||||
** routine with mask==0.
|
||||
** If parameter iOp is less than zero, then invoke the destructor for
|
||||
** all auxiliary data pointers currently cached by the VM passed as
|
||||
** the first argument.
|
||||
**
|
||||
** Or, if iOp is greater than or equal to zero, then the destructor is
|
||||
** only invoked for those auxiliary data pointers created by the user
|
||||
** function invoked by the OP_Function opcode at instruction iOp of
|
||||
** VM pVdbe, and only then if:
|
||||
**
|
||||
** * the associated function parameter is the 32nd or later (counting
|
||||
** from left to right), or
|
||||
**
|
||||
** * the corresponding bit in argument mask is clear (where the first
|
||||
** function parameter corrsponds to bit 0 etc.).
|
||||
*/
|
||||
void sqlite3VdbeDeleteAuxData(VdbeFunc *pVdbeFunc, int mask){
|
||||
int i;
|
||||
for(i=0; i<pVdbeFunc->nAux; i++){
|
||||
struct AuxData *pAux = &pVdbeFunc->apAux[i];
|
||||
if( (i>31 || !(mask&(((u32)1)<<i))) && pAux->pAux ){
|
||||
void sqlite3VdbeDeleteAuxData(Vdbe *pVdbe, int iOp, int mask){
|
||||
AuxData **pp = &pVdbe->pAuxData;
|
||||
while( *pp ){
|
||||
AuxData *pAux = *pp;
|
||||
if( (iOp<0)
|
||||
|| (pAux->iOp==iOp && (pAux->iArg>31 || !(mask & ((u32)1<<pAux->iArg))))
|
||||
){
|
||||
if( pAux->xDelete ){
|
||||
pAux->xDelete(pAux->pAux);
|
||||
}
|
||||
pAux->pAux = 0;
|
||||
*pp = pAux->pNext;
|
||||
sqlite3DbFree(pVdbe->db, pAux);
|
||||
}else{
|
||||
pp= &pAux->pNext;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user