The Single and Double overloads of TryStr2Float in u_dzConvertUtils convert the string to Extended and then assign that to the target type without a range check. A value that is a valid Extended but too large for Single / Double therefore does not return False:
| Delphi 7, 2007, 11 (Win32) | Delphi 12 Win32 | Delphi 12 Win64 | |
|---|---|---|---|
Single 1e300 |
raises EOverflow |
True, INF | True, INF |
Double 1e400 |
raises EOverflow |
True, INF | False (correct, Extended is Double there) |
Up to Delphi 11 the assignment raises because overflow exceptions are unmasked; Delphi 12 masks floating point exceptions, so the result is INF and the function returns True.
This also affects everything built on these overloads, e.g. the Single and Double overloads of TIniFile_TryReadFloat in u_dzClassUtils, which with ehNoException are supposed to return False for an invalid value.
Expected: False if the value is outside the range of the target type.
Measured with a console program calling TryStr2Float('1e300', SingleVar) and TryStr2Float('1e400', DoubleVar) and printing the result or the exception class.
Fixed in revision #2473.
The Single and Double overloads of TryStr2Float now return False for a value that would round to INF in the target type, on every version, instead of raising EOverflow (up to Delphi 11) or returning True with INF (Delphi 12). The check compares with the type's largest value plus half a unit in the last place, so a value that rounds down to MaxSingle / MaxDouble, e.g.
3.40282346638529E38, is still accepted.INFandNAN, which Delphi 12 accepts, stay valid. A value too small for the type still becomes a denormal or 0. TIniFile_TryReadFloat with Single or Double benefits from this. New tests in ConvertUtils.