From b3718ccd92fa531481948c17e0c645fa264e82db Mon Sep 17 00:00:00 2001 From: drh <> Date: Fri, 18 Jul 2025 12:22:41 +0000 Subject: [PATCH] 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. Also increment the version number. FossilOrigin-Name: 53711bf9f6d10d527298e7a59e1eaa2347ae26cd04636e4849ae8a0c4c7e0591 --- VERSION | 2 +- manifest | 21 ++++++++++----------- manifest.uuid | 2 +- src/expr.c | 25 +++++++++++++++++++++++++ src/select.c | 1 + src/sqliteInt.h | 2 ++ 6 files changed, 40 insertions(+), 13 deletions(-) diff --git a/VERSION b/VERSION index 6a6d84a540..acecb4fcb7 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -3.50.3 +3.50.4 diff --git a/manifest b/manifest index 0ee8c25cf2..e701f7ebb6 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Version\s3.50.3 -D 2025-07-17T13:25:10.611 +C Ensure\sthat\sthe\saccumulator\sfor\san\saggregate\salways\sgets\sinitialized,\neven\swhen\sthe\saggregate\sis\son\sthe\sright\sside\sof\sa\sLEFT\sJOIN\sand\snever\ngets\sevaluated.\s\sAlso\sincrement\sthe\sversion\snumber. +D 2025-07-18T12:22:41.674 F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea @@ -8,7 +8,7 @@ F Makefile.in c3e414df4dc8dfb12f1f6baf129fcb6d18cd0ebd3c9109370fb3fceeeef9a37a F Makefile.linux-generic bd3e3cacd369821a6241d4ea1967395c962dfe3057e38cb0a435cee0e8b789d0 F Makefile.msc 0206f28988bb6634c7e8aff05bf6cfa65d6dfe1d2b6bd95160dd99290a83dfc7 F README.md e28077cfbef795e99c9c75ed95aa7257a1166709b562076441a8506ac421b7c1 -F VERSION 613f62a5375c819156a56fa263adc08f8ee5998f45a946d3c5d594385b2ef736 +F VERSION 33191da58a15d51e312248db3124d33e1dbc1797d7f8fe14d9df5ff07430b503 F art/icon-243x273.gif 9750b734f82fdb3dc43127753d5e6fbf3b62c9f4e136c2fbf573b2f57ea87af5 F art/icon-80x90.gif 65509ce3e5f86a9cd64fe7fca2d23954199f31fe44c1e09e208c80fb83d87031 F art/sqlite370.eps aa97a671332b432a54e1d74ff5e8775be34200c2 @@ -736,7 +736,7 @@ F src/date.c 9db4d604e699a73e10b8e85a44db074a1f04c0591a77e2abfd77703f50dce1e9 F src/dbpage.c fcb1aafe00872a8aff9a7aa0ef7ff1b01e5817ec7bbd521f8f3e1e674ac8d609 F src/dbstat.c 73362c0df0f40ad5523a6f5501224959d0976757b511299bf892313e79d14f5c F src/delete.c 03a77ba20e54f0f42ebd8eddf15411ed6bdb06a2c472ac4b6b336521bf7cea42 -F src/expr.c 7e7f57247e864aaa46af2fd6bf3f7433dbefffc470687158340e5d68a15c4469 +F src/expr.c 72e7cddcb2ea06de48f40ee301b81608d86a17b73781e42901ce585f53074589 F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007 F src/fkey.c 928ed2517e8732113d2b9821aa37af639688d752f4ea9ac6e0e393d713eeb76f F src/func.c de47a8295503aa130baae5e6d9868ecf4f7c4dbffa65d83ad1f70bdbac0ee2d6 @@ -785,12 +785,12 @@ F src/printf.c 3b91c334f528359145f4dde0dedd945bbb21044d0825ea064934d7222d61662c F src/random.c 606b00941a1d7dd09c381d3279a058d771f406c5213c9932bbd93d5587be4b9c F src/resolve.c d40fe18d7c2fd0339f5846ffcf7d6809866e380acdf14c76fb2af87e9fe13f64 F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97 -F src/select.c 7a21df5db6bb1a4c1bb6d9fb76c8e2485a22ff8306519ad69d8ddf0d5fa10903 +F src/select.c 5c129b669317a1d57283055482b9c1e105199a7e47d69526491ca165d3376999 F src/shell.c.in ba53a52dafb167ac6320703da741386c34fbcabe8c078a188bb9f89808e3ef8f F src/sqlite.h.in 9ae373d11e1b11ac9c81c508523ae37f1619e739858280078ee9fb4e1e62d3ed F src/sqlite3.rc 015537e6ac1eec6c7050e17b616c2ffe6f70fca241835a84a4f0d5937383c479 F src/sqlite3ext.h 0bfd049bb2088cc44c2ad54f2079d1c6e43091a4e1ce8868779b75f6c1484f1e -F src/sqliteInt.h 08a7dcb8db162875b3dd5229eb0bf75691150ac54fea1ff3670391bd6ef40546 +F src/sqliteInt.h 0c24996d4c02eca6fd971ecbe5a565aaaf5f024265a53ce62d77ee366fcc7c6a F src/sqliteLimit.h 6d817c28a8f19af95e6f4921933b7fbbca48a962bce0eb0ec81e8bb3ef38e68b F src/status.c 0e72e4f6be6ccfde2488eb63210297e75f569f3ce9920f6c3d77590ec6ce5ffd F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1 @@ -2209,10 +2209,9 @@ F tool/version-info.c 3b36468a90faf1bbd59c65fd0eb66522d9f941eedd364fabccd7227350 F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee87c1b31a7 F tool/warnings.sh 1ad0169b022b280bcaaf94a7fa231591be96b514230ab5c98fbf15cd7df842dd F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 63595b74956a9391f03a273204c80ecd0ba946846b7aa0195b9095fe8b6a78e5 -R 987003a9608f543153f11a48f885adf4 -T +sym-release * -T +sym-version-3.50.3 * +P 3ce993b8657d6d9deda380a93cdd6404a8c8ba1b185b2bc423703e41ae5f2543 +Q +235cf6586b9ac914a32bd8adfd460daae998687f02f0998a7aa3c6bfc857d1c9 +R b7e2424242026610046fafc1ea11acb6 U drh -Z 351123ab09d4bd77e28a506f711aa720 +Z 22e3535dfd9f34415ce025fd0e7d864e # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index d2cf7ea043..13e2e5a8bf 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -3ce993b8657d6d9deda380a93cdd6404a8c8ba1b185b2bc423703e41ae5f2543 +53711bf9f6d10d527298e7a59e1eaa2347ae26cd04636e4849ae8a0c4c7e0591 diff --git a/src/expr.c b/src/expr.c index 7e13e5bc08..677e4fe92e 100644 --- a/src/expr.c +++ b/src/expr.c @@ -4898,6 +4898,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 @@ -5582,6 +5588,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 diff --git a/src/select.c b/src/select.c index 8e4c939cd4..dc4e87393c 100644 --- a/src/select.c +++ b/src/select.c @@ -8363,6 +8363,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 diff --git a/src/sqliteInt.h b/src/sqliteInt.h index dee1d07fe5..76aef3d120 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -3064,6 +3064,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 */ @@ -5098,6 +5099,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); -- 2.47.2