diff options
| -rw-r--r-- | generic/tclCompCmdsGR.c | 11 | ||||
| -rw-r--r-- | tests/incr.test | 56 |
2 files changed, 65 insertions, 2 deletions
diff --git a/generic/tclCompCmdsGR.c b/generic/tclCompCmdsGR.c index 7efe6ae..8143c9e 100644 --- a/generic/tclCompCmdsGR.c +++ b/generic/tclCompCmdsGR.c @@ -507,10 +507,17 @@ TclCompileIncrCmd( Tcl_IncrRefCount(intObj); code = TclGetIntFromObj(NULL, intObj, &immValue); - TclDecrRefCount(intObj); - if ((code == TCL_OK) && (-127 <= immValue) && (immValue <= 127)) { + if ( (code == TCL_OK) + && (-127 <= immValue) && (immValue <= 127) + /* avoid overflow during string to int conversion (wide 0xFFFFFFFF to signed int -1): */ + && ( (immValue >= 0) + || (intObj->typePtr != &tclWideIntType) + || ((-127 <= intObj->internalRep.wideValue) && (intObj->internalRep.wideValue <= 127)) + ) + ) { haveImmValue = 1; } + TclDecrRefCount(intObj); if (!haveImmValue) { PushLiteral(envPtr, word, numBytes); } diff --git a/tests/incr.test b/tests/incr.test index af15f5e..ff328b7 100644 --- a/tests/incr.test +++ b/tests/incr.test @@ -236,6 +236,62 @@ test incr-1.30 {TclCompileIncrCmd: array var, braced (no subs)} -setup { incr {array($foo)} } -result 5 +test incr-1.31 {no overflow in TclCompileIncrCmd and Tcl_IncrObjCmd, bug [7179c6724cd38271]} { + # TclCompileIncrCmd: compiled incr TEBC with immutable constant offs (INST_INCR_*_IMM instructions): + lappend res [set i 0; incr i 0x7FFFFFFF] + lappend res [set i 0; incr i 0xFFFFFF80] + lappend res [set i 0; incr i 0xFFFFFF81] + lappend res [set i 0; incr i 0xFFFFFFFF] + lappend res [set i 0; incr i 0x10000007F] + lappend res [set i 0; incr i 0x100000080] + lappend res [set i 0; incr i 0x7FFFFFFFFFFFFFFF] + lappend res [set i 0; incr i 0xFFFFFFFFFFFFFF80] + lappend res [set i 0; incr i 0xFFFFFFFFFFFFFF81] + lappend res [set i 0; incr i 0xFFFFFFFFFFFFFFFF] + lappend res [set i 0; incr i 0x1000000000000007F] + lappend res [set i 0; incr i 0x10000000000000080] + # TclCompileIncrCmd: compiled incr TEBC with dynamic offs (INST_INCR_* instructions without _IMM): + lappend res [set i 0; incr i [set x 0x7FFFFFFF]] + lappend res [set i 0; incr i [set x 0xFFFFFF80]] + lappend res [set i 0; incr i [set x 0xFFFFFF81]] + lappend res [set i 0; incr i [set x 0xFFFFFFFF]] + lappend res [set i 0; incr i [set x 0x10000007F]] + lappend res [set i 0; incr i [set x 0x100000080]] + lappend res [set i 0; incr i [set x 0x7FFFFFFFFFFFFFFF]] + lappend res [set i 0; incr i [set x 0xFFFFFFFFFFFFFF80]] + lappend res [set i 0; incr i [set x 0xFFFFFFFFFFFFFF81]] + lappend res [set i 0; incr i [set x 0xFFFFFFFFFFFFFFFF]] + lappend res [set i 0; incr i [set x 0x1000000000000007F]] + lappend res [set i 0; incr i [set x 0x10000000000000080]] + # Tcl_IncrObjCmd: non-compiled incr command (or NRE): + set cmd incr + lappend res [set i 0; $cmd i 0x7FFFFFFF] + lappend res [set i 0; $cmd i 0xFFFFFF80] + lappend res [set i 0; $cmd i 0xFFFFFF81] + lappend res [set i 0; $cmd i 0xFFFFFFFF] + lappend res [set i 0; $cmd i 0x10000007F] + lappend res [set i 0; $cmd i 0x100000080] + lappend res [set i 0; $cmd i 0x7FFFFFFFFFFFFFFF] + lappend res [set i 0; $cmd i 0xFFFFFFFFFFFFFF80] + lappend res [set i 0; $cmd i 0xFFFFFFFFFFFFFF81] + lappend res [set i 0; $cmd i 0xFFFFFFFFFFFFFFFF] + lappend res [set i 0; $cmd i 0x1000000000000007F] + lappend res [set i 0; $cmd i 0x10000000000000080] +} [lrepeat 3 \ + [expr 0x7FFFFFFF] \ + [expr 0xFFFFFF80] \ + [expr 0xFFFFFF81] \ + [expr 0xFFFFFFFF] \ + [expr 0x10000007F] \ + [expr 0x100000080] \ + [expr 0x7FFFFFFFFFFFFFFF] \ + [expr 0xFFFFFFFFFFFFFF80] \ + [expr 0xFFFFFFFFFFFFFF81] \ + [expr 0xFFFFFFFFFFFFFFFF] \ + [expr 0x1000000000000007F] \ + [expr 0x10000000000000080] \ +] + # Check "incr" and computed command names. unset -nocomplain x i |
