summaryrefslogtreecommitdiffstats
path: root/generic/tclOOCall.c
diff options
context:
space:
mode:
authorsebres <sebres@users.sourceforge.net>2024-05-21 10:33:56 (GMT)
committersebres <sebres@users.sourceforge.net>2024-05-21 10:33:56 (GMT)
commite055d3cdb5ac22d967c59dffd452c743d37e9063 (patch)
tree816d415cc650bea382fd9210fc280b4460ad4c2e /generic/tclOOCall.c
parent32cf8873827bc37408f0a96891258d9665d54ba8 (diff)
parentff100527cd125f5895094ba35b9308e7ffb37756 (diff)
downloadtcl-e055d3cdb5ac22d967c59dffd452c743d37e9063.zip
tcl-e055d3cdb5ac22d967c59dffd452c743d37e9063.tar.gz
tcl-e055d3cdb5ac22d967c59dffd452c743d37e9063.tar.bz2
merge 8.7
Diffstat (limited to 'generic/tclOOCall.c')
-rw-r--r--generic/tclOOCall.c58
1 files changed, 52 insertions, 6 deletions
diff --git a/generic/tclOOCall.c b/generic/tclOOCall.c
index 46ee8be..f13aa99 100644
--- a/generic/tclOOCall.c
+++ b/generic/tclOOCall.c
@@ -1073,15 +1073,28 @@ InitCallChain(
Object *oPtr,
int flags)
{
+ /*
+ * Note that it's possible to end up with a NULL oPtr->selfCls here if
+ * there is a call into stereotypical object after it has finished running
+ * its destructor phase. Such things can't be cached for a long time so the
+ * epoch can be bogus. [Bug 7842f33a5c]
+ */
+
callPtr->flags = flags &
(PUBLIC_METHOD | PRIVATE_METHOD | SPECIAL | FILTER_HANDLING);
if (oPtr->flags & USE_CLASS_CACHE) {
- oPtr = oPtr->selfCls->thisPtr;
+ oPtr = (oPtr->selfCls ? oPtr->selfCls->thisPtr : NULL);
callPtr->flags |= USE_CLASS_CACHE;
}
- callPtr->epoch = oPtr->fPtr->epoch;
- callPtr->objectCreationEpoch = oPtr->creationEpoch;
- callPtr->objectEpoch = oPtr->epoch;
+ if (oPtr) {
+ callPtr->epoch = oPtr->fPtr->epoch;
+ callPtr->objectCreationEpoch = oPtr->creationEpoch;
+ callPtr->objectEpoch = oPtr->epoch;
+ } else {
+ callPtr->epoch = 0;
+ callPtr->objectCreationEpoch = 0;
+ callPtr->objectEpoch = 0;
+ }
callPtr->refCount = 1;
callPtr->numChain = 0;
callPtr->chain = callPtr->staticChain;
@@ -1112,6 +1125,13 @@ IsStillValid(
int mask)
{
if ((oPtr->flags & USE_CLASS_CACHE)) {
+ /*
+ * If the object is in a weird state (due to stereotype tricks) then
+ * just declare the cache invalid. [Bug 7842f33a5c]
+ */
+ if (!oPtr->selfCls) {
+ return 0;
+ }
oPtr = oPtr->selfCls->thisPtr;
flags |= USE_CLASS_CACHE;
}
@@ -1209,8 +1229,16 @@ TclOOGetCallContext(
Tcl_StoreInternalRep(cacheInThisObj, &methodNameType, NULL);
}
- if (oPtr->flags & USE_CLASS_CACHE) {
- if (oPtr->selfCls->classChainCache != NULL) {
+ /*
+ * Note that it's possible to end up with a NULL oPtr->selfCls here if
+ * there is a call into stereotypical object after it has finished
+ * running its destructor phase. It's quite a tangle, but at that
+ * point, we simply can't get stereotypes from the cache.
+ * [Bug 7842f33a5c]
+ */
+
+ if (oPtr->flags & USE_CLASS_CACHE && oPtr->selfCls) {
+ if (oPtr->selfCls->classChainCache) {
hPtr = Tcl_FindHashEntry(oPtr->selfCls->classChainCache,
methodNameObj);
} else {
@@ -1424,6 +1452,17 @@ TclOOGetStereotypeCallChain(
Object obj;
/*
+ * Note that it's possible to end up with a NULL clsPtr here if there is
+ * a call into stereotypical object after it has finished running its
+ * destructor phase. It's quite a tangle, but at that point, we simply
+ * can't get stereotypes. [Bug 7842f33a5c]
+ */
+
+ if (clsPtr == NULL) {
+ return NULL;
+ }
+
+ /*
* Synthesize a temporary stereotypical object so that we can use existing
* machinery to produce the stereotypical call chain.
*/
@@ -1650,9 +1689,16 @@ AddPrivatesFromClassChainToCallContext(
*
* Note that mixins must be processed before the main class hierarchy.
* [Bug 1998221]
+ *
+ * Note also that it's possible to end up with a null classPtr here if
+ * there is a call into stereotypical object after it has finished running
+ * its destructor phase. [Bug 7842f33a5c]
*/
tailRecurse:
+ if (classPtr == NULL) {
+ return 0;
+ }
FOREACH(superPtr, classPtr->mixins) {
if (AddPrivatesFromClassChainToCallContext(superPtr, contextCls,
methodName, cbPtr, doneFilters, flags|TRAVERSED_MIXIN,