diff options
-rw-r--r-- | ChangeLog | 4 | ||||
-rw-r--r-- | generic/tclEvent.c | 55 | ||||
-rw-r--r-- | tests/event.test | 65 |
3 files changed, 109 insertions, 15 deletions
@@ -1,5 +1,9 @@ 2008-03-10 Don Porter <dgp@users.sourceforge.net> + * generic/tclEvent.c (TclDefaultBgErrorHandlerObjCmd): Added error + * tests/event.test (event-5.*): checking to protect against callers + passing invalid return options dictionaries. [Bug 1901113] + * generic/tclBasic.c (ExprAbsFunc): Revised so that the abs() * tests/expr.test: function and the [::tcl::mathfunc::abs] command do not return the value of -0, or equivalent values with diff --git a/generic/tclEvent.c b/generic/tclEvent.c index 4193ade..dc9705d 100644 --- a/generic/tclEvent.c +++ b/generic/tclEvent.c @@ -12,7 +12,7 @@ * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclEvent.c,v 1.79 2008/02/29 20:00:00 dgp Exp $ + * RCS: @(#) $Id: tclEvent.c,v 1.80 2008/03/10 17:54:47 dgp Exp $ */ #include "tclInt.h" @@ -317,30 +317,57 @@ TclDefaultBgErrorHandlerObjCmd( return TCL_ERROR; } - /* Construct the bgerror command */ - TclNewLiteralStringObj(tempObjv[0], "bgerror"); - Tcl_IncrRefCount(tempObjv[0]); - /* - * Determine error message argument. Check the return options in case - * a non-error exception brought us here. + * Check for a valid return options dictionary. */ TclNewLiteralStringObj(keyPtr, "-level"); Tcl_IncrRefCount(keyPtr); Tcl_DictObjGet(NULL, objv[2], keyPtr, &valuePtr); Tcl_DecrRefCount(keyPtr); - Tcl_GetIntFromObj(NULL, valuePtr, &level); + if (valuePtr == NULL) { + Tcl_SetObjResult(interp, Tcl_NewStringObj( + "missing return option \"-level\"", -1)); + return TCL_ERROR; + } + if (Tcl_GetIntFromObj(interp, valuePtr, &level) == TCL_ERROR) { + return TCL_ERROR; + } + TclNewLiteralStringObj(keyPtr, "-code"); + Tcl_IncrRefCount(keyPtr); + Tcl_DictObjGet(NULL, objv[2], keyPtr, &valuePtr); + Tcl_DecrRefCount(keyPtr); + if (valuePtr == NULL) { + Tcl_SetObjResult(interp, Tcl_NewStringObj( + "missing return option \"-code\"", -1)); + return TCL_ERROR; + } + if (Tcl_GetIntFromObj(interp, valuePtr, &code) == TCL_ERROR) { + return TCL_ERROR; + } + if (level != 0) { /* We're handling a TCL_RETURN exception */ code = TCL_RETURN; - } else { - TclNewLiteralStringObj(keyPtr, "-code"); - Tcl_IncrRefCount(keyPtr); - Tcl_DictObjGet(NULL, objv[2], keyPtr, &valuePtr); - Tcl_DecrRefCount(keyPtr); - Tcl_GetIntFromObj(NULL, valuePtr, &code); } + if (code == TCL_OK) { + /* + * Somehow we got to exception handling with no exception. + * (Pass TCL_OK to TclBackgroundException()?) + * Just return without doing anything. + */ + return TCL_OK; + } + + /* Construct the bgerror command */ + TclNewLiteralStringObj(tempObjv[0], "bgerror"); + Tcl_IncrRefCount(tempObjv[0]); + + /* + * Determine error message argument. Check the return options in case + * a non-error exception brought us here. + */ + switch (code) { case TCL_ERROR: tempObjv[1] = objv[1]; diff --git a/tests/event.test b/tests/event.test index 5492140..bdfad16 100644 --- a/tests/event.test +++ b/tests/event.test @@ -9,7 +9,7 @@ # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # -# RCS: @(#) $Id: event.test,v 1.26 2007/12/13 15:26:06 dgp Exp $ +# RCS: @(#) $Id: event.test,v 1.27 2008/03/10 17:54:47 dgp Exp $ package require tcltest 2 namespace import -force ::tcltest::* @@ -205,6 +205,69 @@ test event-5.3 {HandleBgErrors: [Bug 1670155]} -setup { rename demo {} rename trial {} } -result {} +test event-5.3 {Default [interp bgerror] handler} -body { + ::tcl::Bgerror +} -returnCodes error -match glob -result {*msg options*} +test event-5.4 {Default [interp bgerror] handler} -body { + ::tcl::Bgerror {} +} -returnCodes error -match glob -result {*msg options*} +test event-5.5 {Default [interp bgerror] handler} -body { + ::tcl::Bgerror {} {} {} +} -returnCodes error -match glob -result {*msg options*} +test event-5.6 {Default [interp bgerror] handler} -body { + ::tcl::Bgerror {} {} +} -returnCodes error -match glob -result {*-level*} +test event-5.7 {Default [interp bgerror] handler} -body { + ::tcl::Bgerror {} {-level foo} +} -returnCodes error -match glob -result {*expected integer*} +test event-5.8 {Default [interp bgerror] handler} -body { + ::tcl::Bgerror {} {-level 0} +} -returnCodes error -match glob -result {*-code*} +test event-5.9 {Default [interp bgerror] handler} -body { + ::tcl::Bgerror {} {-level 0 -code ok} +} -returnCodes error -match glob -result {*expected integer*} +test event-5.10 {Default [interp bgerror] handler} { + proc bgerror {m} {append ::res $m} + set ::res {} + ::tcl::Bgerror {} {-level 0 -code 0} + rename bgerror {} + set ::res +} {} +test event-5.11 {Default [interp bgerror] handler} { + proc bgerror {m} {append ::res $m} + set ::res {} + ::tcl::Bgerror msg {-level 0 -code 1} + rename bgerror {} + set ::res +} {msg} +test event-5.12 {Default [interp bgerror] handler} { + proc bgerror {m} {append ::res $m} + set ::res {} + ::tcl::Bgerror msg {-level 0 -code 2} + rename bgerror {} + set ::res +} {command returned bad code: 2} +test event-5.13 {Default [interp bgerror] handler} { + proc bgerror {m} {append ::res $m} + set ::res {} + ::tcl::Bgerror msg {-level 0 -code 3} + rename bgerror {} + set ::res +} {invoked "break" outside of a loop} +test event-5.14 {Default [interp bgerror] handler} { + proc bgerror {m} {append ::res $m} + set ::res {} + ::tcl::Bgerror msg {-level 0 -code 4} + rename bgerror {} + set ::res +} {invoked "continue" outside of a loop} +test event-5.15 {Default [interp bgerror] handler} { + proc bgerror {m} {append ::res $m} + set ::res {} + ::tcl::Bgerror msg {-level 0 -code 5} + rename bgerror {} + set ::res +} {command returned bad code: 5} test event-6.1 {BgErrorDeleteProc procedure} { catch {interp delete foo} |