From fc2bc121acb78c5544d30d1e7ceb507397fe3e78 Mon Sep 17 00:00:00 2001 From: dgp Date: Thu, 7 Jul 2016 18:44:56 +0000 Subject: To use a Tcl_Command token [aka (Command *)] for epoch checking, we must not permit it to be freed while we hold it or else it could be mistaken for another token allocated later that just happens to reside at the same address. (Command *) preservation machinery already exists, just need to use it. An extension facing the same problem might have to rely on command delete traces. Earlier revisions used (Namespace *) lifetime to achieve the same results, but that's really an indirect (possibly non-robust) path to achieving the proper goal. Valgrind is happy now. --- generic/tclEnsemble.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/generic/tclEnsemble.c b/generic/tclEnsemble.c index 5c47ce3..24b6b9a 100644 --- a/generic/tclEnsemble.c +++ b/generic/tclEnsemble.c @@ -93,7 +93,7 @@ typedef struct { int epoch; /* Used to confirm when the data in this * really structure matches up with the * ensemble. */ - Tcl_Command token; /* Reference to the comamnd for which this + Command *token; /* Reference to the command for which this * structure is a cache of the resolution. */ Tcl_Obj *fix; /* Corrected spelling, if needed. */ Tcl_HashEntry *hPtr; /* Direct link to entry in the subcommand @@ -1727,7 +1727,7 @@ NsEnsembleImplementationCmdNR( EnsembleCmdRep *ensembleCmd = subObj->internalRep.twoPtrValue.ptr1; if (ensembleCmd->epoch == ensemblePtr->epoch && - ensembleCmd->token == ensemblePtr->token) { + ensembleCmd->token == (Command *)ensemblePtr->token) { prefixObj = Tcl_GetHashValue(ensembleCmd->hPtr); Tcl_IncrRefCount(prefixObj); if (ensembleCmd->fix) { @@ -2404,7 +2404,8 @@ MakeCachedEnsembleCommand( */ ensembleCmd->epoch = ensemblePtr->epoch; - ensembleCmd->token = ensemblePtr->token; + ensembleCmd->token = (Command *) ensemblePtr->token; + ensembleCmd->token->refCount++; if (fix) { Tcl_IncrRefCount(fix); } @@ -2790,6 +2791,7 @@ FreeEnsembleCmdRep( { EnsembleCmdRep *ensembleCmd = objPtr->internalRep.twoPtrValue.ptr1; + TclCleanupCommandMacro(ensembleCmd->token); if (ensembleCmd->fix) { Tcl_DecrRefCount(ensembleCmd->fix); } @@ -2827,6 +2829,7 @@ DupEnsembleCmdRep( copyPtr->internalRep.twoPtrValue.ptr1 = ensembleCopy; ensembleCopy->epoch = ensembleCmd->epoch; ensembleCopy->token = ensembleCmd->token; + ensembleCopy->token->refCount++; ensembleCopy->fix = ensembleCmd->fix; if (ensembleCopy->fix) { Tcl_IncrRefCount(ensembleCopy->fix); -- cgit v0.12 From 1d9f88074f824a962f99296d5aefece2fa918a99 Mon Sep 17 00:00:00 2001 From: dgp Date: Thu, 7 Jul 2016 19:50:02 +0000 Subject: Missed a cleanup line, which created a memleak. --- generic/tclEnsemble.c | 1 + 1 file changed, 1 insertion(+) diff --git a/generic/tclEnsemble.c b/generic/tclEnsemble.c index 24b6b9a..d2bd0a2 100644 --- a/generic/tclEnsemble.c +++ b/generic/tclEnsemble.c @@ -2384,6 +2384,7 @@ MakeCachedEnsembleCommand( if (objPtr->typePtr == &ensembleCmdType) { ensembleCmd = objPtr->internalRep.twoPtrValue.ptr1; + TclCleanupCommandMacro(ensembleCmd->token); if (ensembleCmd->fix) { Tcl_DecrRefCount(ensembleCmd->fix); } -- cgit v0.12