[fpc-devel] Overflow in TMemoryStream?

Michael Van Canneyt michael at freepascal.org
Mon Sep 12 10:38:27 CEST 2016



On Sun, 11 Sep 2016, Martok wrote:

> Hi,
>
> yes, I can confirm this as an overflow, but on its own, it should be safe. Above
> 430MB, the stream doesn't grow by a quarter but just by however much was
> requested, luckily the branch fails before the wrong capacity could be set.
>
> Test:
> type
>  TMS2 = class(TMemoryStream) end;
> var
>  ms: TMS2;
>  ds: Int64;
> begin
>  ds:= 100*1000*1000;
>  ms:= TMS2.Create;
>  ms.SetSize(ds);
>  WriteLn(ds:15,' ', ms.Size:15, ' ', ms.Capacity:15);
>  inc(ds, ds div 10); // grow by less than 25%
>  ms.SetSize(ds);
>  WriteLn(ds:15,' ', ms.Size:15, ' ', ms.Capacity:15);
> end.
>
> with ds=100M, prints:
>      100000000       100000000       100003840
>      110000000       110000000       125005824    << grew by 1/4*100M
>
> with ds=500M, prints:
>      500000000       500000000       500002816
>      550000000       550000000       550002688    << bug, grew by 1/10*500M

Output on linux 64-bit

cadwal: >tms
       100000000       100000000       100003840
       110000000       110000000       125005824
cadwal: >tms
       500000000       500000000       500002816
       550000000       550000000       625004544 This is 1/4
cadwal: >tms
       869000000       869000000       869003264
       955900000       955900000      1086255104

So it looks like a 32 vs. 64 bit issue.

from the method Realloc :

         NewCapacity := (5*FCapacity) div 4;  // 5*FCapacity can cause overflow

Changing this to
    NewCapacity:=FCapacity + (FCapacity div 4)

Will probably fix the issue.

Michael.



More information about the fpc-devel mailing list