Tcl Source Code

View Ticket
Login
Ticket UUID: 1109484
Title: Tcl_Expr* do not gracefully handle wide ints
Type: Bug Version: obsolete: 8.4.9
Submitter: hobbs Created on: 2005-01-25 23:48:10
Subsystem: 10. Objects Assigned To: dkf
Priority: 8 Severity:
Status: Closed Last Modified: 2005-01-28 20:38:58
Resolution: Fixed Closed By: hobbs
    Closed on: 2005-01-28 01:51:16
Description:
The Tcl_Expr* functions in tclBasic.c do checks on the
return value to see if it is int or double, but the
value could be a wide int that fits into the requisite
size.  That would prevent an error condition.  See this
example from TclX:

package require Tclx 8.4
(Tcl) 57 % crange abc 1 {end-[expr 1]}
b
(Tcl) 58 % crange abc 1 {end-[expr wide(1)]}
expression didn't have numeric value
User Comments: dkf added on 2005-01-28 20:38:58:
Logged In: YES 
user_id=79902

Added test (expr-old-37.2) in HEAD.

dgp added on 2005-01-28 11:37:42:
Logged In: YES 
user_id=80530

I see a fix is now in place.

Any chance we can also get some
tests for this in the test suite?

hobbs added on 2005-01-28 08:51:17:

File Added - 117468: 1109484.patch

hobbs added on 2005-01-28 08:51:16:
Logged In: YES 
user_id=72656

Fixed with attached patch in 8.5a3 head and 8.4 branch.

hobbs added on 2005-01-27 08:29:55:
Logged In: YES 
user_id=72656

This patch reportedly fixed an issue someone was having with
TclX, so apparently the problem can creep in in real-life
code.  Any reason not to go with this solution?

hobbs added on 2005-01-26 07:19:48:
Logged In: YES 
user_id=72656

The following is just a teaser patch against core-8-4-branch
that should be used in a few places to fix the issue:

Index: generic/tclBasic.c
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclBasic.c,v
retrieving revision 1.75.2.10
diff -u -r1.75.2.10 tclBasic.c
--- generic/tclBasic.c  29 Sep 2004 19:36:36 -0000     
1.75.2.10
+++ generic/tclBasic.c  26 Jan 2005 00:18:55 -0000
@@ -4144,6 +4144,29 @@
                *ptr = resultPtr->internalRep.longValue;
            } else if (resultPtr->typePtr == &tclDoubleType) {
                *ptr = (long)
resultPtr->internalRep.doubleValue;
+           } else if (resultPtr->typePtr == &tclWideIntType) {
+#ifndef TCL_WIDE_INT_IS_LONG
+               /*
+                * If the object is already a wide integer,
don't convert it.
+                * This code allows for any integer in the
range -ULONG_MAX to
+                * ULONG_MAX to be converted to a long,
ignoring overflow.
+                * The rule preserves existing semantics for
conversion of
+                * integers on input, but avoids inadvertent
demotion of
+                * wide integers to 32-bit ones in the
internal rep.
+                */
+
+               Tcl_WideInt w =
resultPtr->internalRep.wideValue;
+               if (w >= -(Tcl_WideInt)(ULONG_MAX) && w <=
(Tcl_WideInt)(ULONG_MAX)) {
+                   *ptr = Tcl_WideAsLong(w);
+               } else {
+                   Tcl_SetResult(interp,
+                           "integer value too large to
represent as non-long integer",
+                           TCL_STATIC);
+                   result = TCL_ERROR;
+               }
+#else
+               *ptr = resultPtr->internalRep.longValue;
+#endif
            } else {
                Tcl_SetResult(interp,
                        "expression didn't have numeric
value", TCL_STATIC);

Attachments: