mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-07 02:42:48 +03:00
Ensure that the accumulator for an aggregate always gets initialized,
even when the aggregate is on the right side of a LEFT JOIN and never gets evaluated. This fixes a problem introduced by [663f5dd32d9db832] and found by dbsqlfuzz. Test cases in TH3. FossilOrigin-Name: 235cf6586b9ac914a32bd8adfd460daae998687f02f0998a7aa3c6bfc857d1c9
This commit is contained in:
25
src/expr.c
25
src/expr.c
@@ -4989,6 +4989,12 @@ expr_code_doover:
|
||||
sqlite3VdbeLoadString(v, target, pExpr->u.zToken);
|
||||
return target;
|
||||
}
|
||||
case TK_NULLS: {
|
||||
/* Set a range of registers to NULL. pExpr->y.nReg registers starting
|
||||
** with target */
|
||||
sqlite3VdbeAddOp3(v, OP_Null, 0, target, target + pExpr->y.nReg - 1);
|
||||
return target;
|
||||
}
|
||||
default: {
|
||||
/* Make NULL the default case so that if a bug causes an illegal
|
||||
** Expr node to be passed into this function, it will be handled
|
||||
@@ -5698,6 +5704,25 @@ int sqlite3ExprCodeRunJustOnce(
|
||||
return regDest;
|
||||
}
|
||||
|
||||
/*
|
||||
** Make arrangements to invoke OP_Null on a range of registers
|
||||
** during initialization.
|
||||
*/
|
||||
SQLITE_NOINLINE void sqlite3ExprNullRegisterRange(
|
||||
Parse *pParse, /* Parsing context */
|
||||
int iReg, /* First register to set to NULL */
|
||||
int nReg /* Number of sequential registers to NULL out */
|
||||
){
|
||||
u8 okConstFactor = pParse->okConstFactor;
|
||||
Expr t;
|
||||
memset(&t, 0, sizeof(t));
|
||||
t.op = TK_NULLS;
|
||||
t.y.nReg = nReg;
|
||||
pParse->okConstFactor = 1;
|
||||
sqlite3ExprCodeRunJustOnce(pParse, &t, iReg);
|
||||
pParse->okConstFactor = okConstFactor;
|
||||
}
|
||||
|
||||
/*
|
||||
** Generate code to evaluate an expression and store the results
|
||||
** into a register. Return the register number where the results
|
||||
|
@@ -8482,6 +8482,7 @@ int sqlite3Select(
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, 0, iAbortFlag);
|
||||
VdbeComment((v, "clear abort flag"));
|
||||
sqlite3VdbeAddOp3(v, OP_Null, 0, iAMem, iAMem+pGroupBy->nExpr-1);
|
||||
sqlite3ExprNullRegisterRange(pParse, iAMem, pGroupBy->nExpr);
|
||||
|
||||
/* Begin a loop that will extract all source rows in GROUP BY order.
|
||||
** This might involve two separate loops with an OP_Sort in between, or
|
||||
|
@@ -3082,6 +3082,7 @@ struct Expr {
|
||||
Table *pTab; /* TK_COLUMN: Table containing column. Can be NULL
|
||||
** for a column of an index on an expression */
|
||||
Window *pWin; /* EP_WinFunc: Window/Filter defn for a function */
|
||||
int nReg; /* TK_NULLS: Number of registers to NULL out */
|
||||
struct { /* TK_IN, TK_SELECT, and TK_EXISTS */
|
||||
int iAddr; /* Subroutine entry address */
|
||||
int regReturn; /* Register used to hold return address */
|
||||
@@ -5119,6 +5120,7 @@ void sqlite3ExprCodeGeneratedColumn(Parse*, Table*, Column*, int);
|
||||
void sqlite3ExprCodeCopy(Parse*, Expr*, int);
|
||||
void sqlite3ExprCodeFactorable(Parse*, Expr*, int);
|
||||
int sqlite3ExprCodeRunJustOnce(Parse*, Expr*, int);
|
||||
void sqlite3ExprNullRegisterRange(Parse*, int, int);
|
||||
int sqlite3ExprCodeTemp(Parse*, Expr*, int*);
|
||||
int sqlite3ExprCodeTarget(Parse*, Expr*, int);
|
||||
int sqlite3ExprCodeExprList(Parse*, ExprList*, int, int, u8);
|
||||
|
Reference in New Issue
Block a user