From c19c3f2d6de6320a78e1a5fc90c832a6247f8f9c Mon Sep 17 00:00:00 2001 From: nijtmans Date: Mon, 17 Jan 2011 12:34:43 +0000 Subject: [Bug 3148192]: Commands "read/puts" incorrectly interpret parameters. Improved error-message regarding legacy form. --- ChangeLog | 4 ++++ generic/tclIOCmd.c | 50 +++++++++++++++++++++++--------------------------- tests/chanio.test | 4 ++-- tests/io.test | 4 ++-- tests/ioCmd.test | 8 ++++---- 5 files changed, 35 insertions(+), 35 deletions(-) diff --git a/ChangeLog b/ChangeLog index 63329fb..7e44c77 100644 --- a/ChangeLog +++ b/ChangeLog @@ -3,6 +3,10 @@ * win/tcl.m4: handle --enable-64bit=ia64 for gcc. BACKPORT. * win/configure: (autoconf-2.59) * win/tclWin32Dll.c: [Patch 3059922]: fixes for mingw64 - gcc4.5.1 + * generic/tclIOCmd.c: [Bug 3148192]: Commands "read/puts" incorrectly + * tests/chanio.test: interpret parameters. Improved error-message + * tests/io.test regarding legacy form. + * tests/ioCmd.test 2011-01-15 Kevin B. Kenny diff --git a/generic/tclIOCmd.c b/generic/tclIOCmd.c index dce8ed7..3827b8e 100644 --- a/generic/tclIOCmd.c +++ b/generic/tclIOCmd.c @@ -8,7 +8,7 @@ * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclIOCmd.c,v 1.51.2.3 2010/02/11 15:25:25 dkf Exp $ + * RCS: @(#) $Id: tclIOCmd.c,v 1.51.2.4 2011/01/17 12:34:44 nijtmans Exp $ */ #include "tclInt.h" @@ -135,32 +135,24 @@ Tcl_PutsObjCmd( break; case 4: /* [puts -nonewline $chan $x] or [puts $chan $x nonewline] */ + newline = 0; if (strcmp(TclGetString(objv[1]), "-nonewline") == 0) { chanObjPtr = objv[2]; string = objv[3]; - } else { + break; + } else if (strcmp(TclGetString(objv[2]), "nonewline") == 0) { /* * The code below provides backwards compatibility with an old * form of the command that is no longer recommended or - * documented. + * documented. See also [Bug #3151675]. Will be removed in Tcl 9, + * maybe even earlier. */ - char *arg; - int length; - - arg = TclGetStringFromObj(objv[3], &length); - if ((length != 9) - || (strncmp(arg, "nonewline", (size_t) length) != 0)) { - Tcl_AppendResult(interp, "bad argument \"", arg, - "\": should be \"nonewline\"", NULL); - return TCL_ERROR; - } chanObjPtr = objv[1]; string = objv[2]; + break; } - newline = 0; - break; - + /* Fall through */ default: /* [puts] or [puts some bad number of arguments...] */ Tcl_WrongNumArgs(interp, 1, objv, "?-nonewline? ?channelId? string"); @@ -429,24 +421,28 @@ Tcl_ReadObjCmd( i++; /* Consumed channel name. */ /* - * Compute how many bytes to read, and see whether the final newline - * should be dropped. + * Compute how many bytes to read. */ toRead = -1; if (i < objc) { - char *arg; + if (TclGetIntFromObj(interp, objv[i], &toRead) != TCL_OK) { + /* + * The code below provides backwards compatibility with an old + * form of the command that is no longer recommended or + * documented. See also [Bug #3151675]. Will be removed in Tcl 9, + * maybe even earlier. + */ - arg = TclGetString(objv[i]); - if (isdigit(UCHAR(arg[0]))) { /* INTL: digit */ - if (TclGetIntFromObj(interp, objv[i], &toRead) != TCL_OK) { - return TCL_ERROR; + if (strcmp(TclGetString(objv[i]), "nonewline") != 0) { + return TCL_ERROR; } - } else if (strcmp(arg, "nonewline") == 0) { newline = 1; - } else { - Tcl_AppendResult(interp, "bad argument \"", arg, - "\": should be \"nonewline\"", NULL); + } else if (toRead < 0) { + Tcl_ResetResult(interp); + Tcl_AppendResult(interp, "expected non-negative integer but got \"", + TclGetString(objv[i]), "\"", NULL); + Tcl_SetErrorCode(interp, "TCL", "VALUE", "NUMBER", NULL); return TCL_ERROR; } } diff --git a/tests/chanio.test b/tests/chanio.test index ce87e94..bcd24fe 100644 --- a/tests/chanio.test +++ b/tests/chanio.test @@ -13,7 +13,7 @@ # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # -# RCS: @(#) $Id: chanio.test,v 1.3.2.11 2008/06/20 19:23:26 dgp Exp $ +# RCS: @(#) $Id: chanio.test,v 1.3.2.12 2011/01/17 12:34:43 nijtmans Exp $ if {[catch {package require tcltest 2}]} { chan puts stderr "Skipping tests in [info script]. tcltest 2 required." @@ -3858,7 +3858,7 @@ test chan-io-32.3 {Tcl_Read, negative byte count} { set l [list [catch {chan read $f -1} msg] $msg] chan close $f set l -} {1 {bad argument "-1": should be "nonewline"}} +} {1 {expected non-negative integer but got "-1"}} test chan-io-32.4 {Tcl_Read, positive byte count} { set f [open $path(longfile) r] set x [chan read $f 1024] diff --git a/tests/io.test b/tests/io.test index 5449a0d..a96105d 100644 --- a/tests/io.test +++ b/tests/io.test @@ -13,7 +13,7 @@ # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # -# RCS: @(#) $Id: io.test,v 1.80.2.15 2010/12/10 17:16:08 ferrieux Exp $ +# RCS: @(#) $Id: io.test,v 1.80.2.16 2011/01/17 12:34:43 nijtmans Exp $ if {[catch {package require tcltest 2}]} { puts stderr "Skipping tests in [info script]. tcltest 2 required." @@ -3858,7 +3858,7 @@ test io-32.3 {Tcl_Read, negative byte count} { set l [list [catch {read $f -1} msg] $msg] close $f set l -} {1 {bad argument "-1": should be "nonewline"}} +} {1 {expected non-negative integer but got "-1"}} test io-32.4 {Tcl_Read, positive byte count} { set f [open $path(longfile) r] set x [read $f 1024] diff --git a/tests/ioCmd.test b/tests/ioCmd.test index 6bdc827..3d776dc 100644 --- a/tests/ioCmd.test +++ b/tests/ioCmd.test @@ -13,7 +13,7 @@ # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # -# RCS: @(#) $Id: ioCmd.test,v 1.36.2.10 2010/11/30 20:59:28 andreas_kupries Exp $ +# RCS: @(#) $Id: ioCmd.test,v 1.36.2.11 2011/01/17 12:34:43 nijtmans Exp $ if {[lsearch [namespace children] ::tcltest] == -1} { package require tcltest 2 @@ -35,7 +35,7 @@ test iocmd-1.2 {puts command} { } {1 {wrong # args: should be "puts ?-nonewline? ?channelId? string"}} test iocmd-1.3 {puts command} { list [catch {puts froboz -nonewline kablooie} msg] $msg -} {1 {bad argument "kablooie": should be "nonewline"}} +} {1 {wrong # args: should be "puts ?-nonewline? ?channelId? string"}} test iocmd-1.4 {puts command} { list [catch {puts froboz hello} msg] $msg } {1 {can not find channel named "froboz"}} @@ -138,7 +138,7 @@ test iocmd-4.8 {read command with incorrect combination of arguments} { } {1 {wrong # args: should be "read channelId ?numChars?" or "read ?-nonewline? channelId"} NONE} test iocmd-4.9 {read command} { list [catch {read stdin foo} msg] $msg $::errorCode -} {1 {bad argument "foo": should be "nonewline"} NONE} +} {1 {expected integer but got "foo"} {TCL VALUE NUMBER}} test iocmd-4.10 {read command} { list [catch {read file107} msg] $msg $::errorCode } {1 {can not find channel named "file107"} {TCL LOOKUP CHANNEL file107}} @@ -1942,7 +1942,7 @@ test iocmd-32.1 {origin interpreter of moved channel destroyed during access} -m proc foo {args} { oninit; onfinal; track; # destroy interpreter during channel access - # Actually not possible for an interp to destory itself. + # Actually not possible for an interp to destroy itself. interp delete {} return} set chan [chan create {r w} foo] -- cgit v0.12