summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordgp <dgp@users.sourceforge.net>2016-03-10 20:03:38 (GMT)
committerdgp <dgp@users.sourceforge.net>2016-03-10 20:03:38 (GMT)
commit812f825cfcb54b05a3df59e2cb1585af3da47c67 (patch)
treea9bcbf465a18808662e4dd07a1a84ce561e8d906
parentc31b2f4c54d596aafee955890527c1b2406093b1 (diff)
downloadtcl-812f825cfcb54b05a3df59e2cb1585af3da47c67.zip
tcl-812f825cfcb54b05a3df59e2cb1585af3da47c67.tar.gz
tcl-812f825cfcb54b05a3df59e2cb1585af3da47c67.tar.bz2
[b9b2079e6d] Proposed fix. When a compileProc fails, it may have done an
arbitrary amount of partial work, which needs to be undone. When the exception handling machinery got its last big revision, the undoing of what it does was neglected. I think this patch gets it all, but more eyes would be good.
-rw-r--r--generic/tclEnsemble.c43
1 files changed, 43 insertions, 0 deletions
diff --git a/generic/tclEnsemble.c b/generic/tclEnsemble.c
index 8f7d1a2..986a553 100644
--- a/generic/tclEnsemble.c
+++ b/generic/tclEnsemble.c
@@ -3082,6 +3082,11 @@ TclAttemptCompileProc(
Tcl_Token *saveTokenPtr = parsePtr->tokenPtr;
int savedStackDepth = envPtr->currStackDepth;
unsigned savedCodeNext = envPtr->codeNext - envPtr->codeStart;
+ int savedAuxDataArrayNext = envPtr->auxDataArrayNext;
+ int savedExceptArrayNext = envPtr->exceptArrayNext;
+#ifdef TCL_COMPILE_DEBUG
+ int savedExceptDepth = envPtr->exceptDepth;
+#endif
DefineLineInformation;
if (cmdPtr->compileProc == NULL) {
@@ -3130,7 +3135,45 @@ TclAttemptCompileProc(
* we avoid compiling subcommands that recursively call TclCompileScript().
*/
+#ifdef TCL_COMPILE_DEBUG
+ if (envPtr->exceptDepth != savedExceptDepth) {
+ Tcl_Panic("ExceptionRange Starts and Ends do not balance");
+ }
+#endif
+
if (result != TCL_OK) {
+ ExceptionAux *auxPtr = envPtr->exceptAuxArrayPtr;
+
+ for (i = 0; i < savedExceptArrayNext; i++) {
+ while (auxPtr->numBreakTargets > 0
+ && auxPtr->breakTargets[auxPtr->numBreakTargets - 1]
+ >= savedCodeNext) {
+ auxPtr->numBreakTargets--;
+ }
+ while (auxPtr->numContinueTargets > 0
+ && auxPtr->continueTargets[auxPtr->numContinueTargets - 1]
+ >= savedCodeNext) {
+ auxPtr->numContinueTargets--;
+ }
+ auxPtr++;
+ }
+ envPtr->exceptArrayNext = savedExceptArrayNext;
+
+ if (savedAuxDataArrayNext != envPtr->auxDataArrayNext) {
+ AuxData *auxDataPtr = envPtr->auxDataArrayPtr;
+ AuxData *auxDataEnd = auxDataPtr;
+
+ auxDataPtr += savedAuxDataArrayNext;
+ auxDataEnd += envPtr->auxDataArrayNext;
+
+ while (auxDataPtr < auxDataEnd) {
+ if (auxDataPtr->type->freeProc != NULL) {
+ auxDataPtr->type->freeProc(auxDataPtr->clientData);
+ }
+ auxDataPtr++;
+ }
+ envPtr->auxDataArrayNext = savedAuxDataArrayNext;
+ }
envPtr->currStackDepth = savedStackDepth;
envPtr->codeNext = envPtr->codeStart + savedCodeNext;
#ifdef TCL_COMPILE_DEBUG