]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Pervent the parser stack from growing to be larger than 100 plus four times parser-recursion-limit
authordrh <>
Tue, 18 Nov 2025 02:24:46 +0000 (02:24 +0000)
committerdrh <>
Tue, 18 Nov 2025 02:24:46 +0000 (02:24 +0000)
the SQLITE_LIMIT_EXPR_DEPTH setting.

FossilOrigin-Name: 5728129e5432500550096e2a1350897881f0379b49b60faf49481c505b1eb323

doc/lemon.html
manifest
manifest.tags
manifest.uuid
src/parse.y
tool/lemon.c
tool/lempar.c

index 965f305c04169d0209cdab229df162f6fc651c0b..f4f7468fe93c7e644e558923bf2c93aee87800ac 100644 (file)
@@ -695,6 +695,7 @@ 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='#stack_size'>%stack_size</a></tt>
 <li><tt><a href='#start_symbol'>%start_symbol</a></tt>
@@ -1203,15 +1204,29 @@ 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> 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
index ad44d17d2838549c4c2dd2ae2d346be40e5e9e55..e93403433797fa4664d6bd63a96f7e02ce7823fd 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-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
@@ -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 89ea833a6f71773ab1a9063fbb7fb9b32147bc0b1057b53ecab94a3b30c0aef5
+F doc/lemon.html 0e4b854b5ca0cf3600fec4da454197f651e8a0d411a90653703e75474486ad31
 F doc/pager-invariants.txt 83aa3a4724b2d7970cc3f3461f0295c46d4fc19a835a5781cbb35cb52feb0577
 F doc/tcl-extension-testing.md b88861804fc1eaf83249f8e206334189b61e150c360e1b80d0dcf91af82354f5
 F doc/testrunner.md 5ee928637e03f136a25fef852c5ed975932e31927bd9b05a574424ae18c31019
@@ -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 619c3e92a54686c5e47923688c4b9bf7ec534a4690db5677acc28b299c403250
+F src/parse.y 04c6c7278939e3c6307ed3c6ed7482d2928e692560dbe8e57f524851a934e25c
 F src/pcache.c 588cc3c5ccaaadde689ed35ce5c5c891a1f7b1f4d1f56f6cf0143b74d8ee6484
 F src/pcache.h 1497ce1b823cf00094bb0cf3bac37b345937e6f910890c626b16512316d3abf5
 F src/pcache1.c 131ca0daf4e66b4608d2945ae76d6ed90de3f60539afbd5ef9ec65667a5f2fcd
@@ -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 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
@@ -2166,8 +2166,11 @@ F tool/version-info.c 33d0390ef484b3b1cb685d59362be891ea162123cea181cb8e6d2cf6dd
 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.
index bec971799ff1b8ee641c166c7aeb22d12c785393..e9611298bcafb4d1c5d4a519c7966cb8f05b0b90 100644 (file)
@@ -1,2 +1,2 @@
-branch trunk
-tag trunk
+branch parser-recursion-limit
+tag parser-recursion-limit
index a38149056e0b24ea63da685254d467beef17ed34..714d764112fa182880c7faa7f3236fbe782d4794 100644 (file)
@@ -1 +1 @@
-ea48567ac54e4949a8b68977a58a5de7946e074ae8737133071d02f40ac97f34
+5728129e5432500550096e2a1350897881f0379b49b60faf49481c505b1eb323
index 617eb7303b6ee2f2293544a5cace5e4d95f908be..52a292104d5bbac7404d4b345fa4334d0a93a433 100644 (file)
@@ -22,8 +22,8 @@
 }
 
 // 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_
@@ -49,7 +49,7 @@
   }
 }
 %stack_overflow {
-  sqlite3OomFault(pParse->db);
+  if( pParse->nErr==0 ) sqlite3OomFault(pParse->db);
 }
 
 // The name of the generated procedure that implements the parser
@@ -583,8 +583,17 @@ cmd ::= select(X).  {
   ** 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);
   }
 }
 
index 324dda0c5f06f881319934d96e296d4d2e269003..bf86c6382bb9fb1ccc3547b38269aa2fca4050a1 100644 (file)
@@ -495,6 +495,7 @@ struct lemon {
   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 */
@@ -2641,6 +2642,9 @@ static void parseonetoken(struct pstate *psp)
         }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;
@@ -4414,7 +4418,7 @@ void ReportTable(
   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;
@@ -4439,18 +4443,10 @@ void ReportTable(
 
   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,
@@ -4515,6 +4511,12 @@ void ReportTable(
       }
     }
     fprintf(sql, "COMMIT;\n");
+    fclose(sql);
+  }
+  out = file_open(lemp,".c","wb");
+  if( out==0 ){
+    fclose(in);
+    return;
   }
   lineno = 1;
 
@@ -4612,17 +4614,21 @@ void ReportTable(
     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++;
@@ -4634,6 +4640,7 @@ void ReportTable(
     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",
@@ -4642,6 +4649,7 @@ void ReportTable(
     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++;
   }
@@ -5103,7 +5111,6 @@ void ReportTable(
   acttab_free(pActtab);
   fclose(in);
   fclose(out);
-  if( sql ) fclose(sql);
   return;
 }
 
index 74314efeaa4c05c5dce82a21746265110f9e4ed0..7140767f7639d1547aec3225958780b506b7a8a9 100644 (file)
@@ -303,11 +303,11 @@ static int yyGrowStack(yyParser *p){
   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;