summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorpooryorick <com.digitalsmarties@pooryorick.com>2021-09-01 23:13:17 (GMT)
committerpooryorick <com.digitalsmarties@pooryorick.com>2021-09-01 23:13:17 (GMT)
commit166d3a5b6c49ef9433b4e01976d24d25534431fb (patch)
tree908304349d9451e61944df4f26de72a8bbfa1ede
parent00b583a57994fe50d0b67f154b398d81b4ab7561 (diff)
downloadtcl-166d3a5b6c49ef9433b4e01976d24d25534431fb.zip
tcl-166d3a5b6c49ef9433b4e01976d24d25534431fb.tar.gz
tcl-166d3a5b6c49ef9433b4e01976d24d25534431fb.tar.bz2
Fix for [ccc448a6bfd59cbd], namespace ensemble subcommand name prefix matching and a subsequent error results in a segmentation fault
-rw-r--r--generic/tclEnsemble.c20
-rw-r--r--generic/tclIndexObj.c18
-rw-r--r--generic/tclInt.h1
-rw-r--r--generic/tclNamesp.c5
-rw-r--r--tests/namespace.test18
5 files changed, 46 insertions, 16 deletions
diff --git a/generic/tclEnsemble.c b/generic/tclEnsemble.c
index 13408e1..799c645 100644
--- a/generic/tclEnsemble.c
+++ b/generic/tclEnsemble.c
@@ -2201,6 +2201,18 @@ TclSpellFix(
TclNRAddCallback(interp, TclNRReleaseValues, fix, NULL, NULL, NULL);
}
+Tcl_Obj *const *TclEnsembleGetRewriteValues(
+ Tcl_Interp *interp /* Current interpreter. */
+)
+{
+ Interp *iPtr = (Interp *) interp;
+ Tcl_Obj *const *origObjv = iPtr->ensembleRewrite.sourceObjs;
+ if (origObjv[0] == NULL) {
+ origObjv = (Tcl_Obj *const *)origObjv[2];
+ }
+ return origObjv;
+}
+
/*
*----------------------------------------------------------------------
*
@@ -2225,12 +2237,18 @@ TclFetchEnsembleRoot(
int objc,
int *objcPtr)
{
+ Tcl_Obj *const *sourceObjs;
Interp *iPtr = (Interp *) interp;
if (iPtr->ensembleRewrite.sourceObjs) {
*objcPtr = objc + iPtr->ensembleRewrite.numRemovedObjs
- iPtr->ensembleRewrite.numInsertedObjs;
- return iPtr->ensembleRewrite.sourceObjs;
+ if (iPtr->ensembleRewrite.sourceObjs[0] == NULL) {
+ sourceObjs = iPtr->ensembleRewrite.sourceObjs[1];
+ } else {
+ sourceObjs = iPtr->ensembleRewrite.sourceObjs;
+ }
+ return sourceObjs;
}
*objcPtr = objc;
return objv;
diff --git a/generic/tclIndexObj.c b/generic/tclIndexObj.c
index b665589..f81f0b3 100644
--- a/generic/tclIndexObj.c
+++ b/generic/tclIndexObj.c
@@ -798,27 +798,19 @@ Tcl_WrongNumArgs(
}
/*
- * Check to see if we are processing an ensemble implementation, and if so
- * rewrite the results in terms of how the ensemble was invoked.
+ * If processing an an ensemble implementation, rewrite the results in
+ * terms of how the ensemble was invoked.
*/
if (iPtr->ensembleRewrite.sourceObjs != NULL) {
int toSkip = iPtr->ensembleRewrite.numInsertedObjs;
int toPrint = iPtr->ensembleRewrite.numRemovedObjs;
- Tcl_Obj *const *origObjv = iPtr->ensembleRewrite.sourceObjs;
+ Tcl_Obj *const *origObjv = TclEnsembleGetRewriteValues(interp);
/*
- * Check for spelling fixes, and substitute the fixed values.
- */
-
- if (origObjv[0] == NULL) {
- origObjv = (Tcl_Obj *const *)origObjv[2];
- }
-
- /*
- * We only know how to do rewriting if all the replaced objects are
+ * Only do rewrite the command if all the replaced objects are
* actually arguments (in objv) to this function. Otherwise it just
- * gets too complicated and we'd be better off just giving a slightly
+ * gets too complicated and it's to just give a slightly
* confusing error message...
*/
diff --git a/generic/tclInt.h b/generic/tclInt.h
index 7f19a42..96bbfc5 100644
--- a/generic/tclInt.h
+++ b/generic/tclInt.h
@@ -2924,6 +2924,7 @@ MODULE_SCOPE char * TclDStringAppendDString(Tcl_DString *dsPtr,
MODULE_SCOPE Tcl_Obj * TclDStringToObj(Tcl_DString *dsPtr);
MODULE_SCOPE Tcl_Obj *const *TclFetchEnsembleRoot(Tcl_Interp *interp,
Tcl_Obj *const *objv, int objc, int *objcPtr);
+MODULE_SCOPE Tcl_Obj *const *TclEnsembleGetRewriteValues(Tcl_Interp *interp);
MODULE_SCOPE Tcl_Namespace *TclEnsureNamespace(Tcl_Interp *interp,
Tcl_Namespace *namespacePtr);
MODULE_SCOPE void TclFinalizeAllocSubsystem(void);
diff --git a/generic/tclNamesp.c b/generic/tclNamesp.c
index 8f2a711..f935fa4 100644
--- a/generic/tclNamesp.c
+++ b/generic/tclNamesp.c
@@ -4924,8 +4924,9 @@ TclLogCommandInfo(
* command (must be <= command). */
const char *command, /* First character in command that generated
* the error. */
- size_t length, /* Number of bytes in command (-1 means
- * use all bytes up to first null byte). */
+ size_t length, /* Number of bytes in command (TCL_INDEX_NONE
+ * means use all bytes up to first null byte).
+ */
const unsigned char *pc, /* Current pc of bytecode execution context */
Tcl_Obj **tosPtr) /* Current stack of bytecode execution
* context */
diff --git a/tests/namespace.test b/tests/namespace.test
index 2d0c20f..ae233cb 100644
--- a/tests/namespace.test
+++ b/tests/namespace.test
@@ -1920,6 +1920,24 @@ test namespace-42.10 {
unset -nocomplain lst
} -returnCodes error -match glob -result {invalid command name *three*}
+
+test namespace-42.11 {
+ ensembles: prefix matching segmentation fault
+
+ issue ccc448a6bfd59cbd
+} -body {
+ namespace eval n1 {
+ namespace ensemble create
+ namespace export *
+ proc p1 args {error success}
+ }
+ # segmentation fault only occurs in the non-byte-compiled path, so avoid
+ # byte compilation
+ set cmd {namespace eva n1 {[namespace parent]::n1 p1}}
+ {*}$cmd
+} -returnCodes error -result success
+
+
test namespace-43.1 {ensembles: dict-driven} {
namespace eval ns {
namespace export x*