#4004 8.5.2 "tell" returns neg 32-bit value for positions > 2GB

obsolete: 8.5.2
closed-accepted
9
2008-05-23
2008-05-17
Anonymous
No

Tcl "tell" command returned 64-bit unsigned values starting in 8.4 for use in managing files >2GB.

Tcl "tell" command in 8.5.2 seems to be returning a signed value which appears "negative" and unsuitable for use in Tcl "seek" command for file positions > 2GB.

Platform: XP-SP2, builds built locally with VC++ 2008 Express, also the distributed Equi4 "tclkit" for 8.5.2 produce this output:

(2008) 3 % set tcl_patchLevel
8.5.2
(2008) 4 % set fn "whopper.bin"
whopper.bin
(2008) 5 % file stat $fn s
(2008) 6 % set s(size)
3974747277
(2008) 7 % set f [open $fn "rb"]
fileb54c58
(2008) 8 % seek $f 2147016079
(2008) 9 % tell $f
2147016079
(2008) 10 % read $f 1000000 ; set x
can't read "x": no such variable
(2008) 11 % tell $f
-2146951217
(2008) 12 % seek $f 3974747000
(2008) 13 % tell $f
-320220296

By comparison (same platform):
(2008) 11 % set tcl_patchLevel
8.4.4
(2008) 12 % set fn "whopper.bin"
whopper.bin
(2008) 13 % file stat $fn s
(2008) 14 % set s(size)
3974747277
(2008) 15 % set f [open $fn "r"] ; fconfigure $f -translation binary
(2008) 16 % set f
file9bd888
(2008) 17 % seek $f 2147016079
(2008) 18 % tell $f
2147016079
(2008) 19 % read $f 1000000 ; set x
can't read "x": no such variable
(2008) 20 % tell $f
2148016079
(2008) 21 % seek $f 3974747000
(2008) 22 % tell $f
3974747000
(2008) 23 %

David Burns : consollidator<AT>yahoo.com

Discussion

    • labels: 105659 --> 24. Channel Commands
    • priority: 5 --> 7
    • assigned_to: dkf --> andreas_kupries
     
  • Logged In: YES
    user_id=496139
    Originator: NO

    Found and fixed (attached patch).
    The problem is the sign-extending int32->int64 conversion Tcl_LongAsWide, done on the low-order part of the tell value, which is a signed int32. To circumvent this I have replaced the use of the Tcl_LongAsWide macro by the more explicit cast:

    ((Tcl_WideInt)((unsigned)value))

    Test suite passed.
    This should work on 64-bit Windows, though I have now way to check.
    Also notice that generating a test case is not easy since a file slightly over 2G is neede :-(

    File Added: wideseek.patch

     
  • correction for bad long->wide conversion

     
    Attachments
  • correction for bad long->wide conversion

     
    Attachments
  • Logged In: YES
    user_id=496139
    Originator: NO

    Found and fixed (attached patch).
    The problem is the sign-extending int32->int64 conversion Tcl_LongAsWide, done on the low-order part of the tell value, which is a signed int32. To circumvent this I have replaced the use of the Tcl_LongAsWide macro by the more explicit cast:

    ((Tcl_WideInt)((unsigned)value))

    Test suite passed.
    This should work on 64-bit Windows, though I have now way to check.
    Also notice that generating a test case is not easy since a file slightly over 2G is neede :-(

    File Added: wideseek.patch

     
    • priority: 7 --> 9
     
    • status: open --> closed-accepted
     
  • Logged In: YES
    user_id=75003
    Originator: NO

    Committed to Tcl 8.4 branch.
    Committed to Tcl 8.5 branch.
    Committed to Tcl Head branch.