From fef22330907493db7afbe815359fcccf7bcd00bb Mon Sep 17 00:00:00 2001 From: drh <> Date: Tue, 18 Nov 2025 14:48:33 +0000 Subject: [PATCH] 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 --- doc/lemon.html | 26 +++++++++----------------- manifest | 35 ++++++++++++++++------------------- manifest.uuid | 2 +- src/main.c | 4 +++- src/parse.y | 21 +++++++-------------- src/shell.c.in | 1 + src/sqlite.h.in | 5 +++++ src/sqliteInt.h | 2 +- src/sqliteLimit.h | 26 ++++++++++++++++++++++---- src/test1.c | 3 ++- test/misc5.test | 2 +- tool/lemon.c | 13 +++++++------ tool/lempar.c | 12 ++++++++---- 13 files changed, 83 insertions(+), 69 deletions(-) diff --git a/doc/lemon.html b/doc/lemon.html index 63efa950d8..0f5de0913b 100644 --- a/doc/lemon.html +++ b/doc/lemon.html @@ -696,7 +696,7 @@ other than that, the order of directives in Lemon is arbitrary.

  • %right
  • %realloc
  • %stack_overflow -
  • %stack_resizer +
  • %stack_size_limit
  • %stack_size
  • %start_symbol
  • %syntax_error @@ -1205,7 +1205,7 @@ The wildcard token is only matched if there are no alternatives.

    4.4.26 The %realloc, %free, and -%stack_resizer directives

    +%stack_size_limit directives

    The %realloc and %free directives defines function that allocate and free heap memory. The signatures of these functions @@ -1219,21 +1219,13 @@ parse stack space is exceeded. The initial parser stack size is specified by either %stack_size or the -DYYSTACKDEPTH compile-time flag. -

    The %stack_resizer directive defines a function that computes -the new size of the stack whenever it needs resizing. The function takes -two arguments: The old stack size, and the %extra_context value. The -function returns an integer which is the new stack size. If %stack_resizer -is not defined, then the stack size roughly doubles with each new allocation. -The %stack_resizer function is entirely optional. The parser works fine -without it. The %stack_resizer function merely gives the application more -control over the stack size, and offers an opportunity to raise warnings or -errors if the parser stack grows too large. - -

    If the %stack_resizer function returns an integer that is less than or -equal to its first parameter, then %stack_overflow is invoked and parsing -stops. - -

    The %stack_resizer function only works if %extra_context is also defined. +

    The %stack_size_limit directive defines a function that returns +the maximum allowed parser stack size. If this diretive does not exist, +no size limit is enforced. The 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.

    5.0 Error Processing

    diff --git a/manifest b/manifest index 26ff83bd7c..423055ba31 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Yet\sanother\sattempt\sat\scontrolling\sthe\sparser\sstack\ssize. -D 2025-11-18T13:03:08.837 +C Add\sthe\sSQLITE_LIMIT_PARSER_DEPTH\svalue\sfor\ssqlite3_limit().\s\sThis\sisn't\nsomething\sthat\smany\sapplications\swill\sneed,\sbut\sit\sis\suseful\sfor\stesting. +D 2025-11-18T14:48:33.193 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 60b3836301ac8555622523569fc5cd3bae5b7a8cd1abab545b6ec14800c90aec +F doc/lemon.html b4a2ce0ad754bf8ea46fe146bfe6134388748a0a1bcc8292847a52a75307ad4d 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 f54dff6d07f337f9cea8cb3e28144e47877fd2f211fc3a5c5e238e456d51cc8a +F src/parse.y 6706ff4cfe15194279c8da5acf2b0d1e5845ca945c976398bb4cbe0e188e0744 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 acb9b4e4d6a9826d40163b1da71e049859c7230217c39a6a63dc81ed8d28c906 -F tool/lempar.c ff3c9b32cf36152616dd2bb78ea0fdd3ec6c0f2e76ec55f0d2b50dcb35122b46 +F tool/lemon.c 4150f2020d453cfa46b6fa45542e59b923ad7eab063fb4ca20777995622cab0b +F tool/lempar.c 25aea31b33bbd15f0f7324c796e160c602f2a1d4e3f6f87d6d4fb25d77eaf54a 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 5c0214df2c0a7470ac2edca0c483a3edd3c39ef0739688ab9a06e23882200360 -R 77442b17c4e08c97334e79ed87f9944e -T *branch * parser-stack-size -T *sym-parser-stack-size * -T -sym-trunk * +P cb19986dc6bc483df21e082e54a14cb6d7540b1734259e6d326d676908ac0172 +R 7eda36c539b846b8b7294d534ccca677 U drh -Z df6b29f678f7d3bd6a12aec2b921e4cb +Z 033a2ffcce1aafa9ea403459cb7996b3 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 6e103a40ec..e6d9ac66f4 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -cb19986dc6bc483df21e082e54a14cb6d7540b1734259e6d326d676908ac0172 +8f0b07f36159225c476f756f8f9b35c75783bc8bed43b578f4d1055fa800ecc9 diff --git a/src/main.c b/src/main.c index 75439158c2..4e2bee499f 100644 --- a/src/main.c +++ b/src/main.c @@ -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 ){ diff --git a/src/parse.y b/src/parse.y index 1dd5d700be..071fce4198 100644 --- a/src/parse.y +++ b/src/parse.y @@ -22,9 +22,9 @@ } // Function used to enlarge the parser stack, if needed -%stack_resizer parserStackResize -%realloc parserStackRealloc -%free sqlite3_free +%stack_size_limit parserStackSizeLimit +%realloc parserStackRealloc +%free sqlite3_free // All token codes are small integers with #defines that begin with "TK_" %token_prefix TK_ @@ -50,7 +50,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 @@ -588,16 +588,9 @@ cmd ::= select(X). { return sqlite3FaultSim(700) ? 0 : sqlite3_realloc(pOld, newSize); } - /* Determine how big to make the stack */ - static int parserStackResize(int oldSize, Parse *pParse){ - int newSize; - int limit; - limit = pParse->db->aLimit[SQLITE_LIMIT_EXPR_DEPTH]; - if( limit ) limit = limit*4 +100; - newSize = oldSize*2 + 100; - if( newSize>limit ) newSize = limit; - if( newSize<=oldSize ) sqlite3ErrorMsg(pParse, "Recursion limit"); - return newSize; + /* Return an integer that is the maximum allowed stack size */ + static int parserStackSizeLimit(Parse *pParse){ + return pParse->db->aLimit[SQLITE_LIMIT_PARSER_DEPTH]; } } diff --git a/src/shell.c.in b/src/shell.c.in index 85ec8f3c03..5247e2dca8 100644 --- a/src/shell.c.in +++ b/src/shell.c.in @@ -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 }, diff --git a/src/sqlite.h.in b/src/sqlite.h.in index 7e7113696f..b10cbdd4e5 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -4339,6 +4339,10 @@ int sqlite3_limit(sqlite3*, int id, int newVal); ** [[SQLITE_LIMIT_EXPR_DEPTH]] ^(
    SQLITE_LIMIT_EXPR_DEPTH
    **
    The maximum depth of the parse tree on any expression.
    )^ ** +** [[SQLITE_LIMIT_PARSER_DEPTH]] ^(
    SQLITE_LIMIT_PARSER_DEPTH
    +**
    The maximum depth of the LALR(1) parser stack used to analyze +** input SQL statements.
    )^ +** ** [[SQLITE_LIMIT_COMPOUND_SELECT]] ^(
    SQLITE_LIMIT_COMPOUND_SELECT
    **
    The maximum number of terms in a compound SELECT statement.
    )^ ** @@ -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 diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 523bcfb3bd..d0d6ffacfb 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -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 diff --git a/src/sqliteLimit.h b/src/sqliteLimit.h index 6b6bb7167a..d2689a2720 100644 --- a/src/sqliteLimit.h +++ b/src/sqliteLimit.h @@ -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 diff --git a/src/test1.c b/src/test1.c index f8e83dc42d..90dfe8e984 100644 --- a/src/test1.c +++ b/src/test1.c @@ -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; diff --git a/test/misc5.test b/test/misc5.test index 43ee2781a1..80b8d3c67b 100644 --- a/test/misc5.test +++ b/test/misc5.test @@ -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 diff --git a/tool/lemon.c b/tool/lemon.c index b88da9d287..0efbf31787 100644 --- a/tool/lemon.c +++ b/tool/lemon.c @@ -494,7 +494,7 @@ 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 *resizeFunc; /* Function to compute new stack size */ + char *stackSizeLimit; /* Function to return the stack size limit */ char *reallocFunc; /* Function to use to allocate stack space */ char *freeFunc; /* Function to use to free stack space */ int nconflict; /* Number of parsing conflicts */ @@ -2639,8 +2639,8 @@ 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_resizer")==0 ){ - psp->declargslot = &(psp->gp->resizeFunc); + }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); @@ -4640,13 +4640,13 @@ void ReportTable( }else{ fprintf(out,"#define YYDYNSTACK 0\n"); lineno++; } - fprintf(out, "#undef YYRESIZE\n"); lineno++; + 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->resizeFunc) ){ - fprintf(out,"#define YYRESIZE %s\n", lemp->resizeFunc); lineno++; + 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++; @@ -4657,6 +4657,7 @@ void ReportTable( 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++; diff --git a/tool/lempar.c b/tool/lempar.c index 1bffbf6067..c99f2a8f1c 100644 --- a/tool/lempar.c +++ b/tool/lempar.c @@ -299,12 +299,16 @@ static int yyGrowStack(yyParser *p){ int newSize; int idx; yyStackEntry *pNew; +#ifdef YYSIZELIMIT + int nLimit = YYSIZELIMIT(ParseCTX(p)); +#endif -#ifdef YYRESIZE - newSize = YYRESIZE(oldSize, ParseCTX(p)); - if( newSize<=oldSize ) return 1; -#else 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 ){ -- 2.47.3