summaryrefslogtreecommitdiffstats
path: root/generic
diff options
context:
space:
mode:
authordkf <donal.k.fellows@manchester.ac.uk>2008-05-20 22:22:14 (GMT)
committerdkf <donal.k.fellows@manchester.ac.uk>2008-05-20 22:22:14 (GMT)
commita1ca307c098bd1b12e73b18eb500707296e084ca (patch)
treed20e5333aee55b716637ba25b7de217b6e49fef6 /generic
parentecf4164c6f084705cf96b0610c3bfc82c44a094f (diff)
downloadtcl-a1ca307c098bd1b12e73b18eb500707296e084ca.zip
tcl-a1ca307c098bd1b12e73b18eb500707296e084ca.tar.gz
tcl-a1ca307c098bd1b12e73b18eb500707296e084ca.tar.bz2
Correct logic for handling error cases when setting the namespace unknown handler.
Diffstat (limited to 'generic')
-rw-r--r--generic/tclNamesp.c61
1 files changed, 37 insertions, 24 deletions
diff --git a/generic/tclNamesp.c b/generic/tclNamesp.c
index f7fa9c1..691c62f 100644
--- a/generic/tclNamesp.c
+++ b/generic/tclNamesp.c
@@ -23,7 +23,7 @@
* See the file "license.terms" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tclNamesp.c,v 1.162 2008/03/02 18:46:39 msofer Exp $
+ * RCS: @(#) $Id: tclNamesp.c,v 1.163 2008/05/20 22:22:16 dkf Exp $
*/
#include "tclInt.h"
@@ -4296,45 +4296,58 @@ Tcl_SetNamespaceUnknownHandler(
Tcl_Namespace *nsPtr, /* Namespace which is being updated. */
Tcl_Obj *handlerPtr) /* The new handler, or NULL to reset. */
{
- int lstlen;
+ int lstlen = 0;
Namespace *currNsPtr = (Namespace *)nsPtr;
- if (currNsPtr->unknownHandlerPtr != NULL) {
- /*
- * Remove old handler first.
- */
+ /*
+ * Ensure that we check for errors *first* before we change anything.
+ */
- Tcl_DecrRefCount(currNsPtr->unknownHandlerPtr);
- currNsPtr->unknownHandlerPtr = NULL;
+ if (handlerPtr != NULL) {
+ if (TclListObjLength(interp, handlerPtr, &lstlen) != TCL_OK) {
+ /*
+ * Not a list.
+ */
+
+ return TCL_ERROR;
+ }
+ if (lstlen > 0) {
+ /*
+ * We are going to be saving this handler. Increment the reference
+ * count before decrementing the refcount on the previous handler,
+ * so that nothing strange can happen if we are told to set the
+ * handler to the previous value.
+ */
+
+ Tcl_IncrRefCount(handlerPtr);
+ }
}
/*
- * If NULL or an empty list is passed, then reset to the default
- * handler.
+ * Remove old handler next.
*/
- if (handlerPtr == NULL) {
- currNsPtr->unknownHandlerPtr = NULL;
- } else if (TclListObjLength(interp, handlerPtr, &lstlen) != TCL_OK) {
- /*
- * Not a list.
- */
+ if (currNsPtr->unknownHandlerPtr != NULL) {
+ Tcl_DecrRefCount(currNsPtr->unknownHandlerPtr);
+ }
- return TCL_ERROR;
- } else if (lstlen == 0) {
+ /*
+ * Install the new handler.
+ */
+
+ if (lstlen > 0) {
/*
- * Empty list - reset to default.
+ * Just store the handler. It already has the correct reference count.
*/
- currNsPtr->unknownHandlerPtr = NULL;
+ currNsPtr->unknownHandlerPtr = handlerPtr;
} else {
/*
- * Increment ref count and store. The reference count is decremented
- * either in the code above, or when the namespace is deleted.
+ * If NULL or an empty list is passed, this resets to the default
+ * handler.
*/
- Tcl_IncrRefCount(handlerPtr);
- currNsPtr->unknownHandlerPtr = handlerPtr;
+ currNsPtr->unknownHandlerPtr = NULL;
}
return TCL_OK;
}