diff options
author | sebres <sebres@users.sourceforge.net> | 2022-07-27 15:56:13 (GMT) |
---|---|---|
committer | sebres <sebres@users.sourceforge.net> | 2022-07-27 15:56:13 (GMT) |
commit | a66ed8e23823b7ddefdb8867d3f4d5dc5dfd44d6 (patch) | |
tree | e407ca30fc502db26f62d88a08df22b71f4c7501 /generic | |
parent | cf9f33de53a5c07f902ad314bf150e3385b1184f (diff) | |
download | tcl-a66ed8e23823b7ddefdb8867d3f4d5dc5dfd44d6.zip tcl-a66ed8e23823b7ddefdb8867d3f4d5dc5dfd44d6.tar.gz tcl-a66ed8e23823b7ddefdb8867d3f4d5dc5dfd44d6.tar.bz2 |
fixes [4eb3a155ac] and similar segfaults: reset corresponding bodyPtr->procPtr if procPtr gets released in TclProcCleanupProc, also recompile body if its procPtr is not the same as supplied.
Diffstat (limited to 'generic')
-rw-r--r-- | generic/tclProc.c | 17 |
1 files changed, 15 insertions, 2 deletions
diff --git a/generic/tclProc.c b/generic/tclProc.c index 59153b8..7550bfa 100644 --- a/generic/tclProc.c +++ b/generic/tclProc.c @@ -1576,13 +1576,16 @@ TclPushProcCallFrame( * is up-to-date), the namespace must match (so variable handling * is right) and the resolverEpoch must match (so that new shadowed * commands and/or resolver changes are considered). + * Ensure the ByteCode's procPtr is the same (or it's precompiled). */ codePtr = procPtr->bodyPtr->internalRep.twoPtrValue.ptr1; if (((Interp *) *codePtr->interpHandle != iPtr) || (codePtr->compileEpoch != iPtr->compileEpoch) || (codePtr->nsPtr != nsPtr) - || (codePtr->nsEpoch != nsPtr->resolverEpoch)) { + || (codePtr->nsEpoch != nsPtr->resolverEpoch) + || ((codePtr->procPtr != procPtr) && procPtr->bodyPtr->bytes) + ) { goto doCompilation; } } else { @@ -1920,6 +1923,7 @@ TclProcCompileProc( * procPtr->numCompiledLocals if new local variables are found while * compiling. * + * Ensure the ByteCode's procPtr is the same (or it is pure precompiled). * Precompiled procedure bodies, however, are immutable and therefore they * are not recompiled, even if things have changed. */ @@ -1928,7 +1932,9 @@ TclProcCompileProc( if (((Interp *) *codePtr->interpHandle == iPtr) && (codePtr->compileEpoch == iPtr->compileEpoch) && (codePtr->nsPtr == nsPtr) - && (codePtr->nsEpoch == nsPtr->resolverEpoch)) { + && (codePtr->nsEpoch == nsPtr->resolverEpoch) + && ((codePtr->procPtr == procPtr) || !bodyPtr->bytes) + ) { return TCL_OK; } @@ -2139,6 +2145,13 @@ TclProcCleanupProc( Interp *iPtr = procPtr->iPtr; if (bodyPtr != NULL) { + /* procPtr is stored in body's ByteCode, so ensure to reset it. */ + if (bodyPtr->typePtr == &tclByteCodeType) { + ByteCode *codePtr = bodyPtr->internalRep.twoPtrValue.ptr1; + if (codePtr->procPtr == procPtr) { + codePtr->procPtr = NULL; + } + } Tcl_DecrRefCount(bodyPtr); } for (localPtr = procPtr->firstLocalPtr; localPtr != NULL; ) { |