summaryrefslogtreecommitdiffstats
path: root/generic
diff options
context:
space:
mode:
authordkf <donal.k.fellows@manchester.ac.uk>2010-04-08 13:26:23 (GMT)
committerdkf <donal.k.fellows@manchester.ac.uk>2010-04-08 13:26:23 (GMT)
commitf10d81b895d8ca9d30428aac9884685fb284986a (patch)
tree7f94efe33eb67e54166bcce1f6f00fe697506798 /generic
parent9a41057f12f98c43dddf469be6d0822f1c90384c (diff)
downloadtcl-f10d81b895d8ca9d30428aac9884685fb284986a.zip
tcl-f10d81b895d8ca9d30428aac9884685fb284986a.tar.gz
tcl-f10d81b895d8ca9d30428aac9884685fb284986a.tar.bz2
* generic/tclCompCmdsSZ.c (TclSubstCompile): If the first token does
not result in a *guaranteed* push of a Tcl_Obj on the stack, we must push an empty object. Otherwise it is possible to get to a 'concat1' or 'done' without enough values on the stack, resulting in a crash. Thanks to Joe Mistachkin for identifying a script that could trigger this case.
Diffstat (limited to 'generic')
-rw-r--r--generic/tclCompCmdsSZ.c25
1 files changed, 22 insertions, 3 deletions
diff --git a/generic/tclCompCmdsSZ.c b/generic/tclCompCmdsSZ.c
index b19dfc8..3d45833 100644
--- a/generic/tclCompCmdsSZ.c
+++ b/generic/tclCompCmdsSZ.c
@@ -14,7 +14,7 @@
* See the file "license.terms" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tclCompCmdsSZ.c,v 1.7 2010/03/27 22:40:14 nijtmans Exp $
+ * RCS: @(#) $Id: tclCompCmdsSZ.c,v 1.8 2010/04/08 13:26:24 dkf Exp $
*/
#include "tclInt.h"
@@ -659,7 +659,21 @@ TclSubstCompile(
TclSubstParse(interp, bytes, numBytes, flags, &parse, &state);
- for (tokenPtr = parse.tokenPtr, endTokenPtr = tokenPtr + parse.numTokens;
+ /*
+ * Tricky point! If the first token does not result in a *guaranteed* push
+ * of a Tcl_Obj on the stack, we must push an empty object. Otherwise it
+ * is possible to get to an INST_CONCAT1 or INST_DONE without enough
+ * values on the stack, resulting in a crash. Thanks to Joe Mistachkin for
+ * identifying a script that could trigger this case.
+ */
+
+ tokenPtr = parse.tokenPtr;
+ if (tokenPtr->type != TCL_TOKEN_TEXT && tokenPtr->type != TCL_TOKEN_BS) {
+ PushLiteral(envPtr, "", 0);
+ count++;
+ }
+
+ for (endTokenPtr = tokenPtr + parse.numTokens;
tokenPtr < endTokenPtr; tokenPtr = TokenAfter(tokenPtr)) {
int length, literal, catchRange, breakJump;
char buf[TCL_UTF_MAX];
@@ -790,7 +804,11 @@ TclSubstCompile(
Tcl_Panic("TclCompileSubstCmd: bad other jump distance %d",
CurrentOffset(envPtr) - otherFixup.codeOffset);
}
- /* Pull the result to top of stack, discard options dict */
+
+ /*
+ * Pull the result to top of stack, discard options dict.
+ */
+
TclEmitInstInt4(INST_REVERSE, 2, envPtr);
TclEmitOpcode(INST_POP, envPtr);
@@ -802,6 +820,7 @@ TclSubstCompile(
* through them all. So, we now have a stack requirements estimate
* that is too low. Here we manually fix that up.
*/
+
TclAdjustStackDepth(5, envPtr);
/* OK destination */