www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - std.stream.BufferedStream has upsizing bug

I want to modify a file "test.img".
The file size is 1.4MB.
But this code expands the file to 4GB.
(dmd 0.144 for Windows)

----
import std.stream;

int main(char[][] args)
{
    Stream fd_img = new BufferedFile("test.img",
        FileMode.In | FileMode.Out);
    fd_img.seekSet(0);
    ubyte buf[1];
    buf[0] = 0x01;
    uint write_size = fd_img.writeBlock(&buf[0], 1);
    fd_img.close();
    return 0;
}
----

Because std.stream.BufferedStream has "uint bufferSourcePos"
and std.stream.Stream has
"abstract ulong seek(long offset, SeekPos whence)".

The problem occurs on follow line.

stream.d(1694)
----
streamPos = s.seek(-bufferSourcePos, SeekPos.Current);
----

D doesn't extend sign on this case.
D treats this as follow.
 -uint -> uint -> long

This is the sample code.
----
import std.stdio;

void func(long lx)
{
    writefln("%d", lx);
}

int main(char[][] args)
{
    uint x = 1;
    func(x);
    func(-x);
    func(1);
    func(-1);
    return 0;
}
----

Result
----
1
4294967295
1
-1
----

So, this is the right code.
----
streamPos = s.seek(-cast(long)(bufferSourcePos), SeekPos.Current);
----

dmd Linux version doesn't have this problem.
Because lseek() recasts (wrong) long to int.
(This means max file size on Linux is 4GB. :( )


This problem has also D's error reporting
 and/or type casting problem.

If D casts -uint to long directly, the problem doesn't occur.
But it requires "result type" at determining function.
Bottom up approach dislike it.

If direct cast is difficult, I want the warning report.
D doesn't warn this now.
I think "-uint -> uint" is right. It's sometime useful.
(Is "-uint -> int or long" better?)
(Is reporting error for "-uint" better?)
"uint -> long" is right.
But I think D should report "warning" on this combined case if D can catch.
(If two operations are separated too far, it is difficult to find probably.)

Thank you for reading my poor english.
Jan 26 2006