Ticket UUID: | 219223 | |||
Title: | 64 bit format command behaves differently to the 32bit forma | |||
Type: | Bug | Version: | obsolete: 8.3b2 | |
Submitter: | nobody | Created on: | 2000-10-26 05:03:48 | |
Subsystem: | 16. Commands A-H | Assigned To: | dkf | |
Priority: | 7 High | Severity: | ||
Status: | Closed | Last Modified: | 2002-02-19 17:45:56 | |
Resolution: | Fixed | Closed By: | dkf | |
Closed on: | 2002-02-19 10:45:56 | |||
Description: |
OriginalBugID: 4087 Bug Version: 8.3b2 SubmitDate: '2000-01-26' LastModified: '2000-04-09' Severity: SER Status: Assigned Submitter: techsupp ChangedBy: hobbs RelatedBugIDs: 653 OS: Solaris OSVersion: Solaris 7 64 bit Machine: Ultra Enterprise 4500 FixedDate: '2000-10-25' ClosedDate: '2000-10-25' Name: Matthew Finch ReproducibleScript: If I compile tcl8.3b2 in 64 bit mode on Solaris 7 using -xarch=v9 then perform the following I get.... # ./tclsh % format %X 4294967290 integer value too large to represent as non-long integer % If I compile tcl8.3b2 in 32 bit mode on Solaris 7 then perform the following I get... # ./tclsh % format %X 4294967290 FFFFFFFA % The problem is relates to the casting in Tcl_GetIntFromObj() if (((long)((int)l)) == l) { *intPtr = (int)objPtr->internalRep.longValue; return TCL_OK; } The results should be the same. ObservedBehavior: If I compile tcl8.3b2 in 64 bit mode on Solaris 7 using -xarch=v9 then perform the following I get.... # ./tclsh % format %X 4294967290 integer value too large to represent as non-long integer % DesiredBehavior: I expect to see the same behaviour as when I compiled tclsh on Solaris 7 in 32 bit mode e.g # ./tclsh % format %X 4294967290 FFFFFFFA % Actually, there is some level of correctness here. The number the user is using is just -6 as far as Tcl is concerned on a 32bit system. When there are true longs, then Tcl handles the number properly in certain contexts. However, format currently isn't one of them. This should be revisited in 8.4 to look at expanding the use of Tcl_GetLongFromObj, which would solve the problem here. We just need to make sure it won't confuse something else down the chain that will choke on the long value. -- 04/09/2000 hobbs | |||
User Comments: |
dkf added on 2002-02-19 17:45:56:
Logged In: YES user_id=79902 OK, so I'll make the code always work with longs on 64-bit platforms, and the 'l' modifier will have no effect there. This seems to be what the test suite expects (that %d works with long) so I'll make that the defined behaviour everywhere. kennykb added on 2002-02-19 06:04:55: Logged In: YES user_id=99768 dgp says that sizeof(int) == 4, while sizeof(long) == sizeof(void*) == 8. UINT_MAX is 0xffffffff. The problem is that 0xfffffffa < UINT_MAX. The test at line 2108 of tclCmdAH.c reads: if ((unsigned long) intValue > UINT_MAX) This test detects that 0xfffffffa can be formatted with %d instead of %ld. It cannot. In any case, the code at line 2211: sprintf(dst, newFormat, intValue); is surely not correct. The case that we're testing here gets there with "%d" in newFormat, but "intValue" is a long: that surely cannot be expected to work! dkf added on 2002-02-18 21:02:32: Logged In: YES user_id=79902 What is UINT_MAX on Linux/Alpha? I suspect even more strongly that the problem is that that is that sizeof(int)==sizeof(long), and since that's the case, bodging in a fix is easy; the hard bit will be ensuring that it doesn't cause masses of warnings, and stopping people who think they know what they are doing from fiddling with it. dkf added on 2002-02-18 20:51:55: Logged In: YES user_id=79902 Hmm. Can't duplicate the behaviour on Solaris/SPARC at all... dkf added on 2002-02-18 17:25:43: Logged In: YES user_id=79902 Drat, missed a change in a manpage! Don't know what's up on 64-bit Linux-Alpha, but the problem might be that 'int' is 64 bits wide there (fuzzy memory or hearsay.) Will need to see if I can duplicate on 64-bit Solaris-SPARC... dgp added on 2002-02-16 05:03:48: Logged In: YES user_id=80530 No. There are still problems here. As noted before, we need documentation so folks are not surprised by this: % format %d 4294967290 -6 Make it explicit that signed 32-bit values are used unless the 'l' modifier is added: % format %ld 4294967290 4294967290 Also in format.n, point [3] of the last section says that the 'l' modifier is ignored. That is clearly no longer true. Getting to the actual bug, on a 64-bit Linux-Alpha: % format %d 4294967290 -6 % format %ld 4294967290 -6 so things are not consistent. I think the intent of TIP 72 was that there be consistent results on 32- and 64-bit platforms. dkf added on 2002-02-16 04:24:01: Logged In: YES user_id=79902 Is this fixed now? I *think* so, but I'm not sure... dkf added on 2001-09-21 16:17:05: Logged In: YES user_id=79902 This was why I'd not changed it previously. This issue will need resolving as part of the 32/64 cleanup... dgp added on 2001-09-20 23:36:54: Logged In: YES user_id=80530 OK, commits to both HEAD and core-8-3-1-branch on 2001-09-19 have fixed this, sort of. The reported error is corrected: % format %X 4294967290 FFFFFFFA works on both 32-bit and 64-bit platforms. However, the change also has this effect: % format %d 4294967290 -6 on *both* 32-bit and 64-bit platforms. If this behavior is to be kept, then we need to document in the format(n) page that %d formatting as a signed decimal string places its sign boundary at the range of a signed 32-bit integer. andreas_kupries added on 2001-08-21 00:44:45: Logged In: YES user_id=75003 There are two errors in Tcllib modules which seem to result from the problem reported here: http://sourceforge.net/tracker/index.php? func=detail&aid=446997&group_id=12883&atid=112883 http://sourceforge.net/tracker/index.php? func=detail&aid=447037&group_id=12883&atid=112883 dgp added on 2001-03-22 07:32:19: Logged In: YES user_id=80530 I confirm that this patch adds the ability to avoid this bug. It does so by adding new features, though, so perhaps a short TIP is in order. I'm troubled by the non-Portability of test format-1.13. Neither of these results really makes sense to me: # 32-bit platform: % format %d 4294967290 -6 # 64-bit platform: % format %d 4294967290 integer value too large to represent as non-long integer I understand what's going on, but why should the Tcl script level claim that -6 == 4294967290 anywhere? And if it claims such nonsense anywhere, why not everywhere? What I see above is the very platforms which *can* handle the integer value 4294967290 are refusing to do so and throwing an error instead, and those that *can't* are silently converting it into -6 without throwing an error. I suppose if we open the topic up a bit to a discussion of how Tcl ought to be handling integer values at the script level, then a TIP is definitely in order. dkf added on 2001-03-19 20:07:35: Logged In: YES user_id=79902 Please review... dkf added on 2001-03-19 20:06:49: File Added - 4393: format64.patch dkf added on 2001-03-19 20:06:48: Logged In: YES user_id=79902 Trying to upload a patch to fix this... dkf added on 2001-03-19 18:09:26: Logged In: YES user_id=79902 I am developing a patch that fixes this by allowing the use of the 'l' specifier in format and scan. kennykb added on 2000-12-12 00:34:28: Patch #102663 (quite inadvertently) updates the Tcl test suite with a regression test for this problem. There was a bug on 32-bit platforms as well: negative integers [format]ted with %x or %o could not be recovered by [scan]ning them with %x or %o. The [scan] would not return an error but would silently replace them with MAX_INT. The fix for this bug includes a test case that tries to do complementary [format] and [scan] of -1, MAX_INT, and MIN_INT; this test case fails on 64-bit platforms because it trips over this issue with [format]. |
Attachments:
- format64.patch [download] added by dkf on 2001-03-19 20:06:49. [details]