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