summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog7
-rw-r--r--generic/tclBasic.c28
-rw-r--r--tests/subst.test14
3 files changed, 44 insertions, 5 deletions
diff --git a/ChangeLog b/ChangeLog
index 063edc4..f79b448 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2002-02-25 Miguel Sofer <msofer@users.sourceforge.net>
+
+ * generic/tclBasic.c (Tcl_EvalEx): avoiding a buffer overrun
+ reported by Joe English, and restoring tcl7.6 behaviour for
+ [subst]: badly terminated nested scripts will raise an error
+ andnot be evaluated. [Bug #495207]
+
2002-02-25 Don Porter <dgp@users.sourceforge.net>
* unix/tclUnixPort.h: corrected strtoll prototype mismatch on Tru64.
diff --git a/generic/tclBasic.c b/generic/tclBasic.c
index 814b4a5..5e8a626 100644
--- a/generic/tclBasic.c
+++ b/generic/tclBasic.c
@@ -13,7 +13,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tclBasic.c,v 1.47 2002/02/15 14:28:48 dkf Exp $
+ * RCS: @(#) $Id: tclBasic.c,v 1.48 2002/02/25 23:17:21 msofer Exp $
*/
#include "tclInt.h"
@@ -3478,8 +3478,15 @@ Tcl_EvalEx(interp, script, numBytes, flags)
Tcl_Obj *staticObjArray[NUM_STATIC_OBJS], **objv;
Tcl_Token *tokenPtr;
int i, code, commandLength, bytesLeft, nested;
- CallFrame *savedVarFramePtr; /* Saves old copy of iPtr->varFramePtr
- * in case TCL_EVAL_GLOBAL was set. */
+ CallFrame *savedVarFramePtr; /* Saves old copy of iPtr->varFramePtr
+ * in case TCL_EVAL_GLOBAL was set. */
+
+ /* For nested scripts, this variable will be set to point to the first
+ * char after the end of the script - needed only to compare pointers,
+ * nothing will be read nor written there.
+ */
+
+ char *onePast = NULL;
/*
* The variables below keep track of how much state has been
@@ -3509,6 +3516,7 @@ Tcl_EvalEx(interp, script, numBytes, flags)
bytesLeft = numBytes;
if (iPtr->evalFlags & TCL_BRACKET_TERM) {
nested = 1;
+ onePast = script + numBytes;
} else {
nested = 0;
}
@@ -3520,6 +3528,19 @@ Tcl_EvalEx(interp, script, numBytes, flags)
goto error;
}
gotParse = 1;
+
+ /*
+ * A nested script can only terminate in ']'. If the script is not
+ * nested, onePast is NULL and the second test is not performed.
+ */
+
+ next = parse.commandStart + parse.commandSize;
+ if ((next == onePast) && (onePast[-1] != ']')) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj("missing close-bracket", -1));
+ code = TCL_ERROR;
+ goto error;
+ }
+
if (parse.numWords > 0) {
/*
* Generate an array of objects for the words of the command.
@@ -3572,7 +3593,6 @@ Tcl_EvalEx(interp, script, numBytes, flags)
* Advance to the next command in the script.
*/
- next = parse.commandStart + parse.commandSize;
bytesLeft -= next - p;
p = next;
Tcl_FreeParse(&parse);
diff --git a/tests/subst.test b/tests/subst.test
index 662db99..f9e3e78 100644
--- a/tests/subst.test
+++ b/tests/subst.test
@@ -11,7 +11,7 @@
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
-# RCS: @(#) $Id: subst.test,v 1.9 2001/07/12 13:15:09 dkf Exp $
+# RCS: @(#) $Id: subst.test,v 1.10 2002/02/25 23:17:21 msofer Exp $
if {[lsearch [namespace children] ::tcltest] == -1} {
package require tcltest
@@ -82,6 +82,18 @@ test subst-5.3 {command substitutions} {
test subst-5.4 {command substitutions} {
list [catch {subst {$long [set long] [bogus_command]}} msg] $msg
} {1 {invalid command name "bogus_command"}}
+test subst-5.5 {command substitutions} {
+ set a 0
+ list [catch {subst {[set a 1}} msg] $a $msg
+} {1 0 {missing close-bracket}}
+test subst-5.6 {command substitutions} {
+ set a 0
+ list [catch {subst {0[set a 1}} msg] $a $msg
+} {1 0 {missing close-bracket}}
+test subst-5.7 {command substitutions} {
+ set a 0
+ list [catch {subst {0[set a 1; set a 2}} msg] $a $msg
+} {1 1 {missing close-bracket}}
test subst-6.1 {clear the result after command substitution} {
catch {unset a}