diff options
author | dkf <donal.k.fellows@manchester.ac.uk> | 2010-04-08 13:26:23 (GMT) |
---|---|---|
committer | dkf <donal.k.fellows@manchester.ac.uk> | 2010-04-08 13:26:23 (GMT) |
commit | f10d81b895d8ca9d30428aac9884685fb284986a (patch) | |
tree | 7f94efe33eb67e54166bcce1f6f00fe697506798 /generic/tclCompCmdsSZ.c | |
parent | 9a41057f12f98c43dddf469be6d0822f1c90384c (diff) | |
download | tcl-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/tclCompCmdsSZ.c')
-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 */ |