diff options
author | pooryorick <com.digitalsmarties@pooryorick.com> | 2021-09-01 23:13:17 (GMT) |
---|---|---|
committer | pooryorick <com.digitalsmarties@pooryorick.com> | 2021-09-01 23:13:17 (GMT) |
commit | 166d3a5b6c49ef9433b4e01976d24d25534431fb (patch) | |
tree | 908304349d9451e61944df4f26de72a8bbfa1ede | |
parent | 00b583a57994fe50d0b67f154b398d81b4ab7561 (diff) | |
download | tcl-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.c | 20 | ||||
-rw-r--r-- | generic/tclIndexObj.c | 18 | ||||
-rw-r--r-- | generic/tclInt.h | 1 | ||||
-rw-r--r-- | generic/tclNamesp.c | 5 | ||||
-rw-r--r-- | tests/namespace.test | 18 |
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* |