]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Avoid excess stack usage when a VALUES clause with lots of rows occurs
authordrh <drh@noemail.net>
Sun, 14 Jan 2018 20:12:23 +0000 (20:12 +0000)
committerdrh <drh@noemail.net>
Sun, 14 Jan 2018 20:12:23 +0000 (20:12 +0000)
within a scalar expression.  This fixes a problem discovered by OSSFuzz.

FossilOrigin-Name: a4fa0581ba7cfd45fabe0198f55b3c2c8ee3ecfd2825aeed91116f44e77d760b

manifest
manifest.uuid
src/expr.c
src/select.c
test/selectG.test

index 296050499ce68b7d09f3c252749862cef975a458..4a8b555cf8e8c536a35e9e8277e9cf60db7887d6 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Fix\sharmless\scompiler\swarnings\sin\szipfile.c.
-D 2018-01-13T23:28:33.571
+C Avoid\sexcess\sstack\susage\swhen\sa\sVALUES\sclause\swith\slots\sof\srows\soccurs\nwithin\sa\sscalar\sexpression.\s\sThis\sfixes\sa\sproblem\sdiscovered\sby\sOSSFuzz.
+D 2018-01-14T20:12:23.878
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F Makefile.in 38f84f301cbef443b2d269f67a74b8cc536469831f70df7c3e912acc04932cc2
@@ -438,7 +438,7 @@ F src/date.c ebe1dc7c8a347117bb02570f1a931c62dd78f4a2b1b516f4837d45b7d6426957
 F src/dbpage.c 8db4c97f630e7d83f884ea75caf1ffd0988c160e9d530194d93721c80821e0f6
 F src/dbstat.c 7a4ba8518b6369ef3600c49cf9c918ad979acba610b2aebef1b656d649b96720
 F src/delete.c 20c8788451dc737a967c87ea53ad43544d617f5b57d32ccce8bd52a0daf9e89b
-F src/expr.c ad6e7a9c34a4bab9d10cc857d647ae7ce370a633b5c0bfa71f1c29b81ae364b8
+F src/expr.c 46a7d73d5579feaee7a7274fac0efea0bbae71dd5b107a569501d89e0280c762
 F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
 F src/fkey.c d617daf66b5515e2b42c1405b2b4984c30ca50fb705ab164271a9bf66c69e331
 F src/func.c bd528d5ed68ce5cbf78a762e3b735fa75009f7197ff07fab07fd771f35ebaa1b
@@ -485,7 +485,7 @@ F src/printf.c 9506b4b96e59c0467047155f09015750cb2878aeda3d39e5610c1192ddc3c41c
 F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384
 F src/resolve.c bbee7e31d369a18a2f4836644769882e9c5d40ef4a3af911db06410b65cb3730
 F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac
-F src/select.c 8b22abe193e4d8243befa2038e4ae2405802fed1c446e5e502d11f652e09ba74
+F src/select.c bebe7cce45d899d2237c76bce059d525abf5b861f2fce92f6b53914a961c01ba
 F src/shell.c.in b87abffd0db09203ad8a133d56fe8f154ace5ec0a14197a153fb7d80b1438c01
 F src/sqlite.h.in 9daf78e8f3cecc9ea0c3a82201f75bb74f789ecbfcda28d2e47fa80b3d956961
 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
@@ -1205,7 +1205,7 @@ F test/selectC.test e25243f8ca503e06f252eb0218976d07cfeceac3
 F test/selectD.test b0f02a04ef7737decb24e08be2c39b9664b43394
 F test/selectE.test a8730ca330fcf40ace158f134f4fe0eb00c7edbf
 F test/selectF.test 21c94e6438f76537b72532fa9fd4710cdd455fc3
-F test/selectG.test e8600e379589e85e9fefd2fe4d44a4cdd63f6982
+F test/selectG.test 089f7d3d7e6db91566f00b036cb353107a2cca6220eb1cb264085a836dae8840
 F test/server1.test 46803bd3fe8b99b30dbc5ff38ffc756f5c13a118
 F test/session.test 78fa2365e93d3663a6e933f86e7afc395adf18be
 F test/shared.test 1da9dbad400cee0d93f252ccf76e1ae007a63746
@@ -1699,7 +1699,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 f2d2a5df4f29b47212fd2411eae6545087b901a270655640c87ceb472e02a24c
-R 8e0eefc806344b75dcd41a32589e33e5
+P 8f7a592f8c044d75b4615a95e27454100b10c2b26f4cafee97dec23343821130
+R 5b961a6038bd65800f58ecff32ab6963
 U drh
-Z 25a119edfc3f91c75d6d9bd6eb4524cb
+Z 3c12035fed53223a4dcc5a3ae6914444
index 0bd548e74c3690b4490afb1ada81c6c7ca47cabc..2a881ffea9ce1d8049b8e4d75bbb14286282eebd 100644 (file)
@@ -1 +1 @@
-8f7a592f8c044d75b4615a95e27454100b10c2b26f4cafee97dec23343821130
\ No newline at end of file
+a4fa0581ba7cfd45fabe0198f55b3c2c8ee3ecfd2825aeed91116f44e77d760b
\ No newline at end of file
index 32cc4423fabe3cb629210151c4d734ba2518700a..a63de5d9fc249c0bfc01b8e16bb245648249e016 100644 (file)
@@ -2764,7 +2764,6 @@ int sqlite3CodeSubselect(
         pSel->pLimit = sqlite3PExpr(pParse, TK_LIMIT, pLimit, 0);
       }
       pSel->iLimit = 0;
-      pSel->selFlags &= ~SF_MultiValue;
       if( sqlite3Select(pParse, pSel, &dest) ){
         return 0;
       }
index 1a4b0a93afb9b56f0a69c8a6f222502297ec7bfa..c3cb4082fe71b1411eb429aee7873d33d4d4745e 100644 (file)
@@ -2184,9 +2184,14 @@ static int multiSelectOrderBy(
 ** on a VALUES clause.
 **
 ** Because the Select object originates from a VALUES clause:
-**   (1) It has no LIMIT or OFFSET
+**   (1) There is no LIMIT or OFFSET or else there is a LIMIT of exactly 1
 **   (2) All terms are UNION ALL
 **   (3) There is no ORDER BY clause
+**
+** The "LIMIT of exactly 1" case of condition (1) comes about when a VALUES
+** clause occurs within scalar expression (ex: "SELECT (VALUES(1),(2),(3))").
+** The sqlite3CodeSubselect will have added the LIMIT 1 clause in tht case.
+** Since the limit is exactly 1, we only need to evalutes the left-most VALUES.
 */
 static int multiSelectValues(
   Parse *pParse,        /* Parsing context */
@@ -2194,13 +2199,13 @@ static int multiSelectValues(
   SelectDest *pDest     /* What to do with query results */
 ){
   Select *pPrior;
+  Select *pRightmost = p;
   int nRow = 1;
   int rc = 0;
   assert( p->selFlags & SF_MultiValue );
   do{
     assert( p->selFlags & SF_Values );
     assert( p->op==TK_ALL || (p->op==TK_SELECT && p->pPrior==0) );
-    assert( p->pLimit==0 );
     assert( p->pNext==0 || p->pEList->nExpr==p->pNext->pEList->nExpr );
     if( p->pPrior==0 ) break;
     assert( p->pPrior->pNext==p );
@@ -2212,7 +2217,7 @@ static int multiSelectValues(
     p->pPrior = 0;
     rc = sqlite3Select(pParse, p, pDest);
     p->pPrior = pPrior;
-    if( rc ) break;
+    if( rc || pRightmost->pLimit ) break;
     p->nSelectRow = nRow;
     p = p->pNext;
   }
index 86d89b121b658a00d59fca0a45aa9503a2bc599a..fab4c4ed4deca76146ae0dd1dee32506a601eaab 100644 (file)
@@ -36,4 +36,24 @@ do_test 100 {
   }
 } {100000 5000050000 50000.5 1}
   
+# 2018-01-14.  A 100K-entry VALUES clause within a scalar expression does
+# not cause processor stack overflow.
+#
+do_test 110 {
+  set sql "SELECT (VALUES"
+  for {set i 1} {$i<100000} {incr i} {
+    append sql "($i),"
+  }
+  append sql "($i));"
+  db eval $sql
+} {1}
+
+# Only the left-most term of a multi-valued VALUES within a scalar
+# expression is evaluated.
+#
+do_test 120 {
+  set n [llength [split [db eval "explain $sql"] \n]]
+  expr {$n<10}
+} {1}
+
 finish_test