mirror of
https://github.com/sqlite/sqlite.git
synced 2026-10-28 09:46:20 +08:00
Add the SQLITE_LIMIT_CTES option to sqlite3_limit(). The default is 50K.
Setting to zero disables the limit. The limit is approximate - it does not actually count CTEs but rather simply refuses to process a CTE with cursor number that exceeds this limit. This is a re-do of the fix for [bugs:/info/2026-10-04T05:35:14Z|Bug 2026-10-04T05:35:14Z] that also avoids the regression reported by [forum:/info/2026-10-16T20:30:17Z|Forum post 2026-10-16T20:30:17Z]. FossilOrigin-Name: b32709ea065da2eb41a6eb0ca20381d2bd82a356bb5f8bc76fee063d1da93004
This commit is contained in:
1 parent
e58a5a91ed
commit
dac1b8dc84
10 files changed
+80
-19
No files matched your search
@@ -1,5 +1,5 @@
|
||||
C Limit\sthe\ssize\sof\sthe\ssecond\sargument\sof\sthe\s(testing\suse\sonly)\sSQL\sfunction\nfpdecode()\sto\savoid\sa\s(harmless)\ssigned\sinteger\soverflow.\n[bugs:/info/2026-10-18T03:43:20Z|Bug\s2026-10-18T03:43:20Z]
|
||||
D 2026-10-18T18:30:00.323
|
||||
C Add\sthe\sSQLITE_LIMIT_CTES\soption\sto\ssqlite3_limit().\s\sThe\sdefault\sis\s50K.\nSetting\sto\szero\sdisables\sthe\slimit.\s\sThe\slimit\sis\sapproximate\s-\sit\sdoes\snot\nactually\scount\sCTEs\sbut\srather\ssimply\srefuses\sto\sprocess\sa\sCTE\swith\scursor\nnumber\sthat\sexceeds\sthis\slimit.\s\sThis\sis\sa\sre-do\sof\sthe\sfix\sfor\n[bugs:/info/2026-10-04T05:35:14Z|Bug\s2026-10-04T05:35:14Z]\sthat\salso\navoids\sthe\sregression\sreported\sby\n[forum:/info/2026-10-16T20:30:17Z|Forum\spost\s2026-10-16T20:30:17Z].
|
||||
D 2026-10-18T19:10:13.776
|
||||
F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x
|
||||
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
||||
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
||||
@@ -769,7 +769,7 @@ F src/insert.c 482d853c980f4765f045bbea3ab095067a52cd57f47e357f9f17aa7c7fff793f
|
||||
F src/json.c 7d28da4a3740941eab5fa3361276160bb7698bf87218c9d30be7c10b894b6115
|
||||
F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
|
||||
F src/loadext.c 5cd4cd7ec6e1a46416806899086363fbf95eecd3bfb9a388b436c9a77243c902
|
||||
F src/main.c a32bcae6e3bfd9209d922b02c28ba796fa628322c3c4be0c5a76c418be793d13
|
||||
F src/main.c 43912e1fae97d827e2c2345661336bdf36c31d01efd1f3bf9b5900406849b778
|
||||
F src/malloc.c 422f7e0498e1c9ef967f06283b6f2c0b16db6b905d8e06f6dbc8baaa3e4e6c5a
|
||||
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
|
||||
F src/mem1.c 3bb59158c38e05f6270e761a9f435bf19827a264c13d1631c58b84bdc96d73b2
|
||||
@@ -805,18 +805,18 @@ F src/printf.c 4bd228ed9e9346d558362be562757ee5eef6f9bf483b7f02751ca42cf95174d3
|
||||
F src/random.c 606b00941a1d7dd09c381d3279a058d771f406c5213c9932bbd93d5587be4b9c
|
||||
F src/resolve.c 0e0990f60c93db38c735d85e5d1741130e72dd0670aec204b5a39118b53c8044
|
||||
F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97
|
||||
F src/select.c ff27101a0c4b600cca3fd51734d9e445c93b3cef1c20ab42053325c6d7677bf0
|
||||
F src/shell.c.in 9ee1af86fca8195546dbaba2bf8b832e021093aeb269fbbfaea01ea4d7742629
|
||||
F src/sqlite.h.in 648fdc66f52433fc0f6cf9564ac924cde544eca9605bbac36aa22d8c944f11ed
|
||||
F src/select.c 25ca7908bab21aefd6bf8b5424992ebd3b74cb5ac74735beddd889c31c9c1706
|
||||
F src/shell.c.in e474c0820422fb3a34d45151785a606d1e1a42ba468d9580cc92b09a905f7f8e
|
||||
F src/sqlite.h.in d73bee6ea0612260b5edf72e3e58de7bd2a50cff000e0f4b3c3549d3e4c35171
|
||||
F src/sqlite3.rc 015537e6ac1eec6c7050e17b616c2ffe6f70fca241835a84a4f0d5937383c479
|
||||
F src/sqlite3ext.h 5e113c4c0442f2f1b3345d44cbe4b82fad45f2fc0c35f0ed4eef27fb8f1cb394
|
||||
F src/sqliteInt.h 7d95e3bd5370087e99f2b4549d6e135b8ee8e2ff4e1f190f5dd49664a16a872a
|
||||
F src/sqliteLimit.h c433b3fdb5e52f4226bf78d7e8081dff8fd8fbb0ce0cb1a5fee282aaa8976813
|
||||
F src/sqliteInt.h f16084b81ee8fd4fdd5dd6736f823e5fd79ce0116efea5e9ae594e3ce06fd306
|
||||
F src/sqliteLimit.h a905209cea2a167391382f64ecd42f944863ae44eabd540ef24a70361182f5ae
|
||||
F src/status.c 7565d63a79aa2f326339a24a0461a60096d0bd2bce711fefb50b5c89335f3592
|
||||
F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
|
||||
F src/tclsqlite.c ef6b69d919800d1b2d3e1b57a1a0e78872c3bddd413a4bc639a865226cf91b16
|
||||
F src/tclsqlite.h 614b3780a62522bc9f8f2b9fb22689e8009958e7aa77e572d0f3149050af348a
|
||||
F src/test1.c 18f656131b0de7856760b8ea293c1732ed237268d669d99a7316ad5be570ee45
|
||||
F src/test1.c 782616de14bc976c72ca8fffd634f695bc1106cde65242abb0986480711f645f
|
||||
F src/test2.c a61ed01d9264a1db74ab42fbc981fc66165f85d5e3947e92be61a73e79ec4f2d
|
||||
F src/test3.c c959fe0c3b04157483f5a6fa1950c1f222e062d920fee0a8e70410c6b6d45522
|
||||
F src/test4.c 0ac87fc13cdb334ab3a71823f99b6c32a6bebe5d603cd6a71d84c823d43a25a0
|
||||
@@ -2176,7 +2176,7 @@ F test/windowerr.test a8b752402109c15aa1c5efe1b93ccb0ce1ef84fa964ae1cd6684dd0b3c
|
||||
F test/windowfault.test 15094c1529424e62f798bc679e3fe9dfab6e8ba2f7dfe8c923b6248c31660a7c
|
||||
F test/windowpushd.test c420e2265f0e09a0e798d0513a660d71b51602088d81b3dbd038918ee1339dcc
|
||||
F test/with1.test e3fe2cbda3e5b0a8a666e596048313ea5895bfafc34dcdcfbd320470879cc68d
|
||||
F test/with2.test 08db6b31a986e4359b90e1028cb32fb165b49da7c0d6abd0752bb232494d32e8
|
||||
F test/with2.test 9fc63a2676b41dd990960cd122e27cfcc7b36679620e3c0e4b825e82e5b6749f
|
||||
F test/with3.test e30369ea27aa27eb1bda4c5e510c8a9f782c8afd2ab99d1a02b8a7f25a5d3e65
|
||||
F test/with4.test 257be66c0c67fee1defbbac0f685c3465e2cad037f21ce65f23f86084f198205
|
||||
F test/with5.test 262a604e001938428da3d06ca90df9a478eff34ada737e2c023a99954418e8cf
|
||||
@@ -2292,8 +2292,8 @@ F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee
|
||||
F tool/warnings.sh a554d13f6e5cf3760f041b87939e3d616ec6961859c3245e8ef701d1eafc2ca2
|
||||
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
|
||||
F tool/winmain.c 00c8fb88e365c9017db14c73d3c78af62194d9644feaf60e220ab0f411f3604c
|
||||
P f9e0ce3382e4787468bdb4029105fbffb2d4ab92b51c655ae762b555d8570efb
|
||||
R 9c4c405c8de19c2bb6cf17f212a418b5
|
||||
P 72187f18fe8b207e5955f269a5e299e5b18d5b919ae9073b208454c994e9b18d
|
||||
R ef71b58b2dd647a02fd1a522a3dc5ffd
|
||||
U drh
|
||||
Z 452de29e78bcde449f37ddcf141fc02a
|
||||
Z b07817cba2f602e51d663aa31085fc75
|
||||
# Remove this line to create a well-formed Fossil manifest.
|
||||
+1
-1
@@ -1 +1 @@
|
||||
72187f18fe8b207e5955f269a5e299e5b18d5b919ae9073b208454c994e9b18d
|
||||
b32709ea065da2eb41a6eb0ca20381d2bd82a356bb5f8bc76fee063d1da93004
|
||||
+3
-1
@@ -2997,6 +2997,7 @@ static const int aHardLimit[] = {
|
||||
SQLITE_MAX_PARSER_DEPTH,
|
||||
SQLITE_MAX_SCHEMA,
|
||||
SQLITE_MAX_TRIGGER_STEPS,
|
||||
SQLITE_MAX_CTES,
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -3084,7 +3085,8 @@ int sqlite3_limit(sqlite3 *db, int limitId, int newLimit){
|
||||
assert( aHardLimit[SQLITE_LIMIT_WORKER_THREADS]==SQLITE_MAX_WORKER_THREADS );
|
||||
assert( aHardLimit[SQLITE_LIMIT_SCHEMA]==SQLITE_MAX_SCHEMA );
|
||||
assert( aHardLimit[SQLITE_LIMIT_TRIGGER_STEPS]==SQLITE_MAX_TRIGGER_STEPS );
|
||||
assert( SQLITE_LIMIT_TRIGGER_STEPS==(SQLITE_N_LIMIT-1) );
|
||||
assert( aHardLimit[SQLITE_LIMIT_CTES]==SQLITE_MAX_CTES );
|
||||
assert( SQLITE_LIMIT_CTES==(SQLITE_N_LIMIT-1) );
|
||||
|
||||
|
||||
if( limitId<0 || limitId>=SQLITE_N_LIMIT ){
|
||||
|
||||
@@ -5899,6 +5899,12 @@ static int resolveFromTermToCte(
|
||||
pRecTerm = pRecTerm->pPrior;
|
||||
}
|
||||
|
||||
if( pParse->nTab >= db->aLimit[SQLITE_LIMIT_CTES]
|
||||
&& db->aLimit[SQLITE_LIMIT_CTES]>0
|
||||
){
|
||||
sqlite3ErrorMsg(pParse, "too many CTEs");
|
||||
return 2;
|
||||
}
|
||||
#if SQLITE_MAX_EXPR_DEPTH>0
|
||||
pParse->nNestSel++;
|
||||
if( checkSubqueryNestingDepth(pParse) ) return 2;
|
||||
|
||||
+3
-2
@@ -11193,6 +11193,7 @@ static int do_meta_command(const char *zLine, ShellState *p){
|
||||
{ "worker_threads", SQLITE_LIMIT_WORKER_THREADS },
|
||||
{ "schema", SQLITE_LIMIT_SCHEMA },
|
||||
{ "trigger_steps", SQLITE_LIMIT_TRIGGER_STEPS },
|
||||
{ "ctes", SQLITE_LIMIT_CTES },
|
||||
};
|
||||
int i, n2;
|
||||
open_db(p, 0);
|
||||
@@ -11227,8 +11228,8 @@ static int do_meta_command(const char *zLine, ShellState *p){
|
||||
goto meta_command_exit;
|
||||
}
|
||||
if( nArg==3 ){
|
||||
sqlite3_limit(p->db, aLimit[iLimit].limitCode,
|
||||
(int)integerValue(azArg[2]));
|
||||
int v = (int)integerValue(azArg[2]);
|
||||
sqlite3_limit(p->db, aLimit[iLimit].limitCode, v);
|
||||
}else{
|
||||
cli_printf(stdout, "%20s %d\n", aLimit[iLimit].zLimitName,
|
||||
sqlite3_limit(p->db, aLimit[iLimit].limitCode, -1));
|
||||
|
||||
@@ -4449,6 +4449,15 @@ int sqlite3_limit(sqlite3*, int id, int newVal);
|
||||
** [[SQLITE_LIMIT_TRIGGER_STEPS]] ^(<dt>SQLITE_LIMIT_TRIGGER_STEPS</dt>
|
||||
** <dd>The maximum number of SQL statements that can be contained within
|
||||
** a single trigger.</dd>)^
|
||||
**
|
||||
** [[SQLITE_LIMIT_CTES]] ^(<dt>SQLITE_LIMIT_CTES</dt>
|
||||
** <dd>The maximum number of [common table expressions] (CTEs) allowed
|
||||
** in a single SQL statements. This limit is used to limit possible
|
||||
** exponential growth in the number of required cursors required for
|
||||
** nested joins of CTEs. The limit is an absolute upper bound, and
|
||||
** SQLite may refuse to compile a statement if the number of CTEs simply
|
||||
** approaches this limit. Set this limit to 0 to disable the restriction.
|
||||
** </dd>)^
|
||||
** </dl>
|
||||
*/
|
||||
#define SQLITE_LIMIT_LENGTH 0
|
||||
@@ -4466,6 +4475,7 @@ int sqlite3_limit(sqlite3*, int id, int newVal);
|
||||
#define SQLITE_LIMIT_PARSER_DEPTH 12
|
||||
#define SQLITE_LIMIT_SCHEMA 13
|
||||
#define SQLITE_LIMIT_TRIGGER_STEPS 14
|
||||
#define SQLITE_LIMIT_CTES 15
|
||||
|
||||
/*
|
||||
** CAPI3REF: Prepare Flags
|
||||
|
||||
+1
-1
@@ -1574,7 +1574,7 @@ struct Schema {
|
||||
** The number of different kinds of things that can be limited
|
||||
** using the sqlite3_limit() interface.
|
||||
*/
|
||||
#define SQLITE_N_LIMIT (SQLITE_LIMIT_TRIGGER_STEPS+1)
|
||||
#define SQLITE_N_LIMIT (SQLITE_LIMIT_CTES+1)
|
||||
|
||||
/*
|
||||
** Lookaside malloc is a set of fixed-size buffers that can be used
|
||||
|
||||
@@ -302,3 +302,24 @@
|
||||
#ifndef SQLITE_MAX_TRIGGER_STEPS
|
||||
# define SQLITE_MAX_TRIGGER_STEPS 65000
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Maximum number of CTE cursors (approximately). This limit will be
|
||||
** exceeded if any CTE uses a cursor number larger than this value, even
|
||||
** of some of the cursors are used for something other than CTEs.
|
||||
**
|
||||
** The purpose of this limit is to prevent resource exhaustion caused
|
||||
** by hostile SQL inputs such as:
|
||||
**
|
||||
** WITH c0 AS (SELECT 1 AS x),
|
||||
** c1 AS (SELECT a.x AS x FROM c0 a, c0 b),
|
||||
** c2 AS (SELECT a.x AS x FROM c1 a, c1 b),
|
||||
** ...
|
||||
** c17 AS (SELECT a.x AS x FROM c16 a, c16 b)
|
||||
** SELECT count(*) FROM c17;
|
||||
**
|
||||
** See Bug 2026-10-04T05:35:14Z
|
||||
*/
|
||||
#ifndef SQLITE_MAX_CTES
|
||||
# define SQLITE_MAX_CTES 50000
|
||||
#endif
|
||||
+2
-1
@@ -7485,10 +7485,11 @@ static int SQLITE_TCLAPI test_limit(
|
||||
{ "SQLITE_LIMIT_WORKER_THREADS", SQLITE_LIMIT_WORKER_THREADS },
|
||||
{ "SQLITE_LIMIT_SCHEMA", SQLITE_LIMIT_SCHEMA },
|
||||
{ "SQLITE_LIMIT_TRIGGER_STEPS", SQLITE_LIMIT_TRIGGER_STEPS },
|
||||
{ "SQLITE_LIMIT_CTES", SQLITE_LIMIT_CTES },
|
||||
|
||||
/* Out of range test cases */
|
||||
{ "SQLITE_LIMIT_TOOSMALL", -1, },
|
||||
{ "SQLITE_LIMIT_TOOBIG", SQLITE_LIMIT_TRIGGER_STEPS+1 },
|
||||
{ "SQLITE_LIMIT_TOOBIG", SQLITE_LIMIT_CTES+1 },
|
||||
};
|
||||
int i, id = 0;
|
||||
int val;
|
||||
|
||||
@@ -669,5 +669,25 @@ if {$::SQLITE_MAX_EXPR_DEPTH>0} {
|
||||
SELECT x FROM c10;
|
||||
} {1 {VIEWs and/or subqueries nested too deep}}
|
||||
}
|
||||
do_execsql_test 14.3 {
|
||||
CREATE VIEW vcte AS
|
||||
WITH c0 AS (SELECT 1 AS x),
|
||||
c1 AS (SELECT a.x AS x FROM c0 AS a, c0 AS b),
|
||||
c2 AS (SELECT a.x AS x FROM c1 AS a, c1 AS b),
|
||||
c3 AS (SELECT a.x AS x FROM c2 AS a, c2 AS b),
|
||||
c4 AS (SELECT a.x AS x FROM c3 AS a, c3 AS b),
|
||||
c5 AS (SELECT a.x AS x FROM c4 AS a, c4 AS b),
|
||||
c6 AS (SELECT a.x AS x FROM c5 AS a, c5 AS b),
|
||||
c7 AS (SELECT a.x AS x FROM c6 AS a, c6 AS b)
|
||||
SELECT count(*) FROM c7;
|
||||
}
|
||||
sqlite3_limit db SQLITE_LIMIT_CTES 100
|
||||
do_catchsql_test 14.4 {
|
||||
SELECT * FROM vcte;
|
||||
} {1 {too many CTEs}}
|
||||
sqlite3_limit db SQLITE_LIMIT_CTES 0
|
||||
do_catchsql_test 14.5 {
|
||||
SELECT * FROM vcte;
|
||||
} {1 {at most 64 tables in a join}}
|
||||
|
||||
finish_test
|
||||
Reference in new issue
Block a user