Compare commits

..

5 Commits

Author SHA1 Message Date
drh 9e91a1fe89 Modify the "%realloc" and "%free" commands in Lemon so that the functions
they specify take an extra parameter at the end, the %extra_context pointer.
This allows the implementation to distinguish between OOM errors and
failures to increase the stack size because of the stack size limit.

FossilOrigin-Name: 9862c945d9a8531f9bef123aee9ed1fd3f64542250a57beb3a150227bc3c1a12
2025-11-18 15:40:02 +00:00
drh 9432655038 Lower the default stack size for the parse to 50.
FossilOrigin-Name: 41fe19ab054acda912bc32dd6f9c6412416ab1af6cf55515e96c89fb55b46424
2025-11-18 15:20:22 +00:00
drh fef2233090 Add the SQLITE_LIMIT_PARSER_DEPTH value for sqlite3_limit(). This isn't
something that many applications will need, but it is useful for testing.

FossilOrigin-Name: 8f0b07f36159225c476f756f8f9b35c75783bc8bed43b578f4d1055fa800ecc9
2025-11-18 14:48:33 +00:00
drh d26ac414c8 Yet another attempt at controlling the parser stack size.
FossilOrigin-Name: cb19986dc6bc483df21e082e54a14cb6d7540b1734259e6d326d676908ac0172
2025-11-18 13:03:08 +00:00
drh ef4abc0a63 Fix incorrect "#line" generation in Lemon.
FossilOrigin-Name: 5c0214df2c0a7470ac2edca0c483a3edd3c39ef0739688ab9a06e23882200360
2025-11-18 10:38:41 +00:00
14 changed files with 149 additions and 94 deletions
+23 -24
View File
@@ -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>
+16 -19
View File
@@ -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
View File
@@ -1,2 +1,2 @@
branch parser-recursion-limit
tag parser-recursion-limit
branch parser-stack-size
tag parser-stack-size
+1 -1
View File
@@ -1 +1 @@
5728129e5432500550096e2a1350897881f0379b49b60faf49481c505b1eb323
9862c945d9a8531f9bef123aee9ed1fd3f64542250a57beb3a150227bc3c1a12
+3 -1
View File
@@ -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
View File
@@ -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];
}
}
+1
View File
@@ -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 },
+5
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
}