summaryrefslogtreecommitdiffstats
path: root/generic/tclBasic.c
diff options
context:
space:
mode:
authorjan.nijtmans <nijtmans@users.sourceforge.net>2024-03-10 11:27:02 (GMT)
committerjan.nijtmans <nijtmans@users.sourceforge.net>2024-03-10 11:27:02 (GMT)
commitdda19928bf1aabc937d370f3ab5c612189a58ff7 (patch)
tree47c5659dc469a80f8fa44da4b92c19b75fd49035 /generic/tclBasic.c
parent7ce44f26ec53ad8711bafd772e7381f9a3034452 (diff)
parente649d3487899b2a23aad3169224a161891e6ae33 (diff)
downloadtcl-dda19928bf1aabc937d370f3ab5c612189a58ff7.zip
tcl-dda19928bf1aabc937d370f3ab5c612189a58ff7.tar.gz
tcl-dda19928bf1aabc937d370f3ab5c612189a58ff7.tar.bz2
Fix [910d67a229fe7f65]: NS-qualified invocations of command evade [namespace unknown]
Diffstat (limited to 'generic/tclBasic.c')
-rw-r--r--generic/tclBasic.c51
1 files changed, 47 insertions, 4 deletions
diff --git a/generic/tclBasic.c b/generic/tclBasic.c
index b01717e..509e63c 100644
--- a/generic/tclBasic.c
+++ b/generic/tclBasic.c
@@ -5183,11 +5183,54 @@ TEOV_NotFound(
* namespace (TIP 181). */
Namespace *savedNsPtr = NULL;
+ int qualLen;
+ const char *qualName = TclGetStringFromObj(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;
+ }
}
}