-
Notifications
You must be signed in to change notification settings - Fork 4.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Validate IntPtr
and ByRef field overlap
#65246
Validate IntPtr
and ByRef field overlap
#65246
Conversation
Is ByRef and IntPtr overlap a problem? We decided not to check this for ByRef-like types. ByRef pointing to unmanaged memory or other garbage should be fine because that's what happens for Span pointing to unmanaged memory. Or is this futureproofing for when we allow byrefs on the GC heap and we'll need to make sure these writes go through a write barriers when that happens? |
I think the same thing can currently occur. For example, if a @davidwrighton and I discussed this, and I was convinced it was a real issue. Feel free to push back though. |
I don't have an opinion either way. But if we do this, we should probably also revisit this for byref-like types too so that we don't end up with a situation where: ref struct Foo
{
[Offset(0)] ref int Field1;
[Offset(0)] IntPtr Field2
} is disallowed but, ref struct HiddenRef
{
ref int Field;
}
ref struct Foo
{
[Offset(0)] HiddenRef Field1;
[Offset(0)] IntPtr Field2
} is allowed, even though they're basically the same thing. There was some conversation about it at #12842 (comment). |
Or maybe your pull request already does this - I don't read C++ on weekends. |
@MichalStrehovsky I get it, that's okay. However, it does handle your query above.
|
@MichalStrehovsky the problem with ByRef/ByRefLike and IntPtr overlap is that it becomes possible (without the use of unsafe) to generate a byref that points to something in the GC heap which isn't actually an object. (The GC has an invariant that ByRef pointers passed into it must either be within an object on the GC heap or not within the memory regions of the GC Heap at all.) If we've explicitly been permitting ByRefLike structure overlap with IntPtr for the purpose of doing funky things with |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, it was just decided that validating that wasn't worth the hassle at that time: #12842 (comment) This test is going to fail on NativeAOT if we're not adding a check for that to the managed type system. I would be okay with that if it's not observable with crossgen2. The test is doing a FWIW, we've been mirroring these checks in the past (dotnet/coreclr#27054). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we should recurse into reference types when computing has_ref_fields
. Otherwise mono bits LGTM
These tests pass under CrossGen2. I'm assuming that is what is meant here. |
No, as I wrote above "The test is doing a typeof and that's an obvious type load that will let CoreCLR throw the exception no matter if the code was AOT'd". I meant: using System;
using System.Runtime.InteropServices;
Explicit ex = new Explicit
{
Guid = Guid.NewGuid(),
};
return ex.Bytes.Length;
[StructLayout(LayoutKind.Explicit)]
ref struct Explicit
{
[FieldOffset(0)] public Span<byte> Bytes;
[FieldOffset(0)] public Guid Guid;
} I just tried this: C:\git\runtime\artifacts\bin\coreclr\windows.x64.Debug>csc /nologo /noconfig /nostdlib test.cs /r:System.Private.CoreLib.dll
C:\git\runtime\artifacts\bin\coreclr\windows.x64.Debug>corerun test.exe
Unhandled exception. System.TypeLoadException: Could not load type 'Explicit' from assembly 'test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' because it contains an object field at offset 0 that is incorrectly aligned or overlapped by a non-object field.
at Program.<Main>$(String[] args)
C:\git\runtime\artifacts\bin\coreclr\windows.x64.Debug>crossgen2\crossgen2.exe test.exe -o:test.ni.exe -r:System.Private.CoreLib.dll
Emitting R2R PE file: test.ni.exe
C:\git\runtime\artifacts\bin\coreclr\windows.x64.Debug>corerun test.exe
C:\git\runtime\artifacts\bin\coreclr\windows.x64.Debug>echo %ERRORLEVEL%
985271193 So ReadyToRun currently can bypass the checks. |
Support here could be enabled with the conservative GC but instead of permitting that, CoreCLR will block support in the type loader.
Confirmed tests pass locally on mono, CoreCLR, and with CrossGen.
/cc @davidwrighton @MichalStrehovsky @dotnet/interop-contrib