diff options
| author | jan.nijtmans <nijtmans@users.sourceforge.net> | 2024-03-10 13:04:36 (GMT) |
|---|---|---|
| committer | jan.nijtmans <nijtmans@users.sourceforge.net> | 2024-03-10 13:04:36 (GMT) |
| commit | 2f56475abef6d4b1beb76db34e70e5c19fed1993 (patch) | |
| tree | feeb4afa0b424d88feaa912a39297efc68bbfdd9 /generic/tclBasic.c | |
| parent | e155906680eddb78ff64f83914f08d68d555443c (diff) | |
| parent | dda19928bf1aabc937d370f3ab5c612189a58ff7 (diff) | |
| download | tcl-2f56475abef6d4b1beb76db34e70e5c19fed1993.zip tcl-2f56475abef6d4b1beb76db34e70e5c19fed1993.tar.gz tcl-2f56475abef6d4b1beb76db34e70e5c19fed1993.tar.bz2 | |
Fix [910d67a229fe7f65]: NS-qualified invocations of command evade [namespace unknown]
Diffstat (limited to 'generic/tclBasic.c')
| -rw-r--r-- | generic/tclBasic.c | 51 |
1 files changed, 47 insertions, 4 deletions
diff --git a/generic/tclBasic.c b/generic/tclBasic.c index e8ff3d9..592529f 100644 --- a/generic/tclBasic.c +++ b/generic/tclBasic.c @@ -4805,11 +4805,54 @@ TEOV_NotFound( * namespace (TIP 181). */ Namespace *savedNsPtr = NULL; + Tcl_Size qualLen; + const char *qualName = Tcl_GetStringFromObj(objv[0], &qualLen); + currNsPtr = varFramePtr->nsPtr; - if ((currNsPtr == NULL) || (currNsPtr->unknownHandlerPtr == NULL)) { - currNsPtr = iPtr->globalNsPtr; - if (currNsPtr == NULL) { - Tcl_Panic("Tcl_EvalObjv: NULL global namespace pointer"); + if ((currNsPtr == NULL) || (currNsPtr->unknownHandlerPtr == NULL) || + (qualLen > 2 && memchr(qualName, ':', qualLen)) /* fast check for NS:: */ + ) { + /* + * first try to find namespace unknown handler of the namespace + * of executed command if available: + */ + Namespace *altNsPtr, *dummyNsPtr; + const char *simpleName; + + (void) TclGetNamespaceForQualName(interp, qualName, currNsPtr, + TCL_FIND_IF_NOT_SIMPLE, &currNsPtr, &altNsPtr, + &dummyNsPtr, &simpleName); + if (!simpleName) { + goto globNS; + } + if (!currNsPtr || (currNsPtr == iPtr->globalNsPtr)) { + if (!altNsPtr || (altNsPtr == iPtr->globalNsPtr)) { + goto globNS; + } + currNsPtr = altNsPtr; + } + while (currNsPtr->unknownHandlerPtr == NULL || + (currNsPtr->flags & (NS_DYING | NS_DEAD)) + ) { + /* traverse to alive parent namespace containing handler */ + if (!(currNsPtr = currNsPtr->parentPtr) || + (currNsPtr == iPtr->globalNsPtr) + ) { + /* continue from alternate NS if available */ + if (!altNsPtr || (altNsPtr == iPtr->globalNsPtr)) { + goto globNS; + } + currNsPtr = altNsPtr; + altNsPtr = NULL; + continue; + globNS: + /* fallback to the global unknown */ + currNsPtr = iPtr->globalNsPtr; + if (currNsPtr == NULL) { + Tcl_Panic("TEOV_NotFound: NULL global namespace pointer"); + } + break; + } } } |
