runtime: System.IntPtr(long) constructor throws overflow
The current .NET Framework on Windows and CoreCLR have the following implementation for System.IntPtr(long):
public unsafe IntPtr(long value)
{
#if WIN32
m_value = (void *)checked((int)value);
#else
m_value = (void *)value;
#endif
}
This is quite unfortunate on 32-bit platforms because if you get a pointer value as a long which has the higher bit set, it will always throw an overflow exception.
To reproduce:
IntPtr ptr = new IntPtr(0x80000000);
The code should have been:
public unsafe IntPtr(long value)
{
#if WIN32
m_value = (void *)checked((uint)value);
#else
m_value = (void *)value;
#endif
}
since we only care that the higher 32-bits of the long parameter are all zeros.
About this issue
- Original URL
- State: closed
- Created 8 years ago
- Comments: 15 (11 by maintainers)
Links to this issue
Commits related to this issue
- Avoid overflow on 32-bit system Because IntPtr does not allow addresses in the range 0x80000000 to 0xFFFFFFFF we cast the long value to Void *. Downside is that no obvious validity check is done. See... — committed to manu-st/corefx by deleted user 8 years ago
- Avoid overflow on 32-bit system Because IntPtr does not allow addresses in the range 0x80000000 to 0xFFFFFFFF we cast the long value to Void *. Downside is that no obvious validity check is done. See... — committed to manu-st/corefx by deleted user 8 years ago
- Avoid overflow on 32-bit system Because IntPtr does not allow addresses in the range 0x80000000 to 0xFFFFFFFF we cast the long value to Void *. Downside is that no obvious validity check is done. See... — committed to manu-st/corefx by deleted user 8 years ago
- Workaround for 32bit uint -> IntPtr issue in SetClassLong See: https://github.com/dotnet/coreclr/issues/4062 — committed to WernerWenz/opentk by WernerWenz 8 years ago
I think that change would be a bit unfortunate. Consider:
I think it’s the naming of the type that is problematic –
IntPtrreally represents an integer of native size, but it is documented and named as if it represents a pointer. As a native integer the current behavior makes perfect sense. The problem then arises from shoehorning a pointer into a native integer and the native integer being calledIntPtr. A better fit would be to useUIntPtrwhen representing pointers but that type is not CLS compatible and unused in all of the BCL.