1
0
mirror of https://github.com/sqlite/sqlite.git synced 2026-10-23 21:49:02 +03:00

Limit the depth of recursion for CTEs using SQLITE_LIMIT_EXPR_DEPTH.

[bugs:/info/2026-10-04T04:58:58Z|Bug 2026-10-04T04:58:58Z].

FossilOrigin-Name: f54730871303e655a70f3167ce1a39dcd4e53fcf017d225f429e2bb67ad96604
This commit is contained in:
drh
2026-10-05 09:32:24 +00:00
parent d54522a5b8
commit e6ff280c83
4 changed files with 65 additions and 20 deletions

View File

@@ -1,5 +1,5 @@
C Fix\sexpression\stree\sdepth\scalculations\sfor\sCOLLATE.\n[bugs:/info/2026-10-04T04:50:56Z|Bug\s2026-10-04T04:50:56Z]
D 2026-10-04T21:54:17.561
C Limit\sthe\sdepth\sof\srecursion\sfor\sCTEs\susing\sSQLITE_LIMIT_EXPR_DEPTH.\n[bugs:/info/2026-10-04T04:58:58Z|Bug\s2026-10-04T04:58:58Z].
D 2026-10-05T09:32:24.919
F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
@@ -800,7 +800,7 @@ F src/printf.c 4bd228ed9e9346d558362be562757ee5eef6f9bf483b7f02751ca42cf95174d3
F src/random.c 606b00941a1d7dd09c381d3279a058d771f406c5213c9932bbd93d5587be4b9c
F src/resolve.c 0e0990f60c93db38c735d85e5d1741130e72dd0670aec204b5a39118b53c8044
F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97
F src/select.c 5859a4a19581d91fb2c3a818c18ad45de6906434aeaf0c4b74ca5f58295cb432
F src/select.c 6aa1d385f58b7e5b813a1ea4008dfe36378568d13e1cdfac8fb21f135f13e589
F src/shell.c.in 8504577eb02e87b58f9d632bc4458efda074476428774692207ddacc0fe9e1df
F src/sqlite.h.in 884996e07cfb7681efc76661b79d56a93f9edaea7f6fc4a3c82636dc84783486
F src/sqlite3.rc 015537e6ac1eec6c7050e17b616c2ffe6f70fca241835a84a4f0d5937383c479
@@ -2162,7 +2162,7 @@ F test/windowerr.test a8b752402109c15aa1c5efe1b93ccb0ce1ef84fa964ae1cd6684dd0b3c
F test/windowfault.test 15094c1529424e62f798bc679e3fe9dfab6e8ba2f7dfe8c923b6248c31660a7c
F test/windowpushd.test c420e2265f0e09a0e798d0513a660d71b51602088d81b3dbd038918ee1339dcc
F test/with1.test c416097db4ead936b98a76ff3069f76a6009c5aaec5ff2b2c5ca210bc595ad57
F test/with2.test 181674a6cc86a601ca2ac052741cdfad5b529e07e870435d2f6cdb92d589ff17
F test/with2.test 70cdc0b211a2c5ffccc93f5c50cf092367bf5a1792576d23a479915a80fb5506
F test/with3.test e30369ea27aa27eb1bda4c5e510c8a9f782c8afd2ab99d1a02b8a7f25a5d3e65
F test/with4.test 257be66c0c67fee1defbbac0f685c3465e2cad037f21ce65f23f86084f198205
F test/with5.test 262a604e001938428da3d06ca90df9a478eff34ada737e2c023a99954418e8cf
@@ -2278,8 +2278,8 @@ F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee
F tool/warnings.sh a554d13f6e5cf3760f041b87939e3d616ec6961859c3245e8ef701d1eafc2ca2
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
F tool/winmain.c 00c8fb88e365c9017db14c73d3c78af62194d9644feaf60e220ab0f411f3604c
P d4330c79a477bab7e86aba860813f4f83e9af5ef8067698fcdf41efd6a0e8516
R 960558da009947c307ca304fdbbe4e0f
P 252c0b7bf5a727d29605672bb58e06c758173c276671df3e388a68294998b4d3
R 290d962d1474ee55ec1b78b7d7977cb5
U drh
Z 6378420ac511b5740e99c19b2a3da65d
Z 4a8d751b209e545320f7b152e9bdedd1
# Remove this line to create a well-formed Fossil manifest.

View File

@@ -1 +1 @@
252c0b7bf5a727d29605672bb58e06c758173c276671df3e388a68294998b4d3
f54730871303e655a70f3167ce1a39dcd4e53fcf017d225f429e2bb67ad96604

View File

@@ -2490,6 +2490,20 @@ void sqlite3SubqueryColumnTypes(
pTab->szTabRow = 1; /* Any non-zero value works */
}
/*
** Check the current subquery nesting depth. Return true and set an
** error if it has gone too deep.
*/
static int checkSubqueryNestingDepth(Parse *pParse){
#if SQLITE_MAX_EXPR_DEPTH>0
if( pParse->nNestSel >= pParse->db->aLimit[SQLITE_LIMIT_EXPR_DEPTH] ){
sqlite3ErrorMsg(pParse, "VIEWs and/or subqueries nested too deep");
return 1;
}
#endif
return 0;
}
/*
** Given a SELECT statement, generate a Table structure that describes
** the result set of that SELECT.
@@ -2500,12 +2514,7 @@ Table *sqlite3ResultSetOfSelect(Parse *pParse, Select *pSelect, char aff){
u64 savedFlags;
pParse->nNestSel++;
#if SQLITE_MAX_EXPR_DEPTH>0
if( pParse->nNestSel >= db->aLimit[SQLITE_LIMIT_EXPR_DEPTH] ){
sqlite3ErrorMsg(pParse, "VIEWs and/or subqueries nested too deep");
return 0;
}
#endif
if( checkSubqueryNestingDepth(pParse) ) return 0;
savedFlags = db->flags;
db->flags &= ~(u64)SQLITE_FullColNames;
db->flags |= SQLITE_ShortColNames;
@@ -5752,14 +5761,13 @@ With *sqlite3WithPush(Parse *pParse, With *pWith, u8 bFree){
}
/*
** This function checks if argument pFrom refers to a CTE declared by
** This function checks to see if argument pFrom refers to a CTE declared by
** a WITH clause on the stack currently maintained by the parser (on the
** pParse->pWith linked list). And if currently processing a CTE
** CTE expression, through routine checks to see if the reference is
** a recursive reference to the CTE.
** pParse->pWith linked list). And if currently processing a CTE expression,
** it also checks to see if the reference is a recursive reference to the CTE.
**
** If pFrom matches a CTE according to either of these two above, pFrom->pSTab
** and other fields are populated accordingly.
** If pFrom matches a CTE, pFrom->pSTab and other fields are populated
** accordingly.
**
** Return 0 if no match is found.
** Return 1 if a match is found.
@@ -5888,6 +5896,8 @@ static int resolveFromTermToCte(
pRecTerm = pRecTerm->pPrior;
}
pParse->nNestSel++;
if( checkSubqueryNestingDepth(pParse) ) return 2;
pCte->zCteErr = "circular reference: %s";
pSavedWith = pParse->pWith;
pParse->pWith = pWith;
@@ -5912,6 +5922,8 @@ static int resolveFromTermToCte(
}
}
pParse->pWith = pWith;
pParse->nNestSel--;
assert( pParse->nNestSel>=0 );
for(pLeft=pSel; pLeft->pPrior; pLeft=pLeft->pPrior);
pEList = pLeft->pEList;

View File

@@ -635,4 +635,37 @@ do_execsql_test 13.1 {
SELECT * FROM t1, t3;
} {111 222}
# Bug 2026-10-04T04:58:58Z
reset_db
sqlite3_limit db SQLITE_LIMIT_EXPR_DEPTH 12
do_catchsql_test 14.1 {
WITH c0 AS (SELECT 1 AS x),
c1 AS (SELECT x FROM c0),
c2 AS (SELECT x FROM c1),
c3 AS (SELECT x FROM c2),
c4 AS (SELECT x FROM c3),
c5 AS (SELECT x FROM c4),
c6 AS (SELECT x FROM c5),
c7 AS (SELECT x FROM c6),
c8 AS (SELECT x FROM c7),
c9 AS (SELECT x FROM c8),
c10 AS (SELECT x FROM c9)
SELECT x FROM c10;
} {0 1}
sqlite3_limit db SQLITE_LIMIT_EXPR_DEPTH 11
do_catchsql_test 14.2 {
WITH c00 AS (SELECT 1 AS x),
c1 AS (SELECT x FROM c00),
c2 AS (SELECT x FROM c1),
c3 AS (SELECT x FROM c2),
c4 AS (SELECT x FROM c3),
c5 AS (SELECT x FROM c4),
c6 AS (SELECT x FROM c5),
c7 AS (SELECT x FROM c6),
c8 AS (SELECT x FROM c7),
c9 AS (SELECT x FROM c8),
c10 AS (SELECT x FROM c9)
SELECT x FROM c10;
} {1 {VIEWs and/or subqueries nested too deep}}
finish_test