From 50e4aaed789e36a041903895dd126fd1a5c3ba76 Mon Sep 17 00:00:00 2001 From: Sven Harazim Date: Fri, 5 Dec 2025 07:14:08 +0100 Subject: [PATCH] Fixes UInt64 to Double conversion on ARM64 Addresses an issue where direct UInt64 to Double conversion, as well as division operations involving UInt64, were failing on 32-bit ARM64 emulation. Implements a workaround by manually converting UInt64 to Double in two parts (hi and lo Cardinal) to avoid the failing operations. This ensures correct parsing of large numbers. --- sources/JsonDataObjects.pas | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/sources/JsonDataObjects.pas b/sources/JsonDataObjects.pas index a96dd7ef..c535408f 100644 --- a/sources/JsonDataObjects.pas +++ b/sources/JsonDataObjects.pas @@ -7175,6 +7175,19 @@ function ParseAsDoubleUtf8(F, P: PByte): Double; end; end; +// 32-bit ARM64 emulation fix: Manual digit-by-digit conversion +// Both UInt64/Double division AND UInt64->Double implicit conversion fail +function U64ToDouble(u: UInt64): Double; +const + TWO32: Double = 4294967296.0; +var + hi, lo: Cardinal; +begin + hi := Cardinal(u shr 32); + lo := Cardinal(u); + Result := hi * TWO32 + lo; +end; + procedure TUtf8JsonReader.LexNumber(P: PByte{$IFDEF CPUARM}; EndP: PByte{$ENDIF}); var F: PByte; @@ -7297,7 +7310,7 @@ procedure TUtf8JsonReader.LexNumber(P: PByte{$IFDEF CPUARM}; EndP: PByte{$ENDIF} EndInt64P := EndP; while (P < EndInt64P) and (P^ in [Ord('0')..Ord('9')]) do Inc(P); - Value := Value + ParseUInt64Utf8(F, P) / Power10[P - F]; + Value := Value + U64ToDouble(ParseUInt64Utf8(F, P)) / Power10[P - F]; // "Double" can't handle that many digits while (P < EndP) and (P^ in [Ord('0')..Ord('9')]) do @@ -7828,7 +7841,7 @@ procedure TStringJsonReader.LexNumber(P: PChar{$IFDEF CPUARM}; EndP: PChar{$ENDI EndInt64P := EndP; while (P < EndInt64P) and (P^ in ['0'..'9']) do Inc(P); - Value := Value + ParseUInt64(F, P) / Power10[P - F]; + Value := Value + U64ToDouble(ParseUInt64(F, P)) / Power10[P - F]; // "Double" can't handle that many digits while (P < EndP) and (P^ in ['0'..'9']) do