A few tweaks for fixing issue Convert::NativeToInt64 with SUPPORT_ANY_BASE_CONVERSION delivers incorrect results
@@ -25,9 +25,29 @@ HRESULT Library_corlib_native_System_Convert::NativeToInt64___STATIC__I8__STRING
long long minValue = stack.Arg2().NumericByRef().s8;
long long maxValue = stack.Arg3().NumericByRef().s8;
+ // normally we check if the result is in the given range
+ bool check = true;
+
+ // Int64? => use also strtoull the result will be casted to Int64
+ if (isSigned && maxValue == 0x7FFFFFFFFFFFFFFF) isSigned = false;
+
+ // UInt64? => use also strtoull the result will be casted to Int64 and bypass the range check
+ if (minValue == 0 && maxValue == 0)
+ {
+ isSigned = false;
+ check = false;
+ }
+
+ // convert via strtoll / strtoull
result = isSigned ? strtoll(str, nullptr, radix) : (long long) strtoull(str, nullptr, radix);
- stack.SetResult_I8 ((result > maxValue || result < minValue) ? zero : result);
+ // the signed values for SByte, Int16 and Int32 are always positive for base 2, 8 or 16 conversions
+ // because the 64-bit function strtoll is used; need the post process the value
+ // if the result is greater max and smaller (max + 1) * 2 this value should be subtracted
+ if (isSigned && result > maxValue && result < (maxValue + 1) * 2) result -= (maxValue + 1) * 2;
+
+ // for UInt64 the check will be bypassed
+ stack.SetResult_I8 ((check && (result > maxValue || result < minValue)) ? zero : result);
#else
// support for conversion from base 10 and 16 (partial)
