diff options
Diffstat (limited to 'generic')
-rw-r--r-- | generic/tclCompCmdsSZ.c | 25 |
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 */ |