summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog4
-rw-r--r--generic/tclEvent.c55
-rw-r--r--tests/event.test65
3 files changed, 109 insertions, 15 deletions
diff --git a/ChangeLog b/ChangeLog
index b3a0b94..e5292f1 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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}