Menu ▾ ▴

#85 Num2Long/Hex2Long/Dec2Long return a wrapped value for a number that does not fit into UInt32, 0 for an empty string, and with {$Q+} raise EIntOverflow even for High(UInt32)

unread
nobody
2026-10-18
2026-10-18
No

The non-Try conversion functions in u_dzConvertUtils have the problems that [bugs:#64] fixed for TryNum2Long, TryHex2Long and TryDec2Long. They multiply up the digits in a UInt32 without checking for overflow, and they accept an empty string.

Measured on Delphi 2007 and 12 against the library code as it is now:

Call default with {$Q+}
Num2Long('4294967295', 10) 4294967295 EIntOverflow
Hex2Long('FFFFFFFF') 4294967295 EIntOverflow
Num2Long('4294967296', 10) 0 EIntOverflow
Hex2Long('100000000') 0 EIntOverflow
Dec2Long('4294967296') 0 EIntOverflow
Dec2Long('99999999999') 1215752191 EIntOverflow
Num2Long('', 10), Hex2Long(''), Dec2Long('') 0 0

(Dec2Long('4294967295') gives 4294967295 either way. The AnsiString overload of Dec2Long behaves like the string one.)

Num2Long and Hex2Long raise for High(UInt32) itself with {$Q+} because they compute Result * _Base + (digit + 1) - 1, and the + (digit + 1) overflows before the - 1.

Expected: the value for every number that fits, and an exception for one that does not and for an empty string. EDigitOutOfRange, which they already raise for an invalid digit, or a new exception class. They could call TryNum2Long and raise if it returns False.

Callers in the library pass at most four digits, so the overflow does not affect them. u_dzIso8601 (Dec2Long) checks the length first. u_dzStringUtils (Hex2Long) always passes two characters. u_dzMiscUtils (Hex2Long on Copy(_s, i * 2 + 1, 2)) only asserts the length of _s, so with assertions off a string that is too short gives '' and silently 0 for the missing bytes. With the fix it would raise instead.

Related

Bug Reports: #64

Discussion


Log in to post a comment.