<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='#stack_size'>%stack_size</a></tt>
<li><tt><a href='#start_symbol'>%start_symbol</a></tt>
The wildcard token is only matched if there are no alternatives.</p>
<a id='reallc'></a>
-<h4>4.4.26 The <tt>%realloc</tt> and <tt>%free</tt> directives</h4>
-
-<p>The <tt>%realloc</tt> and <tt>%free</tt> directives defines function
-that allocate and free heap memory. The signatures of these functions
-should be the same as the realloc() and free() functions from the standard
-C library.
-
-<p>If both of these functions are defined
-then these functions are used to allocate and free
+<h4>4.4.26 The <tt>%realloc</tt>, <tt>%reallocx</tt>,
+and <tt>%free</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>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
is specified by either <tt>%stack_size</tt> or the
-C Add\sapi.oo1=0\sflag\sto\sext/wasm/GNUmakefile\sto\sstrip\sout\sthe\ssqlite3.oo1\spieces\sfrom\sthe\sbuild.\sPart\sof\sthe\songoing\sresponse\sto\s[forum:4b7d45433731d2e0|forum\spost\s4b7d45433731d2e0].
-D 2025-11-17T23:55:41.172
+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
F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F doc/compile-for-windows.md f9e74d74da88f384edd5809f825035e071608f00f7f39c0e448df7b3982f979c
F doc/json-enhancements.md e356fc834781f1f1aa22ee300027a270b2c960122468499bf347bb123ce1ea4f
F doc/jsonb.md acd77fc3a709f51242655ad7803510c886aa8304202fa9cf2abc5f5c4e9d7ae5
-F doc/lemon.html 89ea833a6f71773ab1a9063fbb7fb9b32147bc0b1057b53ecab94a3b30c0aef5
+F doc/lemon.html 0e4b854b5ca0cf3600fec4da454197f651e8a0d411a90653703e75474486ad31
F doc/pager-invariants.txt 83aa3a4724b2d7970cc3f3461f0295c46d4fc19a835a5781cbb35cb52feb0577
F doc/tcl-extension-testing.md b88861804fc1eaf83249f8e206334189b61e150c360e1b80d0dcf91af82354f5
F doc/testrunner.md 5ee928637e03f136a25fef852c5ed975932e31927bd9b05a574424ae18c31019
F src/os_win.h 4c247cdb6d407c75186c94a1e84d5a22cbae4adcec93fcae8d2bc1f956fd1f19
F src/pager.c a81461de271ac4886ad75b7ca2cca8157a48635820c4646cd2714acdc2c17e5f
F src/pager.h 6137149346e6c8a3ddc1eeb40aee46381e9bc8b0fcc6dda8a1efde993c2275b8
-F src/parse.y 619c3e92a54686c5e47923688c4b9bf7ec534a4690db5677acc28b299c403250
+F src/parse.y 04c6c7278939e3c6307ed3c6ed7482d2928e692560dbe8e57f524851a934e25c
F src/pcache.c 588cc3c5ccaaadde689ed35ce5c5c891a1f7b1f4d1f56f6cf0143b74d8ee6484
F src/pcache.h 1497ce1b823cf00094bb0cf3bac37b345937e6f910890c626b16512316d3abf5
F src/pcache1.c 131ca0daf4e66b4608d2945ae76d6ed90de3f60539afbd5ef9ec65667a5f2fcd
F tool/genfkey.test b6afd7b825d797a1e1274f519ab5695373552ecad5cd373530c63533638a5a4f
F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce
F tool/index_usage.c f62a0c701b2c7ff2f3e21d206f093c123f222dbf07136a10ffd1ca15a5c706c5
-F tool/lemon.c 8f6c122e5727cb0e5f302b8efc91489b1947a8d98206d7a1b1cfc0ed685b6e7c
-F tool/lempar.c bdffd3b233a4e4e78056c9c01fadd2bb3fe902435abde3bce3d769fdf0d5cca2
+F tool/lemon.c fda0511d71764674919872a1457d2f86a7d48b13bfcf98741955c1b217a84570
+F tool/lempar.c a59c5474bdd148ca4c61f2977c7ce6b49e99c48a333b6d48fc7ceacf2292b43a
F tool/libvers.c caafc3b689638a1d88d44bc5f526c2278760d9b9
F tool/loadfts.c 63412f9790e5e8538fbde0b4f6db154aaaf80f7a10a01e3c94d14b773a8dd5a6
F tool/logest.c c34e5944318415de513d29a6098df247a9618c96d83c38d4abd88641fe46e669
F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee87c1b31a7
F tool/warnings.sh d924598cf2f55a4ecbc2aeb055c10bd5f48114793e7ba25f9585435da29e7e98
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
-P 6621737cc05cbf8ff5f576775a8a3c64f666b56d42939968ebb55d72a835646b
-R f725b34e8d754de05251b176eb359cd6
-U stephan
-Z c71a6e355b45027ea5bfc35ef83fb8b3
+P ea48567ac54e4949a8b68977a58a5de7946e074ae8737133071d02f40ac97f34
+R 94faba231c7b1fe01c357a8fbebddcb3
+T *branch * parser-recursion-limit
+T *sym-parser-recursion-limit *
+T -sym-trunk *
+U drh
+Z ef6a72fd333d3e7f2a3d9cd4902c91e6
# Remove this line to create a well-formed Fossil manifest.
-branch trunk
-tag trunk
+branch parser-recursion-limit
+tag parser-recursion-limit
-ea48567ac54e4949a8b68977a58a5de7946e074ae8737133071d02f40ac97f34
+5728129e5432500550096e2a1350897881f0379b49b60faf49481c505b1eb323
}
// Function used to enlarge the parser stack, if needed
-%realloc parserStackRealloc
-%free sqlite3_free
+%reallocx parserStackRealloc
+%free sqlite3_free
// All token codes are small integers with #defines that begin with "TK_"
%token_prefix TK_
}
}
%stack_overflow {
- sqlite3OomFault(pParse->db);
+ if( pParse->nErr==0 ) sqlite3OomFault(pParse->db);
}
// The name of the generated procedure that implements the parser
** sqlite3_realloc() that includes a call to sqlite3FaultSim() to facilitate
** testing.
*/
- static void *parserStackRealloc(void *pOld, sqlite3_uint64 newSize){
- return sqlite3FaultSim(700) ? 0 : sqlite3_realloc(pOld, newSize);
+ 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 */
+ ){
+ 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);
}
}
char *outname; /* Name of the current output file */
char *tokenprefix; /* A prefix added to token names in the .h file */
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 */
}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;
int mhflag, /* Output in makeheaders format if true */
int sqlFlag /* Generate the *.sql file too */
){
- FILE *out, *in, *sql;
+ FILE *out, *in;
int lineno;
struct state *stp;
struct action *ap;
in = tplt_open(lemp);
if( in==0 ) return;
- out = file_open(lemp,".c","wb");
- if( out==0 ){
- fclose(in);
- return;
- }
- if( sqlFlag==0 ){
- sql = 0;
- }else{
- sql = file_open(lemp, ".sql", "wb");
+ if( sqlFlag ){
+ FILE *sql = file_open(lemp, ".sql", "wb");
if( sql==0 ){
fclose(in);
- fclose(out);
return;
}
fprintf(sql,
}
}
fprintf(sql, "COMMIT;\n");
+ fclose(sql);
+ }
+ out = file_open(lemp,".c","wb");
+ if( out==0 ){
+ fclose(in);
+ return;
}
lineno = 1;
fprintf(out,"#define %sARG_FETCH\n",name); lineno++;
fprintf(out,"#define %sARG_STORE\n",name); lineno++;
}
- if( lemp->reallocFunc ){
- fprintf(out,"#define YYREALLOC %s\n", lemp->reallocFunc); 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++;
}else{
- fprintf(out,"#define YYREALLOC realloc\n"); lineno++;
+ fprintf(out,"#define YYREALLOC(A,B,C,D) realloc(A,B*C)\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->freeFunc ){
+ if( (lemp->reallocFunc || lemp->reallocFuncEx) && lemp->freeFunc ){
fprintf(out,"#define YYDYNSTACK 1\n"); lineno++;
}else{
fprintf(out,"#define YYDYNSTACK 0\n"); 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",
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++;
}
acttab_free(pActtab);
fclose(in);
fclose(out);
- if( sql ) fclose(sql);
return;
}
newSize = oldSize*2 + 100;
idx = (int)(p->yytos - p->yystack);
if( p->yystack==p->yystk0 ){
- pNew = YYREALLOC(0, newSize*sizeof(pNew[0]));
+ pNew = YYREALLOC(0,newSize,sizeof(pNew[0]), p->ParseCTX_FIELD);
if( pNew==0 ) return 1;
memcpy(pNew, p->yystack, oldSize*sizeof(pNew[0]));
}else{
- pNew = YYREALLOC(p->yystack, newSize*sizeof(pNew[0]));
+ pNew = YYREALLOC(p->yystack,newSize,sizeof(pNew[0]),p->ParseCTX_FIELD);
if( pNew==0 ) return 1;
}
p->yystack = pNew;