digitalmars.D.bugs - std.stream.BufferedStream has upsizing bug
- Katsuya Higuchi (74/74) Jan 26 2006 I want to modify a file "test.img".
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








Katsuya Higuchi <bugbearr bugbearr.jp>