Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 9e91a1fe89 | |||
| 9432655038 | |||
| fef2233090 | |||
| d26ac414c8 | |||
| ef4abc0a63 |
+23
-24
@@ -695,8 +695,8 @@ other than that, the order of directives in Lemon is arbitrary.</p>
|
||||
<li><tt><a href='#parse_failure'>%parse_failure</a></tt>
|
||||
<li><tt><a href='#pright'>%right</a></tt>
|
||||
<li><tt><a href='#reallc'>%realloc</a></tt>
|
||||
<li><tt><a href='#reallc'>%reallocx</a></tt>
|
||||
<li><tt><a href='#stack_overflow'>%stack_overflow</a></tt>
|
||||
<li><tt><a href='#reallc'>%stack_size_limit</a></tt>
|
||||
<li><tt><a href='#stack_size'>%stack_size</a></tt>
|
||||
<li><tt><a href='#start_symbol'>%start_symbol</a></tt>
|
||||
<li><tt><a href='#syntax_error'>%syntax_error</a></tt>
|
||||
@@ -1204,34 +1204,33 @@ the wildcard token and some other token, the other token is always used.
|
||||
The wildcard token is only matched if there are no alternatives.</p>
|
||||
|
||||
<a id='reallc'></a>
|
||||
<h4>4.4.26 The <tt>%realloc</tt>, <tt>%reallocx</tt>,
|
||||
and <tt>%free</tt> directives</h4>
|
||||
<h4>4.4.26 The <tt>%realloc</tt>, <tt>%free</tt>, and
|
||||
<tt>%stack_size_limit</tt> directives</h4>
|
||||
|
||||
<p>The <tt>%realloc</tt>, <tt>%reallocx</tt>, and <tt>%free</tt>
|
||||
directives defines function that allocate and free heap memory.
|
||||
The signatures of th3 %realloc and %free are the same as
|
||||
realloc() and free() functions from the standard C library.
|
||||
The %reallocx function has the same semantics as %realloc but
|
||||
takes four parameters instead of two:
|
||||
<ol>
|
||||
<li> A pointer to the space to be reallocated, or NULL for a new allocation,
|
||||
<li> The number of elements to allocate,
|
||||
<li> The size of each element,
|
||||
<li> The %extra parameter.
|
||||
</ol>
|
||||
The extra parameters of %reallocx can be used, for example, to monitor
|
||||
the parser stack size and raise an error if it exceeds application-defined
|
||||
limits.
|
||||
If both %reallocx and %realloc are defined, then %reallocx is used
|
||||
and %realloc is ignored.
|
||||
<p>The <tt>%realloc</tt> and <tt>%free</tt> directives defines function
|
||||
that allocate and free heap memory. The signatures and semantics of
|
||||
these functions are similar to the realloc() and free() functions from
|
||||
the standard C library, except that these functions take an extra
|
||||
parameter at the end that is determined by %extra_context. If
|
||||
%extra_context is not defined, then the extra argument is 0. The
|
||||
extra parameter provides the capability to do better error reporting
|
||||
in the event of a memory allocation error, and/or to use an alternative
|
||||
private application heap.
|
||||
|
||||
<p>If %free is defined and one of %realloc and %reallocx is
|
||||
defined then the functions are used to allocate and free
|
||||
memory for supplemental parser stack space, if the initial
|
||||
parse stack space is exceeded. The initial parser stack size
|
||||
<p>If both of these functions are defined then they are used to
|
||||
allocate and free memory for supplemental parser stack space, if
|
||||
the initial parse stack space is exceeded. The initial parser stack size
|
||||
is specified by either <tt>%stack_size</tt> or the
|
||||
-DYYSTACKDEPTH compile-time flag.
|
||||
|
||||
<p>The <tt>%stack_size_limit</tt> directive defines a function that returns
|
||||
the maximum allowed parser stack size. If this diretive does not exist,
|
||||
no size limit is enforced. This function takes a single argument which
|
||||
is the %extra_context value or "0" if %extra_context is not defined.
|
||||
The function should return an integer that is the maximum
|
||||
number of parser stack entries. If more stack space
|
||||
than this is needed, the %stack_overflow code is invoked.
|
||||
|
||||
<a id='errors'></a>
|
||||
<h2>5.0 Error Processing</h2>
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
C Pervent\sthe\sparser\sstack\sfrom\sgrowing\sto\sbe\slarger\sthan\s100\splus\sfour\stimes\nthe\sSQLITE_LIMIT_EXPR_DEPTH\ssetting.
|
||||
D 2025-11-18T02:24:46.688
|
||||
C Modify\sthe\s"%realloc"\sand\s"%free"\scommands\sin\sLemon\sso\sthat\sthe\sfunctions\nthey\sspecify\stake\san\sextra\sparameter\sat\sthe\send,\sthe\s%extra_context\spointer.\nThis\sallows\sthe\simplementation\sto\sdistinguish\sbetween\sOOM\serrors\sand\nfailures\sto\sincrease\sthe\sstack\ssize\sbecause\sof\sthe\sstack\ssize\slimit.
|
||||
D 2025-11-18T15:40:02.793
|
||||
F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x
|
||||
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
||||
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
||||
@@ -60,7 +60,7 @@ F doc/compile-for-unix.md c9dce1ddd4bf0d25efccc5c63eb047e78c01ce06a6ff29c73e0a8a
|
||||
F doc/compile-for-windows.md f9e74d74da88f384edd5809f825035e071608f00f7f39c0e448df7b3982f979c
|
||||
F doc/json-enhancements.md e356fc834781f1f1aa22ee300027a270b2c960122468499bf347bb123ce1ea4f
|
||||
F doc/jsonb.md acd77fc3a709f51242655ad7803510c886aa8304202fa9cf2abc5f5c4e9d7ae5
|
||||
F doc/lemon.html 0e4b854b5ca0cf3600fec4da454197f651e8a0d411a90653703e75474486ad31
|
||||
F doc/lemon.html 2085fda0a90a94fe92159a79dccc5c30d5a2313524887a31659cd66162f17233
|
||||
F doc/pager-invariants.txt 83aa3a4724b2d7970cc3f3461f0295c46d4fc19a835a5781cbb35cb52feb0577
|
||||
F doc/tcl-extension-testing.md b88861804fc1eaf83249f8e206334189b61e150c360e1b80d0dcf91af82354f5
|
||||
F doc/testrunner.md 5ee928637e03f136a25fef852c5ed975932e31927bd9b05a574424ae18c31019
|
||||
@@ -694,7 +694,7 @@ F src/insert.c dfd311b0ac2d4f6359e62013db67799757f4d2cc56cca5c10f4888acfbbfa3fd
|
||||
F src/json.c fb031340edee159c07ad37dbe668ffe945ed86f525b0eb3822e4a67cbc498a72
|
||||
F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
|
||||
F src/loadext.c 4747f72084dc80520a2d23e5bb0bc0760672208a81a2b115ce0b657acd65edf4
|
||||
F src/main.c eaf5215917b7e8b34ddea013524287f6d5021ba0fc70202e7602e225ef0d16bf
|
||||
F src/main.c c99e86fd7dc6c8c2c0f67395562e3300bca2780b845db9bdc2bdac6acf13c6aa
|
||||
F src/malloc.c 410e570b30c26cc36e3372577df50f7a96ee3eed5b2b161c6b6b48773c650c5e
|
||||
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
|
||||
F src/mem1.c 3bb59158c38e05f6270e761a9f435bf19827a264c13d1631c58b84bdc96d73b2
|
||||
@@ -720,7 +720,7 @@ F src/os_win.c a89b501fc195085c7d6c9eec7f5bd782625e94bb2a96b000f4d009703df1083f
|
||||
F src/os_win.h 4c247cdb6d407c75186c94a1e84d5a22cbae4adcec93fcae8d2bc1f956fd1f19
|
||||
F src/pager.c a81461de271ac4886ad75b7ca2cca8157a48635820c4646cd2714acdc2c17e5f
|
||||
F src/pager.h 6137149346e6c8a3ddc1eeb40aee46381e9bc8b0fcc6dda8a1efde993c2275b8
|
||||
F src/parse.y 04c6c7278939e3c6307ed3c6ed7482d2928e692560dbe8e57f524851a934e25c
|
||||
F src/parse.y 4266eeb7dd9a03195e7701e9f2272fac2d950f2c1e629da49aa62b272611eac3
|
||||
F src/pcache.c 588cc3c5ccaaadde689ed35ce5c5c891a1f7b1f4d1f56f6cf0143b74d8ee6484
|
||||
F src/pcache.h 1497ce1b823cf00094bb0cf3bac37b345937e6f910890c626b16512316d3abf5
|
||||
F src/pcache1.c 131ca0daf4e66b4608d2945ae76d6ed90de3f60539afbd5ef9ec65667a5f2fcd
|
||||
@@ -731,17 +731,17 @@ F src/random.c 606b00941a1d7dd09c381d3279a058d771f406c5213c9932bbd93d5587be4b9c
|
||||
F src/resolve.c 5616fbcf3b833c7c705b24371828215ad0925d0c0073216c4f153348d5753f0a
|
||||
F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97
|
||||
F src/select.c ba9cd07ffa3277883c1986085f6ddc4320f4d35d5f212ab58df79a7ecc1a576a
|
||||
F src/shell.c.in ceb0a9cc008ac82d8d2e6ef353db14a54bc40dfd60a8cfbb6bc98d071f538761
|
||||
F src/sqlite.h.in 667dff873941366da98da3200cf757ac05dfb62ea785e6642e33dd586ae5285c
|
||||
F src/shell.c.in 2e4d5dc7978fbf586f590cdc9a30dbf01398bb81159f846293f840f016d218ec
|
||||
F src/sqlite.h.in f1363321ca55cc2feaa289e9fe6dfb08102a28c54edf005564711a2348b06eef
|
||||
F src/sqlite3.rc 015537e6ac1eec6c7050e17b616c2ffe6f70fca241835a84a4f0d5937383c479
|
||||
F src/sqlite3ext.h 5d5330f5f8461f5ce74960436ddcfa53ecd09c2b8b23901e22ae38aec3243998
|
||||
F src/sqliteInt.h 88f7fc9ce1630d9a5f7e0a8e1f3287cdc63882fba985c18e7eee1b9f457f59aa
|
||||
F src/sqliteLimit.h fe70bd8983e5d317a264f2ea97473b359faf3ebb0827877a76813f5cf0cdc364
|
||||
F src/sqliteInt.h e53f8c6f9a809206b8db9524d294c29e21d0c07bea5114121980bbef30333c6b
|
||||
F src/sqliteLimit.h 0a5516b4ec192a205c541e05f67009028a9451dc6678aae4cf8e68596903c246
|
||||
F src/status.c 7565d63a79aa2f326339a24a0461a60096d0bd2bce711fefb50b5c89335f3592
|
||||
F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
|
||||
F src/tclsqlite.c 3c604c49e6cf4211960a9ddb9505280fd22cde32175f40884c641c0f5a286036
|
||||
F src/tclsqlite.h 614b3780a62522bc9f8f2b9fb22689e8009958e7aa77e572d0f3149050af348a
|
||||
F src/test1.c 5d061afe479c7364842e0170be7220dea13389575fa6030d30b3e20bec4e1f75
|
||||
F src/test1.c 0e71fbcb484a271564e98e0158192c28c24f5521594218c3ba48bcb4cf634f91
|
||||
F src/test2.c 62f0830958f9075692c29c6de51b495ae8969e1bef85f239ffcd9ba5fb44a5ff
|
||||
F src/test3.c 432646f581d8af1bb495e58fc98234380250954f5d5535e507fc785eccc3987a
|
||||
F src/test4.c 0ac87fc13cdb334ab3a71823f99b6c32a6bebe5d603cd6a71d84c823d43a25a0
|
||||
@@ -1420,7 +1420,7 @@ F test/misc1.test e3e36262aff1bd9b8b9bf1eeb3af04adb3fc1e23f0a92dbff708bba9e939ac
|
||||
F test/misc2.test a1a3573cc02662becd967766021d6f16c54684d56df5f227481c7ef0d9df0bd0
|
||||
F test/misc3.test 651b88bca19b8ff6a7b6af73dae00c3fd5b3ea5bee0c0d1d91abd4c4b4748718
|
||||
F test/misc4.test 10cd6addb2fa9093df4751a1b92b50440175dd5468a6ec84d0386e78f087db0e
|
||||
F test/misc5.test 02fcaf4d42405be02ec975e946270a50b0282dac98c78303ade0d1392839d2b8
|
||||
F test/misc5.test 0a5d7604e197f10ee471280bfcaaf8229f9d8e2eebfef2c8853222cbc1ea9cd5
|
||||
F test/misc6.test 953cc693924d88e6117aeba16f46f0bf5abede91
|
||||
F test/misc7.test d595599972ec0b436985f0f02f243b68500ffc977b9b3194ec66c0866cfddcab
|
||||
F test/misc8.test 08d2380bc435486b12161521f225043ac2be26f02471c2c1ea4cac0b1548edbd
|
||||
@@ -2101,8 +2101,8 @@ F tool/genfkey.README e550911fa984c8255ebed2ef97824125d83806eb5232582700de949edf
|
||||
F tool/genfkey.test b6afd7b825d797a1e1274f519ab5695373552ecad5cd373530c63533638a5a4f
|
||||
F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce
|
||||
F tool/index_usage.c f62a0c701b2c7ff2f3e21d206f093c123f222dbf07136a10ffd1ca15a5c706c5
|
||||
F tool/lemon.c fda0511d71764674919872a1457d2f86a7d48b13bfcf98741955c1b217a84570
|
||||
F tool/lempar.c a59c5474bdd148ca4c61f2977c7ce6b49e99c48a333b6d48fc7ceacf2292b43a
|
||||
F tool/lemon.c 4150f2020d453cfa46b6fa45542e59b923ad7eab063fb4ca20777995622cab0b
|
||||
F tool/lempar.c b57e1780bf8098dd4a9a5bba537f994276ea825a420f6165153e5894dc2dfb07
|
||||
F tool/libvers.c caafc3b689638a1d88d44bc5f526c2278760d9b9
|
||||
F tool/loadfts.c 63412f9790e5e8538fbde0b4f6db154aaaf80f7a10a01e3c94d14b773a8dd5a6
|
||||
F tool/logest.c c34e5944318415de513d29a6098df247a9618c96d83c38d4abd88641fe46e669
|
||||
@@ -2166,11 +2166,8 @@ F tool/version-info.c 33d0390ef484b3b1cb685d59362be891ea162123cea181cb8e6d2cf6dd
|
||||
F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee87c1b31a7
|
||||
F tool/warnings.sh d924598cf2f55a4ecbc2aeb055c10bd5f48114793e7ba25f9585435da29e7e98
|
||||
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
|
||||
P ea48567ac54e4949a8b68977a58a5de7946e074ae8737133071d02f40ac97f34
|
||||
R 94faba231c7b1fe01c357a8fbebddcb3
|
||||
T *branch * parser-recursion-limit
|
||||
T *sym-parser-recursion-limit *
|
||||
T -sym-trunk *
|
||||
P 41fe19ab054acda912bc32dd6f9c6412416ab1af6cf55515e96c89fb55b46424
|
||||
R eaedc8a6fb66bf638a3308ee531542c6
|
||||
U drh
|
||||
Z ef6a72fd333d3e7f2a3d9cd4902c91e6
|
||||
Z cd45861cdfb2c55973d9d3bae678a719
|
||||
# Remove this line to create a well-formed Fossil manifest.
|
||||
|
||||
+2
-2
@@ -1,2 +1,2 @@
|
||||
branch parser-recursion-limit
|
||||
tag parser-recursion-limit
|
||||
branch parser-stack-size
|
||||
tag parser-stack-size
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
5728129e5432500550096e2a1350897881f0379b49b60faf49481c505b1eb323
|
||||
9862c945d9a8531f9bef123aee9ed1fd3f64542250a57beb3a150227bc3c1a12
|
||||
|
||||
+3
-1
@@ -2930,6 +2930,7 @@ static const int aHardLimit[] = {
|
||||
SQLITE_MAX_VARIABLE_NUMBER, /* IMP: R-38091-32352 */
|
||||
SQLITE_MAX_TRIGGER_DEPTH,
|
||||
SQLITE_MAX_WORKER_THREADS,
|
||||
SQLITE_MAX_PARSER_DEPTH,
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -2999,6 +3000,7 @@ int sqlite3_limit(sqlite3 *db, int limitId, int newLimit){
|
||||
assert( aHardLimit[SQLITE_LIMIT_SQL_LENGTH]==SQLITE_MAX_SQL_LENGTH );
|
||||
assert( aHardLimit[SQLITE_LIMIT_COLUMN]==SQLITE_MAX_COLUMN );
|
||||
assert( aHardLimit[SQLITE_LIMIT_EXPR_DEPTH]==SQLITE_MAX_EXPR_DEPTH );
|
||||
assert( aHardLimit[SQLITE_LIMIT_PARSER_DEPTH]==SQLITE_MAX_PARSER_DEPTH );
|
||||
assert( aHardLimit[SQLITE_LIMIT_COMPOUND_SELECT]==SQLITE_MAX_COMPOUND_SELECT);
|
||||
assert( aHardLimit[SQLITE_LIMIT_VDBE_OP]==SQLITE_MAX_VDBE_OP );
|
||||
assert( aHardLimit[SQLITE_LIMIT_FUNCTION_ARG]==SQLITE_MAX_FUNCTION_ARG );
|
||||
@@ -3008,7 +3010,7 @@ int sqlite3_limit(sqlite3 *db, int limitId, int newLimit){
|
||||
assert( aHardLimit[SQLITE_LIMIT_VARIABLE_NUMBER]==SQLITE_MAX_VARIABLE_NUMBER);
|
||||
assert( aHardLimit[SQLITE_LIMIT_TRIGGER_DEPTH]==SQLITE_MAX_TRIGGER_DEPTH );
|
||||
assert( aHardLimit[SQLITE_LIMIT_WORKER_THREADS]==SQLITE_MAX_WORKER_THREADS );
|
||||
assert( SQLITE_LIMIT_WORKER_THREADS==(SQLITE_N_LIMIT-1) );
|
||||
assert( SQLITE_LIMIT_PARSER_DEPTH==(SQLITE_N_LIMIT-1) );
|
||||
|
||||
|
||||
if( limitId<0 || limitId>=SQLITE_N_LIMIT ){
|
||||
|
||||
+21
-13
@@ -21,9 +21,11 @@
|
||||
*/
|
||||
}
|
||||
|
||||
// Function used to enlarge the parser stack, if needed
|
||||
%reallocx parserStackRealloc
|
||||
%free sqlite3_free
|
||||
// Setup for the parser stack
|
||||
%stack_size 50 // Initial stack size
|
||||
%stack_size_limit parserStackSizeLimit // Function returning max stack size
|
||||
%realloc parserStackRealloc // realloc() for the stack
|
||||
%free parserStackFree // free() for the stack
|
||||
|
||||
// All token codes are small integers with #defines that begin with "TK_"
|
||||
%token_prefix TK_
|
||||
@@ -49,7 +51,7 @@
|
||||
}
|
||||
}
|
||||
%stack_overflow {
|
||||
if( pParse->nErr==0 ) sqlite3OomFault(pParse->db);
|
||||
if( pParse->nErr==0 ) sqlite3ErrorMsg(pParse, "Recursion limit");
|
||||
}
|
||||
|
||||
// The name of the generated procedure that implements the parser
|
||||
@@ -584,16 +586,22 @@ cmd ::= select(X). {
|
||||
** testing.
|
||||
*/
|
||||
static void *parserStackRealloc(
|
||||
void *pOld, /* Old allocation, or NULL to get a new one */
|
||||
int newCount, /* Number of elements */
|
||||
int unitSize, /* Size of each element */
|
||||
Parse *pParse /* Parsing context */
|
||||
void *pOld, /* Prior allocation */
|
||||
sqlite3_uint64 newSize, /* Requested new alloation size */
|
||||
Parse *pParse /* Parsing context */
|
||||
){
|
||||
if( sqlite3FaultSim(700) ) return 0;
|
||||
if( newCount > pParse->db->aLimit[SQLITE_LIMIT_EXPR_DEPTH]*4+100 ){
|
||||
sqlite3ErrorMsg(pParse, "Recursion limit reached");
|
||||
}
|
||||
return sqlite3_realloc64(pOld, newCount*unitSize);
|
||||
void *p = sqlite3FaultSim(700) ? 0 : sqlite3_realloc(pOld, newSize);
|
||||
if( p==0 ) sqlite3OomFault(pParse->db);
|
||||
return p;
|
||||
}
|
||||
static void parserStackFree(void *pOld, Parse *pParse){
|
||||
(void)pParse;
|
||||
sqlite3_free(pOld);
|
||||
}
|
||||
|
||||
/* Return an integer that is the maximum allowed stack size */
|
||||
static int parserStackSizeLimit(Parse *pParse){
|
||||
return pParse->db->aLimit[SQLITE_LIMIT_PARSER_DEPTH];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10047,6 +10047,7 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
{ "sql_length", SQLITE_LIMIT_SQL_LENGTH },
|
||||
{ "column", SQLITE_LIMIT_COLUMN },
|
||||
{ "expr_depth", SQLITE_LIMIT_EXPR_DEPTH },
|
||||
{ "parser_depth", SQLITE_LIMIT_PARSER_DEPTH },
|
||||
{ "compound_select", SQLITE_LIMIT_COMPOUND_SELECT },
|
||||
{ "vdbe_op", SQLITE_LIMIT_VDBE_OP },
|
||||
{ "function_arg", SQLITE_LIMIT_FUNCTION_ARG },
|
||||
|
||||
@@ -4339,6 +4339,10 @@ int sqlite3_limit(sqlite3*, int id, int newVal);
|
||||
** [[SQLITE_LIMIT_EXPR_DEPTH]] ^(<dt>SQLITE_LIMIT_EXPR_DEPTH</dt>
|
||||
** <dd>The maximum depth of the parse tree on any expression.</dd>)^
|
||||
**
|
||||
** [[SQLITE_LIMIT_PARSER_DEPTH]] ^(<dt>SQLITE_LIMIT_PARSER_DEPTH</dt>
|
||||
** <dd>The maximum depth of the LALR(1) parser stack used to analyze
|
||||
** input SQL statements.</dd>)^
|
||||
**
|
||||
** [[SQLITE_LIMIT_COMPOUND_SELECT]] ^(<dt>SQLITE_LIMIT_COMPOUND_SELECT</dt>
|
||||
** <dd>The maximum number of terms in a compound SELECT statement.</dd>)^
|
||||
**
|
||||
@@ -4383,6 +4387,7 @@ int sqlite3_limit(sqlite3*, int id, int newVal);
|
||||
#define SQLITE_LIMIT_VARIABLE_NUMBER 9
|
||||
#define SQLITE_LIMIT_TRIGGER_DEPTH 10
|
||||
#define SQLITE_LIMIT_WORKER_THREADS 11
|
||||
#define SQLITE_LIMIT_PARSER_DEPTH 12
|
||||
|
||||
/*
|
||||
** CAPI3REF: Prepare Flags
|
||||
|
||||
+1
-1
@@ -1537,7 +1537,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_WORKER_THREADS+1)
|
||||
#define SQLITE_N_LIMIT (SQLITE_LIMIT_PARSER_DEPTH+1)
|
||||
|
||||
/*
|
||||
** Lookaside malloc is a set of fixed-size buffers that can be used
|
||||
|
||||
+22
-4
@@ -66,15 +66,33 @@
|
||||
#endif
|
||||
|
||||
/*
|
||||
** The maximum depth of an expression tree. This is limited to
|
||||
** some extent by SQLITE_MAX_SQL_LENGTH. But sometime you might
|
||||
** want to place more severe limits on the complexity of an
|
||||
** expression. A value of 0 means that there is no limit.
|
||||
** The maximum depth of an expression tree. The expression tree depth
|
||||
** is also limited indirectly by SQLITE_MAX_SQL_LENGTH and by
|
||||
** SQLITE_MAX_PARSER_DEPTH. Reducing the maximum complexity of
|
||||
** expressions can help prevent excess memory usage by hostile SQL.
|
||||
**
|
||||
** A value of 0 for this compile-time option causes all expression
|
||||
** depth limiting code to be omitted.
|
||||
*/
|
||||
#ifndef SQLITE_MAX_EXPR_DEPTH
|
||||
# define SQLITE_MAX_EXPR_DEPTH 1000
|
||||
#endif
|
||||
|
||||
/*
|
||||
** The maximum depth of the LALR(1) stack used in the parser that
|
||||
** interprets SQL inputs. The parser stack depth can also be limited
|
||||
** indirectly by SQLITE_MAX_SQL_LENGTH. Limiting the parser stack
|
||||
** depth can help prevent excess memory usage and excess CPU stack
|
||||
** usage when processing hostile SQL.
|
||||
**
|
||||
** Prior to version 3.45.0 (2024-01-15), the parser stack was
|
||||
** hard-coded to 100 entries, and that worked fine for almost all
|
||||
** applications. So the upper bound on this limit need not be large.
|
||||
*/
|
||||
#ifndef SQLITE_MAX_PARSER_DEPTH
|
||||
# define SQLITE_MAX_PARSER_DEPTH 2500
|
||||
#endif
|
||||
|
||||
/*
|
||||
** The maximum number of terms in a compound SELECT statement.
|
||||
** The code generator for compound SELECT statements does one
|
||||
|
||||
+2
-1
@@ -7370,6 +7370,7 @@ static int SQLITE_TCLAPI test_limit(
|
||||
{ "SQLITE_LIMIT_SQL_LENGTH", SQLITE_LIMIT_SQL_LENGTH },
|
||||
{ "SQLITE_LIMIT_COLUMN", SQLITE_LIMIT_COLUMN },
|
||||
{ "SQLITE_LIMIT_EXPR_DEPTH", SQLITE_LIMIT_EXPR_DEPTH },
|
||||
{ "SQLITE_LIMIT_PARSER_DEPTH", SQLITE_LIMIT_PARSER_DEPTH },
|
||||
{ "SQLITE_LIMIT_COMPOUND_SELECT", SQLITE_LIMIT_COMPOUND_SELECT },
|
||||
{ "SQLITE_LIMIT_VDBE_OP", SQLITE_LIMIT_VDBE_OP },
|
||||
{ "SQLITE_LIMIT_FUNCTION_ARG", SQLITE_LIMIT_FUNCTION_ARG },
|
||||
@@ -7381,7 +7382,7 @@ static int SQLITE_TCLAPI test_limit(
|
||||
|
||||
/* Out of range test cases */
|
||||
{ "SQLITE_LIMIT_TOOSMALL", -1, },
|
||||
{ "SQLITE_LIMIT_TOOBIG", SQLITE_LIMIT_WORKER_THREADS+1 },
|
||||
{ "SQLITE_LIMIT_TOOBIG", SQLITE_LIMIT_PARSER_DEPTH+1 },
|
||||
};
|
||||
int i, id = 0;
|
||||
int val;
|
||||
|
||||
+1
-1
@@ -595,7 +595,7 @@ do_test misc5-7.1.2 {
|
||||
}
|
||||
append sql "0$tail); SELECT * FROM t1;"
|
||||
catchsql $sql
|
||||
} {0 900}
|
||||
} {1 {Recursion limit}}
|
||||
|
||||
|
||||
# Parser stack overflow is silently ignored when it occurs while parsing the
|
||||
|
||||
+37
-24
@@ -494,8 +494,8 @@ struct lemon {
|
||||
char *filename; /* Name of the input file */
|
||||
char *outname; /* Name of the current output file */
|
||||
char *tokenprefix; /* A prefix added to token names in the .h file */
|
||||
char *stackSizeLimit; /* Function to return the stack size limit */
|
||||
char *reallocFunc; /* Function to use to allocate stack space */
|
||||
char *reallocFuncEx; /* Alternative realloc() with context pointer */
|
||||
char *freeFunc; /* Function to use to free stack space */
|
||||
int nconflict; /* Number of parsing conflicts */
|
||||
int nactiontab; /* Number of entries in the yy_action[] table */
|
||||
@@ -2639,12 +2639,12 @@ static void parseonetoken(struct pstate *psp)
|
||||
}else if( strcmp(x,"default_type")==0 ){
|
||||
psp->declargslot = &(psp->gp->vartype);
|
||||
psp->insertLineMacro = 0;
|
||||
}else if( strcmp(x,"stack_size_limit")==0 ){
|
||||
psp->declargslot = &(psp->gp->stackSizeLimit);
|
||||
psp->insertLineMacro = 0;
|
||||
}else if( strcmp(x,"realloc")==0 ){
|
||||
psp->declargslot = &(psp->gp->reallocFunc);
|
||||
psp->insertLineMacro = 0;
|
||||
}else if( strcmp(x,"reallocx")==0 ){
|
||||
psp->declargslot = &(psp->gp->reallocFuncEx);
|
||||
psp->insertLineMacro = 0;
|
||||
}else if( strcmp(x,"free")==0 ){
|
||||
psp->declargslot = &(psp->gp->freeFunc);
|
||||
psp->insertLineMacro = 0;
|
||||
@@ -3719,7 +3719,7 @@ PRIVATE int compute_action(struct lemon *lemp, struct action *ap)
|
||||
return act;
|
||||
}
|
||||
|
||||
#define LINESIZE 1000
|
||||
#define LINESIZE 10000
|
||||
/* The next cluster of routines are for reading the template file
|
||||
** and writing the results to the generated parser */
|
||||
/* The first function transfers data from "in" to "out" until
|
||||
@@ -3754,12 +3754,9 @@ PRIVATE void tplt_xfer(char *name, FILE *in, FILE *out, int *lineno)
|
||||
|
||||
/* Skip forward past the header of the template file to the first "%%"
|
||||
*/
|
||||
PRIVATE void tplt_skip_header(FILE *in, int *lineno)
|
||||
{
|
||||
PRIVATE void tplt_skip_header(FILE *in){
|
||||
char line[LINESIZE];
|
||||
while( fgets(line,LINESIZE,in) && (line[0]!='%' || line[1]!='%') ){
|
||||
(*lineno)++;
|
||||
}
|
||||
while( fgets(line,LINESIZE,in) && (line[0]!='%' || line[1]!='%') ){}
|
||||
}
|
||||
|
||||
/* The next function finds the template file and opens it, returning
|
||||
@@ -3829,12 +3826,14 @@ PRIVATE void tplt_linedir(FILE *out, int lineno, char *filename)
|
||||
filename++;
|
||||
}
|
||||
fprintf(out,"\"\n");
|
||||
fflush(out);
|
||||
}
|
||||
|
||||
/* Print a string to the file and keep the linenumber up to date */
|
||||
PRIVATE void tplt_print(FILE *out, struct lemon *lemp, char *str, int *lineno)
|
||||
{
|
||||
if( str==0 ) return;
|
||||
fflush(out);
|
||||
while( *str ){
|
||||
putc(*str,out);
|
||||
if( *str=='\n' ) (*lineno)++;
|
||||
@@ -3847,6 +3846,7 @@ PRIVATE void tplt_print(FILE *out, struct lemon *lemp, char *str, int *lineno)
|
||||
if (!lemp->nolinenosflag) {
|
||||
(*lineno)++; tplt_linedir(out,*lineno,lemp->outname);
|
||||
}
|
||||
fflush(out);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -4411,6 +4411,13 @@ static void writeRuleText(FILE *out, struct rule *rp){
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Return true if the string is not NULL and not empty.
|
||||
*/
|
||||
static int notnull(const char *z){
|
||||
return z && z[0];
|
||||
}
|
||||
|
||||
|
||||
/* Generate C source code for the parser */
|
||||
void ReportTable(
|
||||
@@ -4447,6 +4454,7 @@ void ReportTable(
|
||||
FILE *sql = file_open(lemp, ".sql", "wb");
|
||||
if( sql==0 ){
|
||||
fclose(in);
|
||||
fclose(out);
|
||||
return;
|
||||
}
|
||||
fprintf(sql,
|
||||
@@ -4545,7 +4553,7 @@ void ReportTable(
|
||||
}
|
||||
}
|
||||
if( lemp->include[0]=='/' ){
|
||||
tplt_skip_header(in,&lineno);
|
||||
tplt_skip_header(in);
|
||||
}else{
|
||||
tplt_xfer(lemp->name,in,out,&lineno);
|
||||
}
|
||||
@@ -4565,7 +4573,7 @@ void ReportTable(
|
||||
if( mhflag ){
|
||||
fprintf(out,"#if INTERFACE\n"); lineno++;
|
||||
}else{
|
||||
fprintf(out,"#ifndef %s%s\n", prefix, lemp->symbols[1]->name);
|
||||
fprintf(out,"#ifndef %s%s\n", prefix, lemp->symbols[1]->name); lineno++;
|
||||
}
|
||||
for(i=1; i<lemp->nterminal; i++){
|
||||
fprintf(out,"#define %s%-30s %2d\n",prefix,lemp->symbols[i]->name,i);
|
||||
@@ -4614,52 +4622,58 @@ void ReportTable(
|
||||
fprintf(out,"#define %sARG_FETCH\n",name); lineno++;
|
||||
fprintf(out,"#define %sARG_STORE\n",name); lineno++;
|
||||
}
|
||||
if( lemp->reallocFuncEx ){
|
||||
fprintf(out,"#define YYREALLOC(A,B,C,D) %s(A,B,C,D)\n",
|
||||
lemp->reallocFuncEx); lineno++;
|
||||
}else if( lemp->reallocFunc ){
|
||||
fprintf(out,"#define YYREALLOC(A,B,C,D) %s(A,B*C)\n",
|
||||
lemp->reallocFunc); lineno++;
|
||||
fprintf(out, "#undef YYREALLOC\n"); lineno++;
|
||||
if( lemp->reallocFunc ){
|
||||
fprintf(out,"#define YYREALLOC %s\n", lemp->reallocFunc); lineno++;
|
||||
}else{
|
||||
fprintf(out,"#define YYREALLOC(A,B,C,D) realloc(A,B*C)\n"); lineno++;
|
||||
fprintf(out,"#define YYREALLOC realloc\n"); lineno++;
|
||||
}
|
||||
fprintf(out, "#undef YYFREE\n"); lineno++;
|
||||
if( lemp->freeFunc ){
|
||||
fprintf(out,"#define YYFREE %s\n", lemp->freeFunc); lineno++;
|
||||
}else{
|
||||
fprintf(out,"#define YYFREE free\n"); lineno++;
|
||||
}
|
||||
if( (lemp->reallocFunc || lemp->reallocFuncEx) && lemp->freeFunc ){
|
||||
fprintf(out, "#undef YYDYNSTACK\n"); lineno++;
|
||||
if( lemp->reallocFunc && lemp->freeFunc ){
|
||||
fprintf(out,"#define YYDYNSTACK 1\n"); lineno++;
|
||||
}else{
|
||||
fprintf(out,"#define YYDYNSTACK 0\n"); lineno++;
|
||||
}
|
||||
if( lemp->ctx && lemp->ctx[0] ){
|
||||
fprintf(out, "#undef YYSIZELIMIT\n"); lineno++;
|
||||
if( notnull(lemp->ctx) ){
|
||||
i = lemonStrlen(lemp->ctx);
|
||||
while( i>=1 && ISSPACE(lemp->ctx[i-1]) ) i--;
|
||||
while( i>=1 && (ISALNUM(lemp->ctx[i-1]) || lemp->ctx[i-1]=='_') ) i--;
|
||||
if( notnull(lemp->stackSizeLimit) ){
|
||||
fprintf(out,"#define YYSIZELIMIT %s\n", lemp->stackSizeLimit); lineno++;
|
||||
}
|
||||
fprintf(out,"#define %sCTX(P) ((P)->%s)\n",name,&lemp->ctx[i]); lineno++;
|
||||
fprintf(out,"#define %sCTX_SDECL %s;\n",name,lemp->ctx); lineno++;
|
||||
fprintf(out,"#define %sCTX_PDECL ,%s\n",name,lemp->ctx); lineno++;
|
||||
fprintf(out,"#define %sCTX_PARAM ,%s\n",name,&lemp->ctx[i]); lineno++;
|
||||
fprintf(out,"#define %sCTX_FIELD %s\n",name,&lemp->ctx[i]); lineno++;
|
||||
fprintf(out,"#define %sCTX_FETCH %s=yypParser->%s;\n",
|
||||
name,lemp->ctx,&lemp->ctx[i]); lineno++;
|
||||
fprintf(out,"#define %sCTX_STORE yypParser->%s=%s;\n",
|
||||
name,&lemp->ctx[i],&lemp->ctx[i]); lineno++;
|
||||
}else{
|
||||
fprintf(out,"#define %sCTX(P) 0\n",name); lineno++;
|
||||
fprintf(out,"#define %sCTX_SDECL\n",name); lineno++;
|
||||
fprintf(out,"#define %sCTX_PDECL\n",name); lineno++;
|
||||
fprintf(out,"#define %sCTX_PARAM\n",name); lineno++;
|
||||
fprintf(out,"#define %sCTX_FIELD yyhwm\n", name); lineno++;
|
||||
fprintf(out,"#define %sCTX_FETCH\n",name); lineno++;
|
||||
fprintf(out,"#define %sCTX_STORE\n",name); lineno++;
|
||||
}
|
||||
if( mhflag ){
|
||||
fprintf(out,"#endif\n"); lineno++;
|
||||
}
|
||||
fprintf(out, "#undef YYERRORSYMBOL\n"); lineno++;
|
||||
fprintf(out, "#undef YYERRSYMDT\n"); lineno++;
|
||||
if( lemp->errsym && lemp->errsym->useCnt ){
|
||||
fprintf(out,"#define YYERRORSYMBOL %d\n",lemp->errsym->index); lineno++;
|
||||
fprintf(out,"#define YYERRSYMDT yy%d\n",lemp->errsym->dtnum); lineno++;
|
||||
}
|
||||
fprintf(out,"#undef YYFALLBACK\n"); lineno++;
|
||||
if( lemp->has_fallback ){
|
||||
fprintf(out,"#define YYFALLBACK 1\n"); lineno++;
|
||||
}
|
||||
@@ -5011,7 +5025,6 @@ void ReportTable(
|
||||
sp2->destLineno = -1; /* Avoid emitting this destructor again */
|
||||
}
|
||||
}
|
||||
|
||||
emit_destructor_code(out,lemp->symbols[i],lemp,&lineno);
|
||||
fprintf(out," break;\n"); lineno++;
|
||||
}
|
||||
|
||||
+14
-3
@@ -299,15 +299,24 @@ static int yyGrowStack(yyParser *p){
|
||||
int newSize;
|
||||
int idx;
|
||||
yyStackEntry *pNew;
|
||||
#ifdef YYSIZELIMIT
|
||||
int nLimit = YYSIZELIMIT(ParseCTX(p));
|
||||
#endif
|
||||
|
||||
newSize = oldSize*2 + 100;
|
||||
#ifdef YYSIZELIMIT
|
||||
if( newSize>nLimit ){
|
||||
newSize = nLimit;
|
||||
if( newSize<=oldSize ) return 1;
|
||||
}
|
||||
#endif
|
||||
idx = (int)(p->yytos - p->yystack);
|
||||
if( p->yystack==p->yystk0 ){
|
||||
pNew = YYREALLOC(0,newSize,sizeof(pNew[0]), p->ParseCTX_FIELD);
|
||||
pNew = YYREALLOC(0, newSize*sizeof(pNew[0]), ParseCTX(p));
|
||||
if( pNew==0 ) return 1;
|
||||
memcpy(pNew, p->yystack, oldSize*sizeof(pNew[0]));
|
||||
}else{
|
||||
pNew = YYREALLOC(p->yystack,newSize,sizeof(pNew[0]),p->ParseCTX_FIELD);
|
||||
pNew = YYREALLOC(p->yystack, newSize*sizeof(pNew[0]), ParseCTX(p));
|
||||
if( pNew==0 ) return 1;
|
||||
}
|
||||
p->yystack = pNew;
|
||||
@@ -459,7 +468,9 @@ void ParseFinalize(void *p){
|
||||
}
|
||||
|
||||
#if YYGROWABLESTACK
|
||||
if( pParser->yystack!=pParser->yystk0 ) YYFREE(pParser->yystack);
|
||||
if( pParser->yystack!=pParser->yystk0 ){
|
||||
YYFREE(pParser->yystack, ParseCTX(pParser));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user