Skip to content

Commit 24e4291

Browse files
author
Arnaud Bouchez
committed
core: fixed GetExtended() 64-bit integer overflow
1 parent 7795c5a commit 24e4291

File tree

3 files changed

+22
-6
lines changed

3 files changed

+22
-6
lines changed

src/core/mormot.core.base.pas

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6380,12 +6380,15 @@ function GetExtended(P: PUtf8Char; out err: integer): TSynExtended;
63806380
c := P^;
63816381
include(flags, fNeg);
63826382
end;
6383-
remdigit := 19; // max Int64 resolution
6383+
remdigit := 18; // v64=-9,223,372,036,854,775,808..+9,223,372,036,854,775,807
63846384
repeat
63856385
inc(P);
63866386
if (c >= '0') and
63876387
(c <= '9') then
63886388
begin
6389+
if remdigit = 0 then
6390+
if v64 < 922337203685477580 then // avoid 64-bit overflow
6391+
inc(remdigit); // but allow up to 19 digits if possible
63896392
dec(remdigit);
63906393
if remdigit >= 0 then // over-required digits are just ignored
63916394
begin

src/mormot.commit.inc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
'2.3.9531'
1+
'2.3.9532'

test/test.core.base.pas

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4203,11 +4203,11 @@ procedure TTestCoreBase.NumericalConversions;
42034203
begin
42044204
s := DoubleToString(v);
42054205
val(s, d, err);
4206-
Check(err = 0);
4206+
CheckEqual(err, 0);
42074207
CheckSame(d, v);
42084208
StringToUtf8(s, u);
42094209
d := GetExtended(pointer(u), err);
4210-
Check(err = 0);
4210+
CheckEqual(err, 0);
42114211
CheckSame(d, v);
42124212
end;
42134213

@@ -4549,6 +4549,17 @@ procedure TTestCoreBase.NumericalConversions;
45494549
Check(UInt32ToUtf8(1599638299) = '1599638299');
45504550
Check(Int32ToUtf8(-1599638299) = '-1599638299');
45514551
Check(Int64ToUtf8(-1271083787498396012) = '-1271083787498396012');
4552+
CheckEqual(Int64ToUtf8(242161819595454762), '242161819595454762');
4553+
// detect 64-bit overflow of main digits in GetExtended()
4554+
CheckDoubleToShort(95.0290695380, '95.029069538');
4555+
Check(ToDouble('95.0290695380', d), '95.02');
4556+
CheckSame(d, 95.029069538);
4557+
Check(ToDouble('95.02906953800000000000', d), '95.x');
4558+
CheckSame(d, 95.029069538);
4559+
Check(ToDouble('184467440737095514', d), '184467440737095514');
4560+
CheckSame(d, 184467440737095514);
4561+
Check(ToDouble('1844674407370955148', d), '1844674407370955148');
4562+
CheckSame(d, 1844674407370955148);
45524563
// SQLite text-to-float converter routine failed with this number
45534564
Check(ToDouble('18446744073709551488', d), '18446744073709551488');
45544565
CheckSame(d, 1.8446744074e+19, 1e+10);
@@ -4557,9 +4568,11 @@ procedure TTestCoreBase.NumericalConversions;
45574568
CheckDoubleToShortSame(d);
45584569
CheckDoubleToShort(1234567890123456789, '1.2345678901234568E18');
45594570
CheckDoubleToShortSame(1234567890123456789);
4571+
CheckDoubleToShortSame(18446744073709551);
4572+
CheckDoubleToShortSame(184467440737095514);
4573+
CheckDoubleToShortSame(1844674407370955148);
45604574
{$endif FPC}
4561-
s := Int64ToUtf8(242161819595454762);
4562-
Check(s = '242161819595454762');
4575+
// validate ScanUtf8()
45634576
Check(ScanUtf8('1 2 3', ' %', [@i, @j, @d]) = 0);
45644577
Check(ScanUtf8('', '%d%d%f', [@i, @j, @d]) = 0);
45654578
Check(ScanUtf8('1 2 7', '%d%d%f', [@i, @j, @d]) = 3);

0 commit comments

Comments
 (0)