Tcl Source Code

View Ticket
Login
Ticket UUID: 63449c05144fa85be0217ee3f82a78c6605bbdd3
Title: [namespace children] doesn't match non-glob patterns below the global namespace
Type: Bug Version: Current
Submitter: stu Created on: 2024-02-22 07:17:55
Subsystem: 21. [namespace] Assigned To: jan.nijtmans
Priority: 6 Severity: Minor
Status: Closed Last Modified: 2025-07-31 18:45:11
Resolution: Fixed Closed By: dgp
    Closed on: 2025-07-31 18:45:11
Description:
# Create namespaces
namespace eval a { namespace eval b {} }

# Good result with non-glob pattern, and global namespace
namespace children :: a  ;# => ::a

# Good result with single-char glob pattern, and other namespace
namespace children a {[b]}  ;# => ::a::b

# Good result because of glob char in pattern, and other namespace
namespace children a b*  ;# => ::a::b

# Bad result with non-glob pattern, and other namespace
namespace children a b  ;# => {}


In generic/tclNamespace.c, function NamespaceChildrenCmd (lines 2988-3108), Tcl_StringMatch will be called if a glob char is present in the pattern, otherwise the matching will be performed with a combination of strncmp() and Tcl_FindHashEntry:
line 3067:  if ((pattern != NULL) && TclMatchIsTrivial(pattern)) {

The hash table lookup:
line 3075 or 3078:  Tcl_FindHashEntry(&nsPtr->childTable, pattern+length) != NULL

These two chars might be added but they won't be taken into account when matching: lines 3053-3055:
if (nsPtr != globalNsPtr) {
    TclDStringAppendLiteral(&buffer, "::");
}


With a quick hack patch:
-Tcl_FindHashEntry(&nsPtr->childTable, pattern+length) != NULL
+Tcl_FindHashEntry(&nsPtr->childTable, 2+pattern+length) != NULL

The child namespace can now be found:
namespace children a b  ;# => ::a::b

However namespace ::a can no longer be found in the global namespace!
namespace children :: a  ;# => {}


The two namespace separator ("::") chars are not being accounted for properly.
User Comments: dgp added on 2025-07-31 18:45:11:
Backport landed on the 8.6 branch last December, so I guess
the decision got made.  Closing.

oehhar (claiming to be oehar) added on 2024-12-15 10:04:56:

Great ! I would love some explanatory text around the fix source. Maybe, I care tomorrow !

And it is 9.0.1, not 9.0.2, right ?

Take care, Harald


jan.nijtmans added on 2024-12-14 23:40:59:

The CI build shows no regressions. So, Yes I think this should be included into Tcl 9.0.2 (to be discussed within the TTT).

Was this problem introduced in Tcl 8.7 or 9.0, or was it always there? Should it be backported to 8.7 and/or 8.6? Therefore, leaving this ticket open. No hurry to decide that.


jan.nijtmans added on 2024-12-13 15:06:13:

Proposed fix [ee821ec00f|here]


stu added on 2024-12-02 15:02:07:
The patch is just a suggestion.
The problem is an offset of 2 is not added when it should be.
I'm not familiar enough with the code to pick the best place to do this.

stu added on 2024-02-22 07:33:25:
Correction:
-Tcl_FindHashEntry(&nsPtr->childTable, pattern+length) != NULL
+Tcl_FindHashEntry(&nsPtr->childTable, (nsPtr != globalNsPtr ? 2 : 0)+pattern+length) != NULL

stu added on 2024-02-22 07:32:03:
This patch handles global and non-global. q&d poc

-Tcl_FindHashEntry(&nsPtr->childTable, 2+pattern+length) != NULL
+Tcl_FindHashEntry(&nsPtr->childTable, (nsPtr != globalNsPtr ? 2 : 0)+pattern+length) != NULL