]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Defer deletion of expressions that are optimized out by the AND optimizer
authordrh <>
Wed, 31 Mar 2021 13:31:33 +0000 (13:31 +0000)
committerdrh <>
Wed, 31 Mar 2021 13:31:33 +0000 (13:31 +0000)
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

manifest
manifest.uuid
src/expr.c
src/sqliteInt.h
test/select4.test

index 345eb10e6d9702f62ff3a46f67b31c9252aba446..1970e0d540a75611b2d701a15e527582c92459af 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Ensure\sthat\snegative\snumbers\smay\snot\sbe\sused\sin\sframe\soffset\sclauses\seven\sif\sthey\sare\sinitially\stext\svalue.\se.g.\s(RANGE\sBETWEEN\s'-1'\sPRECEDING\s...).
-D 2021-03-31T11:31:19.995
+C Defer\sdeletion\sof\sexpressions\sthat\sare\soptimized\sout\sby\sthe\sAND\soptimizer\nin\sthe\ssqlite3ExprAnd()\sroutine\suntil\sthe\scorresponding\sParse\sobject\sis\ndeleted.\s\sThis\savoids\sa\sdangling\spointer\sin\sAggInfo\sif\ssqlite3ExprAnd()\nis\sinvoked\sby\sthe\spush-down\soptimization.\s\sThe\sdangling\spointer\sappears\nto\sbe\sharmless\sin\srelease\sbuilds,\sonly\sshowing\sup\sin\sdebug\sbuilds.\nProblem\sfound\sby\sdbsqlfuzz.
+D 2021-03-31T13:31:33.513
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -494,7 +494,7 @@ F src/date.c e0632f335952b32401482d099321bbf12716b29d6e72836b53ae49683ebae4bf
 F src/dbpage.c 8a01e865bf8bc6d7b1844b4314443a6436c07c3efe1d488ed89e81719047833a
 F src/dbstat.c 3aa79fc3aed7ce906e4ea6c10e85d657299e304f6049861fe300053ac57de36c
 F src/delete.c 73f57a9a183532c344a3135cf8f2a5589376e39183e0b5f562d6b61b2af0f4d8
-F src/expr.c 1a63403c5b06f762efc74f88ba59ea1ff58c9897bc74b36561ac4e259083e61e
+F src/expr.c 1bf346b7efbe37f62aab7079fdc9ee1aa13e9bea29dbb161f9e7036db9df24e2
 F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
 F src/fkey.c e9063648396c58778f77583a678342fe4a9bc82436bf23c5f9f444f2df0fdaa4
 F src/func.c 479f6929be027eb0210cbdde9d3529c012facf082d64a6b854a9415940761e5e
@@ -547,7 +547,7 @@ F src/shell.c.in dcce260883836c9b58847505fbccce8d5546af925046f7dacd9443e922ece03
 F src/sqlite.h.in 3426a080ea1f222a73e3bd91e7eacbd30570a0117c03d42c6dde606f33e5e318
 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
 F src/sqlite3ext.h 61b38c073d5e1e96a3d45271b257aef27d0d13da2bea5347692ae579475cd95e
-F src/sqliteInt.h 109a1489293798c2aa84b4ee3cbe311994e6ecb9f1cd15e8ec3eec92655c8f67
+F src/sqliteInt.h c5cfae5891a6e643116f66f63769bcffeba89ca51f6278732da710eb0cf092b6
 F src/sqliteLimit.h d7323ffea5208c6af2734574bae933ca8ed2ab728083caa117c9738581a31657
 F src/status.c 4b8bc2a6905163a38b739854a35b826c737333fab5b1f8e03fa7eb9a4799c4c1
 F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
@@ -1337,7 +1337,7 @@ F test/securedel2.test 2d54c28e46eb1fd6902089958b20b1b056c6f1c5
 F test/select1.test 3d23f66bf9ba77570acfe2ca5f1540ece17037cc64ab1a00efec9758ac29c268
 F test/select2.test 352480e0e9c66eda9c3044e412abdf5be0215b56
 F test/select3.test c49fbb758903f3718e2de5aa4655eda4838131cbea24a86db908f8b6889aa68c
-F test/select4.test e8a2502e3623f3058871030599a48abb35789d2244d5b380ecf3696873fdd4a4
+F test/select4.test f0684d3da3bccacbe2a1ebadf6fb49d9df6f53acb4c6ebc228a88d0d6054cc7b
 F test/select5.test df9ec0d218cedceb4fe7b63262025b547b50a55e59148c6f40b60ca25f1d4546
 F test/select6.test 319d45e414cdd321bf17cfacedaf19e3935ad64dac357c53f1492338c6e9b801
 F test/select7.test f659f231489349e8c5734e610803d7654207318f
@@ -1911,7 +1911,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
 F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 3039bcaff95bb5d096c80b5eefdaeda6abd1d1337e829f32fd28a968f663f481
-R 7b19f4193fff66a2a9516f68b5ccb188
-U dan
-Z 82b60d1644919097b1f10e4e15aa5fcc
+P 8b681b274dd01c3e0f76d5bbddcbb2450c6d9475b9cfa0db961a3ab5edf51db1
+R 1913f072c7bc3e67445edd5a42763229
+U drh
+Z 097b16b038df82ff66ede32b1c1f045a
index 2d9053d242266ab12b3bec86c72905ca72a75bc1..219a63fbbbd7229929bbdfa9254dc6d56c41ad3f 100644 (file)
@@ -1 +1 @@
-8b681b274dd01c3e0f76d5bbddcbb2450c6d9475b9cfa0db961a3ab5edf51db1
\ No newline at end of file
+c36b43589abd9f62a709bdb47b8748e0c1e8743487a3d83d1eb35eb06b65d763
\ No newline at end of file
index a780fac112808d79137e3153f658d2b60069f77f..ac0f4073f188d3b80164af05b18a3584a15e5ca1 100644 (file)
@@ -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);
         }
       }
     }
index 09a692d1b52ce6d622fc405eb5d1d6e8cb2eff50..fcc50e15766ab0be309ed6c86648bb1906d563e8 100644 (file)
@@ -4287,6 +4287,7 @@ Expr *sqlite3ExprFunction(Parse*,ExprList*, Token*, int);
 void sqlite3ExprFunctionUsable(Parse*,Expr*,FuncDef*);
 void sqlite3ExprAssignVarNumber(Parse*, Expr*, u32);
 void sqlite3ExprDelete(sqlite3*, Expr*);
+void sqlite3ExprDeferredDelete(Parse*, Expr*);
 void sqlite3ExprUnmapAndDelete(Parse*, Expr*);
 ExprList *sqlite3ExprListAppend(Parse*,ExprList*,Expr*);
 ExprList *sqlite3ExprListAppendVector(Parse*,ExprList*,IdList*,Expr*);
index 6dbfd4d0a19114640fe5d9eb56653c0e16de06b3..d49708ece87ce49907477bf8da2b47737b147430 100644 (file)
@@ -1025,5 +1025,19 @@ do_execsql_test select4-18.3 {
    WHERE abs(z1.aa)=z2.aa AND z1.aa=123;
 } {123}
 
+# 2021-03-31 Fix an assert() problem in the logic at the end of sqlite3Select()
+# that validates AggInfo.  The checks to ensure that AggInfo.aCol[].pCExpr
+# references a valid expression was looking at an expression that had been
+# deleted by the truth optimization in sqlite3ExprAnd() which was invoked by
+# the push-down optimization.  This is harmless in delivery builds, as that code
+# only runs with SQLITE_DEBUG.  But it should still be fixed.  The problem
+# was discovered by dbsqlfuzz (crash-dece7b67a3552ed7e571a7bda903afd1f7bd9b21)
+#
+reset_db
+do_execsql_test select4-19.1 {
+  CREATE TABLE t1(x);
+  INSERT INTO t1 VALUES(99);
+  SELECT sum((SELECT 1 FROM (SELECT 2 WHERE x IS NULL) WHERE 0)) FROM t1;
+} {{}}
 
 finish_test