diff options
-rw-r--r-- | ChangeLog | 3 | ||||
-rw-r--r-- | changes | 4 | ||||
-rw-r--r-- | generic/tkGrid.c | 123 | ||||
-rw-r--r-- | tests/grid.test | 53 |
4 files changed, 174 insertions, 9 deletions
@@ -2,6 +2,9 @@ *** 8.4.13 TAGGED FOR RELEASE *** + * generic/tkGrid.c: Fixed handling of out of bounds row or column. + * tests/grid.test: [Bug 1432666] + * changes: Updates for next RC. 2006-04-11 Jeff Hobbs <jeffh@ActiveState.com> @@ -2,7 +2,7 @@ This file summarizes all changes made to Tk since version 1.0 was released on March 13, 1991. Changes that aren't backward compatible are marked specially. -RCS: @(#) $Id: changes,v 1.64.2.37 2006/04/12 15:30:27 dgp Exp $ +RCS: @(#) $Id: changes,v 1.64.2.38 2006/04/12 17:36:25 dgp Exp $ 3/16/91 (bug fix) Modified tkWindow.c to remove Tk's Tcl commands from the interpreter when the main window is deleted (otherwise there will @@ -5929,4 +5929,6 @@ registered applevents (steffen) 2006-04-11 (bug fix)[1212056] fix panic on safe window exit on Windows (hobbs) +2006-04-12 (bug fix)[1432666] grid row/col out of bounds crash (spjuth) + --- Released 8.4.13, April 19, 2006 --- See ChangeLog for details --- diff --git a/generic/tkGrid.c b/generic/tkGrid.c index aade17d..373567d 100644 --- a/generic/tkGrid.c +++ b/generic/tkGrid.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: tkGrid.c,v 1.25.2.4 2006/04/05 19:49:21 hobbs Exp $ + * RCS: @(#) $Id: tkGrid.c,v 1.25.2.5 2006/04/12 17:35:21 dgp Exp $ */ #include "tkInt.h" @@ -289,6 +289,10 @@ static Tcl_Obj *NewQuadObj _ANSI_ARGS_((Tcl_Interp*, int, int, int, int)); static int ResolveConstraints _ANSI_ARGS_((Gridder *gridPtr, int rowOrColumn, int maxOffset)); static void SetGridSize _ANSI_ARGS_((Gridder *gridPtr)); +static int SetSlaveColumn _ANSI_ARGS_((Tcl_Interp *interp, + Gridder *slavePtr, int column, int numCols)); +static int SetSlaveRow _ANSI_ARGS_((Tcl_Interp *interp, + Gridder *slavePtr, int row, int numRows)); static void StickyToString _ANSI_ARGS_((int flags, char *result)); static int StringToSticky _ANSI_ARGS_((char *string)); static void Unlink _ANSI_ARGS_((Gridder *gridPtr)); @@ -2185,6 +2189,86 @@ SetGridSize(masterPtr) } /* + *---------------------------------------------------------------------- + * + * SetSlaveColumn -- + * + * Update column data for a slave, checking that MAX_ELEMENT bound + * is not passed. + * + * Results: + * TCL_ERROR if out of bounds, TCL_OK otherwise + * + * Side effects: + * Slave fields are updated. + * + *---------------------------------------------------------------------- + */ + +static int +SetSlaveColumn( + Tcl_Interp *interp, /* Interp for error message */ + Gridder *slavePtr, /* Slave to be updated */ + int column, /* New column or -1 to be unchanged */ + int numCols) /* New columnspan or -1 to be unchanged */ +{ + int newColumn, newNumCols, lastCol; + + newColumn = (column >= 0) ? column : slavePtr->column; + newNumCols = (numCols >= 1) ? numCols : slavePtr->numCols; + + lastCol = ((newColumn >= 0) ? newColumn : 0) + newNumCols; + if (lastCol >= MAX_ELEMENT) { + Tcl_SetResult(interp, "Column out of bounds", TCL_STATIC); + return TCL_ERROR; + } + + slavePtr->column = newColumn; + slavePtr->numCols = newNumCols; + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * SetSlaveRow -- + * + * Update row data for a slave, checking that MAX_ELEMENT bound + * is not passed. + * + * Results: + * TCL_ERROR if out of bounds, TCL_OK otherwise + * + * Side effects: + * Slave fields are updated. + * + *---------------------------------------------------------------------- + */ + +static int +SetSlaveRow( + Tcl_Interp *interp, /* Interp for error message */ + Gridder *slavePtr, /* Slave to be updated */ + int row, /* New row or -1 to be unchanged */ + int numRows) /* New rowspan or -1 to be unchanged */ +{ + int newRow, newNumRows, lastRow; + + newRow = (row >= 0) ? row : slavePtr->row; + newNumRows = (numRows >= 1) ? numRows : slavePtr->numRows; + + lastRow = ((newRow >= 0) ? newRow : 0) + newNumRows; + if (lastRow >= MAX_ELEMENT) { + Tcl_SetResult(interp, "Row out of bounds", TCL_STATIC); + return TCL_ERROR; + } + + slavePtr->row = newRow; + slavePtr->numRows = newNumRows; + return TCL_OK; +} + +/* *-------------------------------------------------------------- * * CheckSlotData -- @@ -2669,7 +2753,9 @@ ConfigureSlaves(interp, tkwin, objc, objv) "\": must be a non-negative integer", (char *)NULL); return TCL_ERROR; } - slavePtr->column = tmp; + if (SetSlaveColumn(interp, slavePtr, tmp, -1) != TCL_OK) { + return TCL_ERROR; + } } else if (index == CONF_COLUMNSPAN) { if (Tcl_GetIntFromObj(interp, objv[i+1], &tmp) != TCL_OK || tmp <= 0) { @@ -2679,7 +2765,9 @@ ConfigureSlaves(interp, tkwin, objc, objv) "\": must be a positive integer", (char *)NULL); return TCL_ERROR; } - slavePtr->numCols = tmp; + if (SetSlaveColumn(interp, slavePtr, -1, tmp) != TCL_OK) { + return TCL_ERROR; + } } else if (index == CONF_IN) { if (TkGetWindowFromObj(interp, tkwin, objv[i+1], &other) != TCL_OK) { @@ -2735,7 +2823,9 @@ ConfigureSlaves(interp, tkwin, objc, objv) "\": must be a non-negative integer", (char *)NULL); return TCL_ERROR; } - slavePtr->row = tmp; + if (SetSlaveRow(interp, slavePtr, tmp, -1) != TCL_OK) { + return TCL_ERROR; + } } else if (index == CONF_ROWSPAN) { if ((Tcl_GetIntFromObj(interp, objv[i+1], &tmp) != TCL_OK) || tmp <= 0) { @@ -2746,6 +2836,9 @@ ConfigureSlaves(interp, tkwin, objc, objv) return TCL_ERROR; } slavePtr->numRows = tmp; + if (SetSlaveRow(interp, slavePtr, -1, tmp) != TCL_OK) { + return TCL_ERROR; + } } else if (index == CONF_STICKY) { int sticky = StringToSticky(Tcl_GetString(objv[i+1])); if (sticky == -1) { @@ -2826,14 +2919,26 @@ ConfigureSlaves(interp, tkwin, objc, objv) */ if (slavePtr->column == -1) { - slavePtr->column = defaultColumn; + if (SetSlaveColumn(interp, slavePtr, defaultColumn, -1) != TCL_OK) { + return TCL_ERROR; + } + } + if (SetSlaveColumn(interp, slavePtr, -1, + slavePtr->numCols + defaultColumnSpan - 1) != TCL_OK) { + return TCL_ERROR; } - slavePtr->numCols += defaultColumnSpan - 1; if (slavePtr->row == -1) { if (masterPtr->masterDataPtr == NULL) { + if (SetSlaveRow(interp, slavePtr, 0, -1) != TCL_OK) { + return TCL_ERROR; + } slavePtr->row = 0; } else { slavePtr->row = masterPtr->masterDataPtr->rowEnd; + if (SetSlaveRow(interp, slavePtr, + masterPtr->masterDataPtr->rowEnd, -1) != TCL_OK) { + return TCL_ERROR; + } } } defaultColumn += slavePtr->numCols; @@ -2915,7 +3020,11 @@ ConfigureSlaves(interp, tkwin, objc, objv) if (slavePtr->column == lastColumn && slavePtr->row + slavePtr->numRows - 1 == lastRow) { if (slavePtr->numCols <= width) { - slavePtr->numRows++; + + if (SetSlaveRow(interp, slavePtr, -1, + slavePtr->numRows + 1) != TCL_OK) { + return TCL_ERROR; + } match++; j += slavePtr->numCols - 1; lastWindow = Tk_PathName(slavePtr->tkwin); diff --git a/tests/grid.test b/tests/grid.test index 1e07028..ccf2eca 100644 --- a/tests/grid.test +++ b/tests/grid.test @@ -5,7 +5,7 @@ # Copyright (c) 1998-1999 by Scriptics Corporation. # All rights reserved. # -# RCS: @(#) $Id: grid.test,v 1.17.2.2 2006/04/05 19:49:20 hobbs Exp $ +# RCS: @(#) $Id: grid.test,v 1.17.2.3 2006/04/12 17:35:21 dgp Exp $ package require tcltest 2.1 namespace import -force tcltest::configure @@ -713,6 +713,57 @@ test grid-10.33 {column/row configure - invalid indices} { list [catch {grid rowconfigure . {0 1 2} -weight} msg] $msg } {1 {grid rowconfigure: must specify a single element on retrieval}} +test grid-10.37 {column/row configure} { + list [catch {grid columnconfigure . 100000} msg] $msg +} {0 {-minsize 0 -pad 0 -uniform {} -weight 0}} +grid_reset 10.37 + +test grid-10.38 {column/row configure} -body { + # This is a test for bug 1423666 where a column >= 10000 caused + # a crash in layout. The update is needed to reach the layout stage. + # Test different combinations of row/column overflow + frame .f + set res {} + lappend res [catch {grid .f -row 10 -column 9999} msg] $msg ; update + lappend res [catch {grid .f -row 9999 -column 10} msg] $msg ; update + lappend res [catch {grid .f -columnspan 2 -column 9998} msg] $msg ; update + lappend res [catch {grid .f -rowspan 2 -row 9998} msg] $msg ; update + lappend res [catch {grid .f -column 9998 -columnspan 2} msg] $msg ; update + lappend res [catch {grid .f -row 9998 -rowspan 2} msg] $msg ; update + set res +} -cleanup {destroy .f} -result [lrange { + 1 {Column out of bounds} + 1 {Row out of bounds} + 1 {Column out of bounds} + 1 {Row out of bounds} + 1 {Column out of bounds} + 1 {Row out of bounds} +} 0 end] +grid_reset 10.38 + +test grid-10.39 {column/row configure} -body { + # Additional tests for row/column overflow + frame .f + frame .g + set res {} + grid .f -row 9998 -column 0 + lappend res [catch {grid ^ .g} msg] $msg ; update + grid forget .g + lappend res [catch {grid .g} msg] $msg ; update + grid forget .f .g + lappend res [catch {grid .f - -column 9998} msg] $msg ; update + grid forget .f .g + lappend res [catch {eval grid [string repeat " x " 9999] .f} msg] $msg + update + set res +} -cleanup {destroy .f .g} -result [lrange { + 1 {Row out of bounds} + 1 {Row out of bounds} + 1 {Column out of bounds} + 1 {Column out of bounds} +} 0 end] +grid_reset 10.39 + # auto-placement tests test grid-11.1 {default widget placement} { |