Ensure that the Expr objects that describe indexed expressions are not modified
by code generation. Fix for an assert() problem found by Jon Metzman using AFL.
FossilOrigin-Name: 34073ce87d88a02313217023ae92e15939192cd9
diff --git a/src/expr.c b/src/expr.c
index 8f6377e..5c67de1 100644
--- a/src/expr.c
+++ b/src/expr.c
@@ -2468,7 +2468,7 @@
assert( pIdx->aColExpr );
assert( pIdx->aColExpr->nExpr>iIdxCol );
pParse->iSelfTab = iTabCur;
- sqlite3ExprCode(pParse, pIdx->aColExpr->a[iIdxCol].pExpr, regOut);
+ sqlite3ExprCodeCopy(pParse, pIdx->aColExpr->a[iIdxCol].pExpr, regOut);
}else{
sqlite3ExprCodeGetColumnOfTable(pParse->pVdbe, pIdx->pTable, iTabCur,
iTabCol, regOut);
@@ -3321,7 +3321,7 @@
sqlite3VdbeAddOp2(pParse->pVdbe, OP_Copy, pExpr->iTable, target);
}else{
inReg = sqlite3ExprCodeTarget(pParse, pExpr, target);
- assert( pParse->pVdbe || pParse->db->mallocFailed );
+ assert( pParse->pVdbe!=0 || pParse->db->mallocFailed );
if( inReg!=target && pParse->pVdbe ){
sqlite3VdbeAddOp2(pParse->pVdbe, OP_SCopy, inReg, target);
}
@@ -3329,6 +3329,18 @@
}
/*
+** Make a transient copy of expression pExpr and then code it using
+** sqlite3ExprCode(). This routine works just like sqlite3ExprCode()
+** except that the input expression is guaranteed to be unchanged.
+*/
+void sqlite3ExprCodeCopy(Parse *pParse, Expr *pExpr, int target){
+ sqlite3 *db = pParse->db;
+ pExpr = sqlite3ExprDup(db, pExpr, 0);
+ if( !db->mallocFailed ) sqlite3ExprCode(pParse, pExpr, target);
+ sqlite3ExprDelete(db, pExpr);
+}
+
+/*
** Generate code that will evaluate expression pExpr and store the
** results in register target. The results are guaranteed to appear
** in register target. If the expression is constant, then this routine
diff --git a/src/insert.c b/src/insert.c
index 52769e9..7ac2a25 100644
--- a/src/insert.c
+++ b/src/insert.c
@@ -1408,7 +1408,7 @@
int x;
if( iField==XN_EXPR ){
pParse->ckBase = regNewData+1;
- sqlite3ExprCode(pParse, pIdx->aColExpr->a[i].pExpr, regIdx+i);
+ sqlite3ExprCodeCopy(pParse, pIdx->aColExpr->a[i].pExpr, regIdx+i);
pParse->ckBase = 0;
VdbeComment((v, "%s column %d", pIdx->zName, i));
}else{
diff --git a/src/sqliteInt.h b/src/sqliteInt.h
index 4249ef7..a328aff 100644
--- a/src/sqliteInt.h
+++ b/src/sqliteInt.h
@@ -3461,6 +3461,7 @@
void sqlite3ExprCacheClear(Parse*);
void sqlite3ExprCacheAffinityChange(Parse*, int, int);
void sqlite3ExprCode(Parse*, Expr*, int);
+void sqlite3ExprCodeCopy(Parse*, Expr*, int);
void sqlite3ExprCodeFactorable(Parse*, Expr*, int);
void sqlite3ExprCodeAtInit(Parse*, Expr*, int, u8);
int sqlite3ExprCodeTemp(Parse*, Expr*, int*);