aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--jim.c71
-rw-r--r--jim.h7
-rw-r--r--regtest.tcl18
3 files changed, 59 insertions, 37 deletions
diff --git a/jim.c b/jim.c
index fda721a..892f110 100644
--- a/jim.c
+++ b/jim.c
@@ -5051,7 +5051,8 @@ Jim_Interp *Jim_CreateInterp(void)
memset(i, 0, sizeof(*i));
- i->maxNestingDepth = JIM_MAX_NESTING_DEPTH;
+ i->maxCallFrameDepth = JIM_MAX_CALLFRAME_DEPTH;
+ i->maxEvalDepth = JIM_MAX_EVAL_DEPTH;
i->lastCollectTime = time(NULL);
/* Note that we can create objects only after the
@@ -9676,6 +9677,35 @@ static int JimUnknown(Jim_Interp *interp, int argc, Jim_Obj *const *argv, Jim_Ob
return retCode;
}
+static int JimInvokeCommand(Jim_Interp *interp, Jim_Cmd *cmdPtr, Jim_Obj *fileNameObj, int linenr, int objc, Jim_Obj *const *objv)
+{
+ int retcode;
+
+ if (cmdPtr == NULL) {
+ return JimUnknown(interp, objc, objv, fileNameObj, linenr);
+ }
+ if (interp->evalDepth == interp->maxEvalDepth) {
+ Jim_SetResultString(interp, "Infinite eval recursion", -1);
+ return JIM_ERR;
+ }
+ interp->evalDepth++;
+
+ /* Call it -- Make sure result is an empty object. */
+ JimIncrCmdRefCount(cmdPtr);
+ Jim_SetEmptyResult(interp);
+ if (cmdPtr->isproc) {
+ retcode = JimCallProcedure(interp, cmdPtr, fileNameObj, linenr, objc, objv);
+ }
+ else {
+ interp->cmdPrivData = cmdPtr->u.native.privData;
+ retcode = cmdPtr->u.native.cmdProc(interp, objc, objv);
+ }
+ JimDecrCmdRefCount(interp, cmdPtr);
+ interp->evalDepth--;
+
+ return retcode;
+}
+
/* Eval the object vector 'objv' composed of 'objc' elements.
* Every element is used as single argument.
* Jim_EvalObj() will call this function every time its object
@@ -9694,24 +9724,11 @@ static int JimEvalObjVector(Jim_Interp *interp, int objc, Jim_Obj *const *objv,
/* Incr refcount of arguments. */
for (i = 0; i < objc; i++)
Jim_IncrRefCount(objv[i]);
+
/* Command lookup */
cmdPtr = Jim_GetCommand(interp, objv[0], JIM_ERRMSG);
- if (cmdPtr == NULL) {
- retcode = JimUnknown(interp, objc, objv, fileNameObj, linenr);
- }
- else {
- /* Call it -- Make sure result is an empty object. */
- JimIncrCmdRefCount(cmdPtr);
- Jim_SetEmptyResult(interp);
- if (cmdPtr->isproc) {
- retcode = JimCallProcedure(interp, cmdPtr, fileNameObj, linenr, objc, objv);
- }
- else {
- interp->cmdPrivData = cmdPtr->u.native.privData;
- retcode = cmdPtr->u.native.cmdProc(interp, objc, objv);
- }
- JimDecrCmdRefCount(interp, cmdPtr);
- }
+ retcode = JimInvokeCommand(interp, cmdPtr, fileNameObj, linenr, objc, objv);
+
/* Decr refcount of arguments and return the retcode */
for (i = 0; i < objc; i++)
Jim_DecrRefCount(interp, objv[i]);
@@ -10131,23 +10148,7 @@ int Jim_EvalObj(Jim_Interp *interp, Jim_Obj *scriptObjPtr)
if (retcode == JIM_OK && argc) {
/* Lookup the command to call */
cmd = Jim_GetCommand(interp, argv[0], JIM_ERRMSG);
- if (cmd != NULL) {
- /* Call it -- Make sure result is an empty object. */
- JimIncrCmdRefCount(cmd);
- Jim_SetEmptyResult(interp);
- if (cmd->isproc) {
- retcode =
- JimCallProcedure(interp, cmd, script->fileNameObj, linenr, argc, argv);
- } else {
- interp->cmdPrivData = cmd->u.native.privData;
- retcode = cmd->u.native.cmdProc(interp, argc, argv);
- }
- JimDecrCmdRefCount(interp, cmd);
- }
- else {
- /* Call [unknown] */
- retcode = JimUnknown(interp, argc, argv, script->fileNameObj, linenr);
- }
+ retcode = JimInvokeCommand(interp, cmd, script->fileNameObj, linenr, argc, argv);
if (interp->signal_level && interp->sigmask) {
/* Check for a signal after each command */
retcode = JIM_SIGNAL;
@@ -10274,7 +10275,7 @@ static int JimCallProcedure(Jim_Interp *interp, Jim_Cmd *cmd, Jim_Obj *fileNameO
}
/* Check if there are too nested calls */
- if (interp->framePtr->level == interp->maxNestingDepth) {
+ if (interp->framePtr->level == interp->maxCallFrameDepth) {
Jim_SetResultString(interp, "Too many nested calls. Infinite recursion?", -1);
return JIM_ERR;
}
diff --git a/jim.h b/jim.h
index 4308a69..72c1637 100644
--- a/jim.h
+++ b/jim.h
@@ -140,7 +140,8 @@ extern "C" {
/* The following are internal codes and should never been seen/used */
#define JIM_EVAL 7
-#define JIM_MAX_NESTING_DEPTH 1000 /* default max nesting depth */
+#define JIM_MAX_CALLFRAME_DEPTH 1000 /* default max nesting depth for procs */
+#define JIM_MAX_EVAL_DEPTH 2000 /* default max nesting depth for eval */
/* Some function get an integer argument with flags to change
* the behaviour. */
@@ -517,7 +518,9 @@ typedef struct Jim_Interp {
int errorLine; /* Error line where an error occurred. */
Jim_Obj *errorFileNameObj; /* Error file where an error occurred. */
int addStackTrace; /* > 0 If a level should be added to the stack trace */
- int maxNestingDepth; /* Used for infinite loop detection. */
+ int maxCallFrameDepth; /* Used for infinite loop detection. */
+ int maxEvalDepth; /* Used for infinite loop detection. */
+ int evalDepth; /* Current eval depth */
int returnCode; /* Completion code to return on JIM_RETURN. */
int returnLevel; /* Current level of 'return -level' */
int exitCode; /* Code to return to the OS on JIM_EXIT. */
diff --git a/regtest.tcl b/regtest.tcl
index 0f2e5b6..0be3830 100644
--- a/regtest.tcl
+++ b/regtest.tcl
@@ -178,6 +178,24 @@ catch {
incr globx
puts "TEST 25 PASSED"
+# REGTEST 26
+# 2 Dec 2011 - infinite eval recursion
+catch {
+ set x 0
+ set y {incr x; eval $y}
+ eval $y
+} msg
+puts "TEST 26 PASSED"
+
+# REGTEST 27
+# 2 Dec 2011 - infinite alias recursion
+catch {
+ proc p {} {}
+ alias p p
+ p
+} msg
+puts "TEST 27 PASSED"
+
# TAKE THE FOLLOWING puts AS LAST LINE
puts "--- ALL TESTS PASSED ---"