summaryrefslogtreecommitdiffstats
path: root/generic
diff options
context:
space:
mode:
authordkf <donal.k.fellows@manchester.ac.uk>2013-02-04 14:40:40 (GMT)
committerdkf <donal.k.fellows@manchester.ac.uk>2013-02-04 14:40:40 (GMT)
commit5537ab67eb915869ddd76bfbe1a7881c6faca15a (patch)
tree9f69275332c80280626c60becf9e973a7d69c4da /generic
parent586e53a4ac38b4a017a8be29a3832632ef62705a (diff)
parent5e82c1c3bc9f6e0222ba44ec737ef82ea07d6e5e (diff)
downloadtcl-5537ab67eb915869ddd76bfbe1a7881c6faca15a.zip
tcl-5537ab67eb915869ddd76bfbe1a7881c6faca15a.tar.gz
tcl-5537ab67eb915869ddd76bfbe1a7881c6faca15a.tar.bz2
[3603163]: Stop crash in weird case where [eval] is used to make [array set]
get confused about whether there is a local variable table or not. Thanks to Poor Yorick for identifying a reproducible crashing case.
Diffstat (limited to 'generic')
-rw-r--r--generic/tclCompCmds.c41
1 files changed, 23 insertions, 18 deletions
diff --git a/generic/tclCompCmds.c b/generic/tclCompCmds.c
index 389c1ee..4751455 100644
--- a/generic/tclCompCmds.c
+++ b/generic/tclCompCmds.c
@@ -284,7 +284,7 @@ TclCompileArraySetCmd(
CompileEnv *envPtr) /* Holds resulting instructions. */
{
DefineLineInformation; /* TIP #280 */
- Tcl_Token *tokenPtr;
+ Tcl_Token *varTokenPtr, *dataTokenPtr;
int simpleVarName, isScalar, localIndex;
int dataVar, iterVar, keyVar, valVar, infoIndex;
int back, fwd, offsetBack, offsetFwd, savedStackDepth;
@@ -294,10 +294,10 @@ TclCompileArraySetCmd(
return TCL_ERROR;
}
- tokenPtr = TokenAfter(parsePtr->tokenPtr);
- PushVarNameWord(interp, tokenPtr, envPtr, TCL_NO_ELEMENT,
+ varTokenPtr = TokenAfter(parsePtr->tokenPtr);
+ PushVarNameWord(interp, varTokenPtr, envPtr, TCL_NO_ELEMENT,
&localIndex, &simpleVarName, &isScalar, 1);
- tokenPtr = TokenAfter(tokenPtr);
+ dataTokenPtr = TokenAfter(varTokenPtr);
if (!isScalar) {
return TCL_ERROR;
}
@@ -307,7 +307,8 @@ TclCompileArraySetCmd(
* operation.
*/
- if (tokenPtr->type == TCL_TOKEN_SIMPLE_WORD && tokenPtr[1].size == 0) {
+ if (dataTokenPtr->type == TCL_TOKEN_SIMPLE_WORD
+ && dataTokenPtr[1].size == 0) {
if (localIndex >= 0) {
TclEmitInstInt4(INST_ARRAY_EXISTS_IMM, localIndex, envPtr);
TclEmitInstInt1(INST_JUMP_TRUE1, 7, envPtr);
@@ -326,7 +327,16 @@ TclCompileArraySetCmd(
return TCL_OK;
}
- if (envPtr->procPtr == NULL) {
+ /*
+ * Prepare for the internal foreach.
+ */
+
+ dataVar = TclFindCompiledLocal(NULL, 0, 1, envPtr);
+ iterVar = TclFindCompiledLocal(NULL, 0, 1, envPtr);
+ keyVar = TclFindCompiledLocal(NULL, 0, 1, envPtr);
+ valVar = TclFindCompiledLocal(NULL, 0, 1, envPtr);
+
+ if (dataVar < 0) {
/*
* Right number of arguments, but not compilable as we can't allocate
* (unnamed) local variables to manage the internal iteration.
@@ -343,21 +353,16 @@ TclCompileArraySetCmd(
cmdPtr);
TclEmitPush(cmdLit, envPtr);
TclDecrRefCount(objPtr);
- TclEmitInstInt4(INST_REVERSE, 2, envPtr);
- CompileWord(envPtr, tokenPtr, interp, 2);
+ if (localIndex >= 0) {
+ CompileWord(envPtr, varTokenPtr, interp, 1);
+ } else {
+ TclEmitInstInt4(INST_REVERSE, 2, envPtr);
+ }
+ CompileWord(envPtr, dataTokenPtr, interp, 2);
TclEmitInstInt1(INST_INVOKE_STK1, 3, envPtr);
return TCL_OK;
}
- /*
- * Prepare for the internal foreach.
- */
-
- dataVar = TclFindCompiledLocal(NULL, 0, 1, envPtr);
- iterVar = TclFindCompiledLocal(NULL, 0, 1, envPtr);
- keyVar = TclFindCompiledLocal(NULL, 0, 1, envPtr);
- valVar = TclFindCompiledLocal(NULL, 0, 1, envPtr);
-
infoPtr = ckalloc(sizeof(ForeachInfo) + sizeof(ForeachVarList *));
infoPtr->numLists = 1;
infoPtr->firstValueTemp = dataVar;
@@ -372,7 +377,7 @@ TclCompileArraySetCmd(
* Start issuing instructions to write to the array.
*/
- CompileWord(envPtr, tokenPtr, interp, 2);
+ CompileWord(envPtr, dataTokenPtr, interp, 2);
TclEmitOpcode( INST_DUP, envPtr);
TclEmitOpcode( INST_LIST_LENGTH, envPtr);
PushLiteral(envPtr, "1", 1);