summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorpooryorick <com.digitalsmarties@pooryorick.com>2020-08-12 13:35:00 (GMT)
committerpooryorick <com.digitalsmarties@pooryorick.com>2020-08-12 13:35:00 (GMT)
commit478d024dc372e58261448aa2e96a39cca274733b (patch)
tree7d8ca4dd257c89320d65a0c6b7ffcf0479207e02
parent167c883c087ff89c46268d3b3a0067a8095704a5 (diff)
parent80c4d66b217ec43299960d17a40f07d4cfd870bf (diff)
downloadtcl-478d024dc372e58261448aa2e96a39cca274733b.zip
tcl-478d024dc372e58261448aa2e96a39cca274733b.tar.gz
tcl-478d024dc372e58261448aa2e96a39cca274733b.tar.bz2
merge bug-3422267ed6b79922
-rw-r--r--generic/tclNamesp.c7
-rw-r--r--generic/tclProc.c7
-rw-r--r--tests/interp.test37
3 files changed, 50 insertions, 1 deletions
diff --git a/generic/tclNamesp.c b/generic/tclNamesp.c
index 26dca62..fea23aa 100644
--- a/generic/tclNamesp.c
+++ b/generic/tclNamesp.c
@@ -959,7 +959,7 @@ Tcl_DeleteNamespace(
/*
* If the namespace has associated ensemble commands, delete them first.
* This leaves the actual contents of the namespace alone (unless they are
- * linked ensemble commands, of course). Note that this code is actually
+ * linked ensemble commands, of course). This code is
* reentrant so command delete traces won't purturb things badly.
*/
@@ -1770,7 +1770,9 @@ DoImport(
TclInvokeImportedCmd, InvokeImportedNRCmd, dataPtr,
DeleteImportedCmd);
dataPtr->realCmdPtr = cmdPtr;
+ cmdPtr->refCount++;
dataPtr->selfPtr = (Command *) importedCmd;
+ dataPtr->selfPtr->refCount++;
dataPtr->selfPtr->compileProc = cmdPtr->compileProc;
Tcl_DStringFree(&ds);
@@ -1781,6 +1783,7 @@ DoImport(
refPtr = (ImportRef *)ckalloc(sizeof(ImportRef));
refPtr->importedCmdPtr = (Command *) importedCmd;
+ refPtr->importedCmdPtr->refCount++;
refPtr->nextPtr = cmdPtr->importRefPtr;
cmdPtr->importRefPtr = refPtr;
} else {
@@ -2076,7 +2079,9 @@ DeleteImportedCmd(
} else {
prevPtr->nextPtr = refPtr->nextPtr;
}
+ TclCleanupCommandMacro(refPtr->importedCmdPtr);
ckfree(refPtr);
+ TclCleanupCommandMacro(selfPtr)
ckfree(dataPtr);
return;
}
diff --git a/generic/tclProc.c b/generic/tclProc.c
index 0d67c37..150d036 100644
--- a/generic/tclProc.c
+++ b/generic/tclProc.c
@@ -215,6 +215,7 @@ Tcl_ProcObjCmd(
*/
procPtr->cmdPtr = (Command *) cmd;
+ procPtr->cmdPtr->refCount++;
/*
* TIP #280: Remember the line the procedure body is starting on. In a
@@ -2154,6 +2155,12 @@ TclProcCleanupProc(
ckfree(localPtr);
localPtr = nextPtr;
}
+ /*
+ * TclOOMethod.c:clOOMakeProcMethod sets cmdPtr to NULL
+ */
+ if (procPtr->cmdPtr) {
+ TclCleanupCommandMacro(procPtr->cmdPtr);
+ }
ckfree(procPtr);
/*
diff --git a/tests/interp.test b/tests/interp.test
index 599ac08..9287756 100644
--- a/tests/interp.test
+++ b/tests/interp.test
@@ -3664,6 +3664,43 @@ test interp-38.8 {interp debug basic setup} -body {
} -returnCodes {
error
} -result {wrong # args: should be "interp debug path ?-frame ?bool??"}
+
+test interp-39.0 {
+ no segmentation fault when a command is deleted
+} -body {
+ variable res {}
+
+ proc p1 args {
+ return success
+ }
+ namespace eval ns1 {
+ namespace export *
+ }
+ interp alias {} [namespace current]::ns1::p2 {} [namespace current]::p1
+ namespace eval ns2 {
+ namespace import [namespace parent]::ns1::p2
+ }
+ proc ondelete {oldname newname op} {
+ variable res
+ namespace delete ns1
+ catch {
+ ns1::p2
+ } res
+ }
+
+ trace add command ns2::p2 delete [namespace which ondelete]
+ rename ns2::p2 {}
+ rename p1 {}
+ if {
+ [string match {*invalid command name*ns1::p2*} $res]
+ } {
+ return 1
+ } else {
+ return $res
+ }
+} -cleanup {
+} -result 1
+
# cleanup
unset -nocomplain hidden_cmds