#1 2014-05-07 05:18:38

avista
Member
Registered: 2014-01-06
Posts: 63

Bug in StrCommons.StrInt64() function for minimum Int64 value

Using Delphi XE2, 32-bit target:

For the minimum Int64 value of -9223372036854775808, StrInt64() returns an invalid result (however StrInt32 works fine for the minimum 32 bit value):

program StrToInt64Bug;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  SynCommons,
  System.SysUtils;

procedure DoInt32ToStr(Value: Integer);
var
  tmp: array[0..23] of AnsiChar;
  output: array[0..23] of AnsiChar;
  P: PAnsiChar;
  T: PAnsiChar;
  Len: Integer;
begin
  FillChar(tmp, SizeOf(tmp), 0);
  T := @tmp[23];
  P := StrInt32(T, Value);
  Len := T-P;
  FillChar(output, SizeOf(output), 0);
  move(P[0],output[0],Len);
  Writeln;
  Writeln('SynCommons.StrInt32(', Value, ') = ', output);
end;

procedure DoInt64ToStr(Value: Int64);
var
  tmp: array[0..23] of AnsiChar;
  output: array[0..23] of AnsiChar;
  P: PAnsiChar;
  T: PAnsiChar;
  Len: Integer;
begin
  FillChar(tmp, SizeOf(tmp), 0);
  T := @tmp[23];
  P := StrInt64(T, Value);
  Len := T-P;
  FillChar(output, SizeOf(output), 0);
  move(P[0],output[0],Len);
  Writeln;
  Writeln('SynCommons.StrInt64(', Value, ') = ', output);
end;

var
  Value32: Integer;
  Value64: Int64;
begin
  try
    // 32 bit
    Value32 := Low(Integer);
    Writeln('Low(Integer) = ', Value32);
    DoInt32ToStr(Value32);
    Writeln;

    Value32 := Low(Int32)+1;
    Writeln('Low(Int32)+1 = ', Value32);
    DoInt32ToStr(Value32);
    Writeln;

    // 64 bit
    Value64 := Low(Int64);
    Writeln('Low(Int64) = ', Value64);
    DoInt64ToStr(Value64);
    Writeln;

    Value64 := Low(Int64)+1;
    Writeln('Low(Int64)+1 = ', Value64);
    DoInt64ToStr(Value64);
    Writeln;

    Writeln;
    Writeln('Press ENTER to continue...');
    Readln;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.

Last edited by avista (2014-05-07 05:23:01)

Offline

#2 2014-05-07 08:44:24

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,272
Website

Re: Bug in StrCommons.StrInt64() function for minimum Int64 value

AFAIK Int64ToUtf8(-9223372036854775808) just does not compile under Delphi 7.
Sounds more like a compiler bug...
smile

The following tests do pass:

  Check(Int64ToUtf8(-maxInt)='-2147483647');
  Check(Int64ToUtf8(-1)='-1');
  Check(Int64ToUtf8(-9223372036854775807)='-9223372036854775807');

Offline

#3 2014-05-07 15:24:04

avista
Member
Registered: 2014-01-06
Posts: 63

Re: Bug in StrCommons.StrInt64() function for minimum Int64 value

Int64ToUtf8(-9223372036854775808) works under XE2, however I'm using this conversion with text based record serialization, which fails and returns garbage:

procedure DoTestRec;
type
  TTestRec = packed record
    aInt64: Int64;
  end;
const
  __TestRec = 'aInt64 Int64';
var
  Rec: TTestRec;
  Json: RawUTF8;
begin
  TTextWriter.RegisterCustomJSONSerializerFromText(TypeInfo(TTestRec), __TestRec);
  Rec.aInt64 := -9223372036854775808;
  Json := RecordSaveJSON(Rec, TypeInfo(TTestRec));
  Writeln(Json);
end;

{"aInt64":-E'#0'Ü›F'#0'D›E'#0'T˜'#0#0'F'#0'h›ü'#$1A'}

1 more than the minimum value returns the correct JSON:

{"aInt64":-9223372036854775807}

I traced the call to the following routine, which is why I created the small test application in my previous email:

procedure TTextWriter.Add(Value: Int64);
var tmp: array[0..23] of AnsiChar;
    P: PAnsiChar;
    Len: integer;
begin
  if B+24>=BEnd then
    Flush;
{$ifdef CPU64}
  P := StrInt32(@tmp[23],Value); // StrInt32 use PtrInt, i.e. Int64
{$else}
  P := StrInt64(@tmp[23],Value);
{$endif}
  Len := @tmp[23]-P;
  move(P[0],B[1],Len);
  inc(B,Len);
end;

Thanks

Last edited by avista (2014-05-07 15:25:09)

Offline

#4 2014-05-08 08:20:48

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,272
Website

Re: Bug in StrCommons.StrInt64() function for minimum Int64 value

I think we found the problem, and fixed the issue.
See http://synopse.info/fossil/info/9da5910e5c

Thanks for the report!

Offline

#5 2014-05-08 17:15:44

avista
Member
Registered: 2014-01-06
Posts: 63

Re: Bug in StrCommons.StrInt64() function for minimum Int64 value

Thanks, I've confirmed that this fixes the problem. smile

Offline

Board footer

Powered by FluxBB