summaryrefslogtreecommitdiffstats
path: root/generic/tclCompile.c
diff options
context:
space:
mode:
Diffstat (limited to 'generic/tclCompile.c')
-rw-r--r--generic/tclCompile.c23
1 files changed, 23 insertions, 0 deletions
diff --git a/generic/tclCompile.c b/generic/tclCompile.c
index 87f1bfc..1a7d32f 100644
--- a/generic/tclCompile.c
+++ b/generic/tclCompile.c
@@ -2121,10 +2121,25 @@ TclCompileScript(
* has not yet generated any bytecode. */
const char *p = script; /* Where we are in our compile. */
int depth = TclGetStackDepth(envPtr);
+ Interp *iPtr = (Interp *) interp;
if (envPtr->iPtr == NULL) {
Tcl_Panic("TclCompileScript() called on uninitialized CompileEnv");
}
+ /*
+ * Check depth to avoid SO by too many nested calls of TclCompileScript
+ * (considering interp recursionlimit).
+ * Factor 5/4 (1.25) is used to avoid too mistaken limit recognition
+ * during "mixed" evaluation and compilation process (nested eval+compile)
+ * and is good enough for default recursionlimit (1000).
+ */
+ if (iPtr->numLevels / 5 > iPtr->maxNestingDepth / 4) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "too many nested compilations (infinite loop?)", -1));
+ Tcl_SetErrorCode(interp, "TCL", "LIMIT", "STACK", NULL);
+ TclCompileSyntaxError(interp, envPtr);
+ return;
+ }
/* Each iteration compiles one command from the script. */
@@ -2203,8 +2218,16 @@ TclCompileScript(
continue;
}
+ /*
+ * Avoid stack exhaustion by too many nested calls of TclCompileScript
+ * (considering interp recursionlimit).
+ */
+ iPtr->numLevels++;
+
lastCmdIdx = CompileCommandTokens(interp, parsePtr, envPtr);
+ iPtr->numLevels--;
+
/*
* TIP #280: Track lines in the just compiled command.
*/