diff options
author | dkf <donal.k.fellows@manchester.ac.uk> | 2011-01-18 13:50:03 (GMT) |
---|---|---|
committer | dkf <donal.k.fellows@manchester.ac.uk> | 2011-01-18 13:50:03 (GMT) |
commit | c246782cc0bc14600f737dfc07d0bc3853d95dd4 (patch) | |
tree | 15edbecb894fd8e2daad2287e1441ab6dc1615b0 /generic/tclOOMethod.c | |
parent | 57ab68714417969c9ff520967d92a7e3dde7a66d (diff) | |
download | tcl-c246782cc0bc14600f737dfc07d0bc3853d95dd4.zip tcl-c246782cc0bc14600f737dfc07d0bc3853d95dd4.tar.gz tcl-c246782cc0bc14600f737dfc07d0bc3853d95dd4.tar.bz2 |
* generic/tclOOMethod.c (PushMethodCallFrame): [Bug 3001438]: Make
sure that the cmdPtr field of the procPtr is correct and relevant at
all times so that [info frame] can report sensible information about a
frame after a return to it from a recursive call, instead of probably
crashing (depending on what else has overwritten the Tcl stack!)
Diffstat (limited to 'generic/tclOOMethod.c')
-rw-r--r-- | generic/tclOOMethod.c | 38 |
1 files changed, 35 insertions, 3 deletions
diff --git a/generic/tclOOMethod.c b/generic/tclOOMethod.c index 61aeb12..735ced9 100644 --- a/generic/tclOOMethod.c +++ b/generic/tclOOMethod.c @@ -8,7 +8,7 @@ * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclOOMethod.c,v 1.29 2010/11/09 16:26:30 dkf Exp $ + * RCS: @(#) $Id: tclOOMethod.c,v 1.30 2011/01/18 13:50:03 dkf Exp $ */ #ifdef HAVE_CONFIG_H @@ -41,6 +41,7 @@ typedef struct { Tcl_Obj *nameObj; /* The "name" of the command. */ Command cmd; /* The command structure. Mostly bogus. */ ExtraFrameInfo efi; /* Extra information used for [info frame]. */ + Command *oldCmdPtr; struct PNI pni; /* Specialist information used in the efi * field for this type of call. */ } PMFrameData; @@ -711,6 +712,13 @@ InvokeProcedureMethod( result = pmPtr->preCallProc(pmPtr->clientData, interp, context, (Tcl_CallFrame *) fdPtr->framePtr, &isFinished); if (isFinished || result != TCL_OK) { + /* + * Restore the old cmdPtr so that a subsequent use of [info frame] + * won't crash on us. [Bug 3001438] + */ + + pmPtr->procPtr->cmdPtr = fdPtr->oldCmdPtr; + Tcl_PopCallFrame(interp); TclStackFree(interp, fdPtr->framePtr); if (--pmPtr->refCount < 1) { @@ -752,6 +760,13 @@ FinalizePMCall( } /* + * Restore the old cmdPtr so that a subsequent use of [info frame] won't + * crash on us. [Bug 3001438] + */ + + pmPtr->procPtr->cmdPtr = fdPtr->oldCmdPtr; + + /* * Scrap the special frame data now that we're done with it. Note that we * are inlining DeleteProcedureMethod() here; this location is highly * sensitive when it comes to performance! @@ -820,6 +835,14 @@ PushMethodCallFrame( } /* + * Save the old cmdPtr so that when this recursive call returns, we can + * restore it. To do otherwise causes crashes in [info frame] after we + * return from a recursive call. [Bug 3001438] + */ + + fdPtr->oldCmdPtr = pmPtr->procPtr->cmdPtr; + + /* * Compile the body. This operation may fail. */ @@ -845,7 +868,7 @@ PushMethodCallFrame( result = TclProcCompileProc(interp, pmPtr->procPtr, pmPtr->procPtr->bodyPtr, nsPtr, "body of method", namePtr); if (result != TCL_OK) { - return result; + goto failureReturn; } /* @@ -856,7 +879,7 @@ PushMethodCallFrame( result = TclPushStackFrame(interp, (Tcl_CallFrame **) framePtrPtr, (Tcl_Namespace *) nsPtr, FRAME_IS_PROC|FRAME_IS_METHOD); if (result != TCL_OK) { - return result; + goto failureReturn; } fdPtr->framePtr->clientData = contextPtr; @@ -891,6 +914,15 @@ PushMethodCallFrame( } return TCL_OK; + + /* + * Restore the old cmdPtr so that a subsequent use of [info frame] won't + * crash on us. [Bug 3001438] + */ + + failureReturn: + pmPtr->procPtr->cmdPtr = fdPtr->oldCmdPtr; + return result; } /* |