Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-devel / 2009-01

Read from memory stream with position before start of file

9 messages · 3 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

C Western

While finding the bug #12897 I found that a memory stream position could be set to before the start of the file without giving an error, and subsequent reads would appear to work (unless the position was so far off an invalid region of memory was read). I found the precise problem by patching TCustomMemoryStream to raise an exception if the position is set before the start of the file. Should an exception be raised in this circumstance, which would make finding bugs easier? Or should the position just be set to 0, which would be more consistent with the behaviour when going beyond the end of the stream?

See attached patch for the sort of thing I am thinking of.

Colin

Reply by email

Michael Van Canneyt
to C Western
C Western wrote 9 lines
While finding the bug #12897 I found that a memory stream position could be set to before the start of the file without giving an error, and subsequent reads would appear to work (unless the position was so far off an invalid region of memory was read). I found the precise problem by patching TCustomMemoryStream to raise an exception if the position is set before the start of the file. Should an exception be raised in this circumstance, which would make finding bugs easier? Or should the position just be set to 0, which would be more consistent with the behaviour when going beyond the end of the stream?

I think that an exception is better. If you set the position to a non-existing position, there is an error in your logic anyway.

Michael.

Reply by email

Paul Ishenin
to Michael Van Canneyt
Michael Van Canneyt wrote 14 lines
> While finding the bug #12897 I found that a memory stream position could > be set to before the start of the file without giving an error, and > subsequent reads would appear to work (unless the position was so far > off an invalid region of memory was read). I found the precise problem > by patching TCustomMemoryStream to raise an exception if the position is > set before the start of the file. Should an exception be raised in this > circumstance, which would make finding bugs easier? Or should the > position just be set to 0, which would be more consistent with the > behaviour when going beyond the end of the stream? > I think that an exception is better. If you set the position to a non-existing position, there is an error in your logic anyway.

Just tested with delphi

procedure TForm1.Button1Click(Sender: TObject);
var
  S: TMemoryStream;
begin
  S := TMemoryStream.Create;
  S.Position := 10;
  ShowMessage(IntToStr(S.Position));
  S.Position := -1;
  ShowMessage(IntToStr(S.Position));
  S.Free;
end;

It shows 10 and -1.

If you do an exception or silent change of position it can cause incompatibilities. Maybe read operation must be fixed to ignore positions out of the range 0..Size -1?

Best regards,
Paul Ishenin.

Reply by email

Michael Van Canneyt
to Paul Ishenin
Paul Ishenin wrote 35 lines
Michael Van Canneyt wrote: > > While finding the bug #12897 I found that a memory stream position could > > be set to before the start of the file without giving an error, and > > subsequent reads would appear to work (unless the position was so far > > off an invalid region of memory was read). I found the precise problem > > by patching TCustomMemoryStream to raise an exception if the position is > > set before the start of the file. Should an exception be raised in this > > circumstance, which would make finding bugs easier? Or should the > > position just be set to 0, which would be more consistent with the > > behaviour when going beyond the end of the stream? > > > > I think that an exception is better. If you set the position to a > non-existing > position, there is an error in your logic anyway. > Just tested with delphi procedure TForm1.Button1Click(Sender: TObject); var S: TMemoryStream; begin S := TMemoryStream.Create; S.Position := 10; ShowMessage(IntToStr(S.Position)); S.Position := -1; ShowMessage(IntToStr(S.Position)); S.Free; end; It shows 10 and -1. If you do an exception or silent change of position it can cause incompatibilities. Maybe read operation must be fixed to ignore positions out of the range 0..Size -1?

What does Delphi do in such a case ?

Michael.

Reply by email

C Western
to Michael Van Canneyt
Michael Van Canneyt wrote 45 lines
On Thu, 1 Jan 2009, Paul Ishenin wrote: > Michael Van Canneyt wrote: > >>> While finding the bug #12897 I found that a memory stream position could >>> be set to before the start of the file without giving an error, and >>> subsequent reads would appear to work (unless the position was so far >>> off an invalid region of memory was read). I found the precise problem >>> by patching TCustomMemoryStream to raise an exception if the position is >>> set before the start of the file. Should an exception be raised in this >>> circumstance, which would make finding bugs easier? Or should the >>> position just be set to 0, which would be more consistent with the >>> behaviour when going beyond the end of the stream? >>> >>> >> I think that an exception is better. If you set the position to a >> non-existing >> position, there is an error in your logic anyway. >> >> > Just tested with delphi > > procedure TForm1.Button1Click(Sender: TObject); > var > S: TMemoryStream; > begin > S := TMemoryStream.Create; > S.Position := 10; > ShowMessage(IntToStr(S.Position)); > S.Position := -1; > ShowMessage(IntToStr(S.Position)); > S.Free; > end; > > It shows 10 and -1. > > If you do an exception or silent change of position it can cause > incompatibilities. Maybe read operation must be fixed to ignore positions out > of the range 0..Size -1? > What does Delphi do in such a case ?

Delphi reads and writes silently do nothing for position < 0, though I would prefer an exception.

Colin

Reply by email

Paul Ishenin
to Michael Van Canneyt: What does Delphi do in such a case ? Michael.
Michael Van Canneyt wrote 7 lines
> If you do an exception or silent change of position it can cause > incompatibilities. Maybe read operation must be fixed to ignore positions out > of the range 0..Size -1? > What does Delphi do in such a case ?

Tested so:

procedure TForm1.Button1Click(Sender: TObject);
var
  S: TMemoryStream;
  B: Byte;
  Count: Integer;
begin
  S := TMemoryStream.Create;
  B := 1;
  S.Write(B, SizeOf(B));
  S.Position := -1;
  Count := S.Read(B, SizeOf(B));
  ShowMessage(IntToStr(Count));
  S.Free;
end;

Count = 0. IOW, delphi does not read if position < 0

Best regards,
Paul Ishenin.

Reply by email

Michael Van Canneyt
to Paul Ishenin
Paul Ishenin wrote 27 lines
Michael Van Canneyt wrote: > > If you do an exception or silent change of position it can cause > > incompatibilities. Maybe read operation must be fixed to ignore positions > > out > > of the range 0..Size -1? > > > > What does Delphi do in such a case ? > Tested so: procedure TForm1.Button1Click(Sender: TObject); var S: TMemoryStream; B: Byte; Count: Integer; begin S := TMemoryStream.Create; B := 1; S.Write(B, SizeOf(B)); S.Position := -1; Count := S.Read(B, SizeOf(B)); ShowMessage(IntToStr(Count)); S.Free; end; Count = 0. IOW, delphi does not read if position < 0

And writing ?

Michael.

Reply by email

Paul Ishenin
to Michael Van Canneyt
Michael Van Canneyt wrote
And writing ?

Silently do nothing:

procedure TForm4.Button1Click(Sender: TObject);
var
  S: TMemoryStream;
  B: Byte;
  Count: Integer;
begin
  S := TMemoryStream.Create;
  S.Position := -1;
  B := 1;
  S.Write(B, SizeOf(B));
  ShowMessage(IntToStr(S.Size));
  S.Free;
end;

it shows 0

Best regards,
Paul Ishenin.

Reply by email

C Western
to Paul Ishenin
Paul Ishenin wrote 23 lines
Michael Van Canneyt wrote: > And writing ? > Silently do nothing: procedure TForm4.Button1Click(Sender: TObject); var S: TMemoryStream; B: Byte; Count: Integer; begin S := TMemoryStream.Create; S.Position := -1; B := 1; S.Write(B, SizeOf(B)); ShowMessage(IntToStr(S.Size)); S.Free; end; it shows 0 Best regards, Paul Ishenin.

I have submitted a patch:

<http://bugs.freepascal.org/view.php?id=13318>

Colin

Reply by email