diff options
author | drh <> | 2021-03-31 13:31:33 +0000 |
---|---|---|
committer | drh <> | 2021-03-31 13:31:33 +0000 |
commit | b3ad4e611854dd5f4ad26378c4cfccf9f0c858dd (patch) | |
tree | 90a34dd0350c25af32bd33caca8e8d8edcdb42b6 /src/expr.c | |
parent | b03786ad6e89e1b38d94dfe9ca48aee921a97196 (diff) | |
download | sqlite-b3ad4e611854dd5f4ad26378c4cfccf9f0c858dd.tar.gz sqlite-b3ad4e611854dd5f4ad26378c4cfccf9f0c858dd.zip |
Defer deletion of expressions that are optimized out by the AND optimizer
in the sqlite3ExprAnd() routine until the corresponding Parse object is
deleted. This avoids a dangling pointer in AggInfo if sqlite3ExprAnd()
is invoked by the push-down optimization. The dangling pointer appears
to be harmless in release builds, only showing up in debug builds.
Problem found by dbsqlfuzz.
FossilOrigin-Name: c36b43589abd9f62a709bdb47b8748e0c1e8743487a3d83d1eb35eb06b65d763
Diffstat (limited to 'src/expr.c')
-rw-r--r-- | src/expr.c | 26 |
1 files changed, 20 insertions, 6 deletions
diff --git a/src/expr.c b/src/expr.c index a780fac11..ac0f4073f 100644 --- a/src/expr.c +++ b/src/expr.c @@ -968,8 +968,8 @@ Expr *sqlite3ExprAnd(Parse *pParse, Expr *pLeft, Expr *pRight){ }else if( (ExprAlwaysFalse(pLeft) || ExprAlwaysFalse(pRight)) && !IN_RENAME_OBJECT ){ - sqlite3ExprDelete(db, pLeft); - sqlite3ExprDelete(db, pRight); + sqlite3ExprDeferredDelete(pParse, pLeft); + sqlite3ExprDeferredDelete(pParse, pRight); return sqlite3Expr(db, TK_INTEGER, "0"); }else{ return sqlite3PExpr(pParse, TK_AND, pLeft, pRight); @@ -1166,6 +1166,22 @@ void sqlite3ExprDelete(sqlite3 *db, Expr *p){ if( p ) sqlite3ExprDeleteNN(db, p); } + +/* +** Arrange to cause pExpr to be deleted when the pParse is deleted. +** This is similar to sqlite3ExprDelete() except that the delete is +** deferred untilthe pParse is deleted. +** +** The pExpr might be deleted immediately on an OOM error. +** +** The deferred delete is (currently) implemented by adding the +** pExpr to the pParse->pConstExpr list with a register number of 0. +*/ +void sqlite3ExprDeferredDelete(Parse *pParse, Expr *pExpr){ + pParse->pConstExpr = + sqlite3ExprListAppend(pParse, pParse->pConstExpr, pExpr); +} + /* Invoke sqlite3RenameExprUnmap() and sqlite3ExprDelete() on the ** expression. */ @@ -5821,8 +5837,7 @@ static int agginfoPersistExprCb(Walker *pWalker, Expr *pExpr){ pExpr = sqlite3ExprDup(db, pExpr, 0); if( pExpr ){ pAggInfo->aCol[iAgg].pCExpr = pExpr; - pParse->pConstExpr = - sqlite3ExprListAppend(pParse, pParse->pConstExpr, pExpr); + sqlite3ExprDeferredDelete(pParse, pExpr); } } }else{ @@ -5831,8 +5846,7 @@ static int agginfoPersistExprCb(Walker *pWalker, Expr *pExpr){ pExpr = sqlite3ExprDup(db, pExpr, 0); if( pExpr ){ pAggInfo->aFunc[iAgg].pFExpr = pExpr; - pParse->pConstExpr = - sqlite3ExprListAppend(pParse, pParse->pConstExpr, pExpr); + sqlite3ExprDeferredDelete(pParse, pExpr); } } } |