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

Add SQLITE_LIMIT_TRIGGER_STEPS and -DSQLITE_MAX_TRIGGER_STEPS=n. Default maximum

is 65000.

FossilOrigin-Name: 6fbed57b1447725ae9d923d69b509fd5932d8c6bae6cf6ac0d1248a943752a58
This commit is contained in:
drh
2026-08-18 09:17:48 +00:00
parent 0489a60a42
commit 9fd4cbde74
12 changed files with 76 additions and 21 deletions

View File

@@ -1,5 +1,5 @@
C Plaform\sportability\simprovements\sfor\sautosetup/find_tclconfig.tcl,\sfrom\sDan\sShearer\sat\sforum\spost\s[bugs:778223d22549a1a1|2026-08-13T20:55:18Z].
D 2026-08-18T07:51:01.702
C Add\sSQLITE_LIMIT_TRIGGER_STEPS\sand\s-DSQLITE_MAX_TRIGGER_STEPS=n.\s\sDefault\smaximum\nis\s65000.
D 2026-08-18T09:17:48.729
F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
@@ -707,7 +707,7 @@ F src/insert.c 64c22744bce3b1e9630288043c1967a60b4f02c8fc7707fdb10d13c1ec30d297
F src/json.c 3f05a035d3a747a549e75bb419afcad7137e3241a5a836d20a62335d9e90a35d
F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
F src/loadext.c 5cd4cd7ec6e1a46416806899086363fbf95eecd3bfb9a388b436c9a77243c902
F src/main.c 2af1793f14ae547168e11682720aefc360d3fec75bc1dbabd9565ca09b02c8ab
F src/main.c fb8399bd4731dd01392628fdd452d16abd00216681af58aab34265018441219a
F src/malloc.c 422f7e0498e1c9ef967f06283b6f2c0b16db6b905d8e06f6dbc8baaa3e4e6c5a
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
F src/mem1.c 3bb59158c38e05f6270e761a9f435bf19827a264c13d1631c58b84bdc96d73b2
@@ -744,17 +744,17 @@ F src/random.c 606b00941a1d7dd09c381d3279a058d771f406c5213c9932bbd93d5587be4b9c
F src/resolve.c 7145e41ad75e04a811b326aa5faf83c2e071480fabd9fc825055a6b889e6cb86
F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97
F src/select.c 7720e5e4ffcdf630691a2208e284a5b4eb507f51a06a380487b10ef5f6a9c8dc
F src/shell.c.in 49689bdd9228e3ff3a199c3e0a214c3601dd8448537bc6790e5b2ac2a594b6d5
F src/sqlite.h.in 2101a2b494cbc282d0dc1c3f631c4fb83060c52876cc9d7615b091ad66d932b1
F src/shell.c.in 7ba51656c54cb0d3ecaa70c35e20ae67c25778431d1d9355d5f6486b54c86c12
F src/sqlite.h.in efc3f7aa00a2bb01c087435e6fa5f86103e310e6c3ea072b12cc110cf2715a75
F src/sqlite3.rc 015537e6ac1eec6c7050e17b616c2ffe6f70fca241835a84a4f0d5937383c479
F src/sqlite3ext.h 0efd4723bad9124ea1f581d9f1ea0254ac1c6f3e5fb29e4f3dcf36c72485a456
F src/sqliteInt.h ddeeebaff5d345d5d338f823f492ac99c2918dd69616070de77fd65f1a8b67d8
F src/sqliteLimit.h 7617f2ee673dab382046beba4552283f442cf1a181bb169ac38eb908135dd8da
F src/sqliteInt.h 95a3e8fcf076b1dd54699718c98b2157c4ed9b36020faa0dfef75b698e6d64d2
F src/sqliteLimit.h c433b3fdb5e52f4226bf78d7e8081dff8fd8fbb0ce0cb1a5fee282aaa8976813
F src/status.c 7565d63a79aa2f326339a24a0461a60096d0bd2bce711fefb50b5c89335f3592
F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
F src/tclsqlite.c ed8f7cd15cf56e05a31270d002598f349c1c17f5a21b9f8b55688a519f633ec6
F src/tclsqlite.h 614b3780a62522bc9f8f2b9fb22689e8009958e7aa77e572d0f3149050af348a
F src/test1.c bd9e5123ef2136c960a16c09a1abfbcb6c1498e5193deb2acee188260a31a473
F src/test1.c 83f56d24b5de0965af7b245dc0199690389772e3813f8bca2c88f11e524982fe
F src/test2.c a61ed01d9264a1db74ab42fbc981fc66165f85d5e3947e92be61a73e79ec4f2d
F src/test3.c c959fe0c3b04157483f5a6fa1950c1f222e062d920fee0a8e70410c6b6d45522
F src/test4.c 0ac87fc13cdb334ab3a71823f99b6c32a6bebe5d603cd6a71d84c823d43a25a0
@@ -767,7 +767,7 @@ F src/test_backup.c a2bfd90d2ff2511b8635507bdb30fa9b605ade19c16b533066cae3077f5b
F src/test_bestindex.c d75fad21369d80910238032bcf8d9ca1f2bffda13c1ceec63bfbb7f704448b15
F src/test_blob.c 3a946319c1b062a58d249c67be099c3bc1ec52f2e6ba23b1867699f0b8189ac2
F src/test_btree.c 28283787d32b8fa953eb77412ad0de2c9895260e4e5bd5a94b3c7411664f90d5
F src/test_config.c ac3e4e5e3f5d23a3b604f64b98920a18411f9aa38d58ccd1f5be21103237b2e5
F src/test_config.c 45b83ce7981fd01c58e85b67955bc6a344da5abfb4db1c3f2ba6dcc7adc85d83
F src/test_delete.c d0e8f6dc55cfc98a7c27c057fb88d512260564bf0b611482656c68b8f7f401ed
F src/test_demovfs.c 3efa2adf4f21e10d95521721687d5ca047aea91fa62dd8cc22ac9e5a9c942383
F src/test_devsym.c 649434ed34d0b03fbd5a6b42df80f0f9a7e53f94dd1710aad5dd8831e91c4e86
@@ -804,7 +804,7 @@ F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
F src/threads.c 85d8b9f05f78211c61e3739ab5db761d7118766d1916ae7f2764735106bc4e13
F src/tokenize.c e9d52d9f7374d82dadcd11726bea8a597d43709d6672704f3f0375bf1d726912
F src/treeview.c feaa59f14db4f7b5aacca9c5ad5aeb562c1f98262c1ffd74371f4186ade91fc5
F src/trigger.c 74bc99aaa36dc820481960d4cde3cd7f060964525deebd527eee55ac3b6a2895
F src/trigger.c 0ddd0ae0ed85498deb721720303d3931969c3d6d28dadd0f0c33fd20bc3cdbf2
F src/update.c 3e5e7ff66fa19ebe4d1b113d480639a24cc1175adbefabbd1a948a07f28e37cf
F src/upsert.c dd9f0fcccbfb4f20e1026a21a7254ba3f2c08e9cfa92affaff5b5ec3b00ea549
F src/utf.c 7267c3fb9e2467020507601af3354c2446c61f444387e094c779dccd5ca62165
@@ -1692,7 +1692,7 @@ F test/spellfix2.test dfc8f519a3fc204cb2dfa8b4f29821ae90f6f8c3
F test/spellfix3.test 0f9efaaa502a0e0a09848028518a6fb096c8ad33
F test/spellfix4.test 7c56a09de68b95051ef0627fe235e514efbba2aa816dc2a9c5c670d98877e632
F test/sqldiff1.test 1b7ab4f312442c5cc6b3a5f299fa8ca051416d1dd173cb1126fd51bf64f2c3fb
F test/sqllimits1.test aa8b02192c0ce71bd64ad2e475f5584739119143f11283ce6764339636fdc9f5
F test/sqllimits1.test c4545743e6e374d1c2b61f8c23546cbd7cce994c729b53e426a05f7688ac2e51
F test/sqllog.test 6af6cb0b09f4e44e1917e06ce85be7670302517a
F test/starschema1.test f5388cd32527ab18d3f98f9e3402ec780f6a186e04e0d9c8531d7568ee734e11
F test/startup.c 1beb5ca66fcc0fce95c3444db9d1674f90fc605499a574ae2434dcfc10d22805
@@ -1906,7 +1906,7 @@ F test/trans.test 45f6f9ab6f66a7b5744f1caac06b558f95da62501916906cf55586a896f9f4
F test/trans2.test 62bd045bfc7a1c14c5ba83ba64d21ade31583f76
F test/trans3.test 91a100e5412b488e22a655fe423a14c26403ab94
F test/transitive1.test d6252d06ddc104d13372fce0da93af501546bf5d75cb4d2a1f83b8c27238997a
F test/trigger1.test 141bd2bbfa82fa91aed7391f50517373c9823ff8f55af35e56313dbc75112ca1
F test/trigger1.test e8c2d09342c26ab99e2e2dbef9a0f3a789e43492608637b1614b1f6cc04ce9fc
F test/trigger2.test 30fcb3a6aa6782020d47968735ee6086ed795f73a7affa9406c8d5a36e7b5265
F test/trigger3.test aa640bb2bbb03edd5ff69c055117ea088f121945
F test/trigger4.test 74700b76ebf3947b2f7a92405141eb2cf2a5d359
@@ -2219,8 +2219,8 @@ F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee
F tool/warnings.sh a554d13f6e5cf3760f041b87939e3d616ec6961859c3245e8ef701d1eafc2ca2
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
F tool/winmain.c 00c8fb88e365c9017db14c73d3c78af62194d9644feaf60e220ab0f411f3604c
P e53c5fd75f3e0b7642acb4ca1cd4ef8155f256986bd6f112f372360a434cd4bf
R 0140e2988d8041ec5fb49a24826c2ee5
U stephan
Z e045cd4b15eacb90149093e2d74f5645
P 2df4fe72f74afb650e23c3643e61ec5bf8a3f1d163af9adbc4ce8ba4c1f895ec
R 83901b437f2bcf333fd9e8706583327f
U drh
Z 59f61ab32d908d034d9fef2583905ec5
# Remove this line to create a well-formed Fossil manifest.

View File

@@ -1 +1 @@
2df4fe72f74afb650e23c3643e61ec5bf8a3f1d163af9adbc4ce8ba4c1f895ec
6fbed57b1447725ae9d923d69b509fd5932d8c6bae6cf6ac0d1248a943752a58

View File

@@ -2993,6 +2993,7 @@ static const int aHardLimit[] = {
SQLITE_MAX_WORKER_THREADS,
SQLITE_MAX_PARSER_DEPTH,
SQLITE_MAX_SCHEMA,
SQLITE_MAX_TRIGGER_STEPS,
};
/*
@@ -3034,6 +3035,9 @@ static const int aHardLimit[] = {
#if SQLITE_MAX_WORKER_THREADS<0 || SQLITE_MAX_WORKER_THREADS>50
# error SQLITE_MAX_WORKER_THREADS must be between 0 and 50
#endif
#if SQLITE_MAX_TRIGGER_STEPS<0 || SQLITE_MAX_TRIGGER_STEPS>65535
# error SQLITE_MAX_TRIGGER_STEPS must be between 0 and 65535
#endif
/*
@@ -3076,7 +3080,8 @@ int sqlite3_limit(sqlite3 *db, int limitId, int newLimit){
assert( aHardLimit[SQLITE_LIMIT_TRIGGER_DEPTH]==SQLITE_MAX_TRIGGER_DEPTH );
assert( aHardLimit[SQLITE_LIMIT_WORKER_THREADS]==SQLITE_MAX_WORKER_THREADS );
assert( aHardLimit[SQLITE_LIMIT_SCHEMA]==SQLITE_MAX_SCHEMA );
assert( SQLITE_LIMIT_SCHEMA==(SQLITE_N_LIMIT-1) );
assert( aHardLimit[SQLITE_LIMIT_TRIGGER_STEPS]==SQLITE_MAX_TRIGGER_STEPS );
assert( SQLITE_LIMIT_TRIGGER_STEPS==(SQLITE_N_LIMIT-1) );
if( limitId<0 || limitId>=SQLITE_N_LIMIT ){

View File

@@ -10901,6 +10901,7 @@ static int do_meta_command(const char *zLine, ShellState *p){
{ "trigger_depth", SQLITE_LIMIT_TRIGGER_DEPTH },
{ "worker_threads", SQLITE_LIMIT_WORKER_THREADS },
{ "schema", SQLITE_LIMIT_SCHEMA },
{ "trigger_steps", SQLITE_LIMIT_TRIGGER_STEPS },
};
int i, n2;
open_db(p, 0);

View File

@@ -4436,6 +4436,10 @@ int sqlite3_limit(sqlite3*, int id, int newVal);
** [[SQLITE_LIMIT_SCHEMA]] ^(<dt>SQLITE_LIMIT_SCHEMA</dt>
** <dd>The maximum number of objects (tables, indexes, triggers, and views)
** defined by the database schema.</dd>)^
**
** [[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>)^
** </dl>
*/
#define SQLITE_LIMIT_LENGTH 0
@@ -4452,6 +4456,7 @@ int sqlite3_limit(sqlite3*, int id, int newVal);
#define SQLITE_LIMIT_WORKER_THREADS 11
#define SQLITE_LIMIT_PARSER_DEPTH 12
#define SQLITE_LIMIT_SCHEMA 13
#define SQLITE_LIMIT_TRIGGER_STEPS 14
/*
** CAPI3REF: Prepare Flags

View File

@@ -1561,7 +1561,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_SCHEMA+1)
#define SQLITE_N_LIMIT (SQLITE_LIMIT_TRIGGER_STEPS+1)
/*
** Lookaside malloc is a set of fixed-size buffers that can be used

View File

@@ -294,3 +294,11 @@
#ifndef SQLITE_MAX_SCHEMA
# define SQLITE_MAX_SCHEMA 10000000
#endif
/*
** Maximum number of SQL statements allowed in the body of a single
** trigger.
*/
#ifndef SQLITE_MAX_TRIGGER_STEPS
# define SQLITE_MAX_TRIGGER_STEPS 65000
#endif

View File

@@ -7477,10 +7477,11 @@ static int SQLITE_TCLAPI test_limit(
{ "SQLITE_LIMIT_TRIGGER_DEPTH", SQLITE_LIMIT_TRIGGER_DEPTH },
{ "SQLITE_LIMIT_WORKER_THREADS", SQLITE_LIMIT_WORKER_THREADS },
{ "SQLITE_LIMIT_SCHEMA", SQLITE_LIMIT_SCHEMA },
{ "SQLITE_LIMIT_TRIGGER_STEPS", SQLITE_LIMIT_TRIGGER_STEPS },
/* Out of range test cases */
{ "SQLITE_LIMIT_TOOSMALL", -1, },
{ "SQLITE_LIMIT_TOOBIG", SQLITE_LIMIT_SCHEMA+1 },
{ "SQLITE_LIMIT_TOOBIG", SQLITE_LIMIT_TRIGGER_STEPS+1 },
};
int i, id = 0;
int val;

View File

@@ -828,6 +828,7 @@ Tcl_SetVar2(interp, "sqlite_options", "mergesort", "1", TCL_GLOBAL_ONLY);
LINKVAR( MAX_DEFAULT_PAGE_SIZE );
LINKVAR( MAX_WORKER_THREADS );
LINKVAR( MAX_SCHEMA );
LINKVAR( MAX_TRIGGER_STEPS );
{
static const int cv_TEMP_STORE = SQLITE_TEMP_STORE;

View File

@@ -332,6 +332,7 @@ void sqlite3FinishTrigger(
DbFixer sFix; /* Fixer object */
int iDb; /* Database containing the trigger */
Token nameToken; /* Trigger name for error reporting */
u64 n; /* Number of steps */
pParse->pNewTrigger = 0;
if( NEVER(pParse->nErr) || !pTrig ) goto triggerfinish_cleanup;
@@ -339,10 +340,14 @@ void sqlite3FinishTrigger(
iDb = sqlite3SchemaToIndex(pParse->db, pTrig->pSchema);
assert( iDb>=00 && iDb<db->nDb );
pTrig->step_list = pStepList;
while( pStepList ){
for(n=0; pStepList; n++){
pStepList->pTrig = pTrig;
pStepList = pStepList->pNext;
}
if( n>pParse->db->aLimit[SQLITE_LIMIT_TRIGGER_STEPS] ){
sqlite3ErrorMsg(pParse, "trigger \"%w\" contains too many steps", zName);
goto triggerfinish_cleanup;
}
sqlite3TokenInit(&nameToken, pTrig->zName);
sqlite3FixInit(&sFix, pParse, iDb, "trigger", &nameToken);
if( sqlite3FixTriggerStep(&sFix, pTrig->step_list)

View File

@@ -66,6 +66,10 @@ do_test sqllimits1-1.13 {
sqlite3_limit db SQLITE_LIMIT_SCHEMA 999999999
sqlite3_limit db SQLITE_LIMIT_SCHEMA -1
} $SQLITE_MAX_SCHEMA
do_test sqllimits1-1.14 {
sqlite3_limit db SQLITE_LIMIT_TRIGGER_STEPS 999999999
sqlite3_limit db SQLITE_LIMIT_TRIGGER_STEPS -1
} $SQLITE_MAX_TRIGGER_STEPS
# Limit parameters out of range.
#

View File

@@ -851,4 +851,29 @@ do_catchsql_test trigger1-24.2 {
INSERT INTO t1 VALUES(9876);
} {1 {attempt to insert 9876 where is not a power of 2}}
# 2026-08-18 Limit to the number of statements in a trigger.
#
reset_db
do_execsql_test trigger1-25.1 {
CREATE TABLE t1(x);
CREATE TABLE t2(y);
} {}
sqlite3_limit db SQLITE_LIMIT_TRIGGER_STEPS 3
do_execsql_test trigger1-25.2 {
CREATE TRIGGER r1 AFTER INSERT ON t1 BEGIN
SELECT * FROM t2;
SELECT * FROM t2;
SELECT * FROM t2;
END;
} {}
do_catchsql_test trigger1-25.3 {
CREATE TRIGGER r2 AFTER UPDATE ON t1 BEGIN
SELECT * FROM t2;
SELECT * FROM t2;
SELECT * FROM t2;
SELECT * FROM t2;
END;
} {1 {trigger "r2" contains too many steps}}
finish_test