Skip to content

[EnC] FieldInfo.GetValue on a newly-added ValueType field crashes CoreCLR #76702

Description

@lambdageek

Found this while working on #76462, but it also reproduces with net7 (and probably net6.0 and older, see below)

Repro:

  1. dotnet new console
  2. Use the following for Program.cs:
// #define UPDATE

using System.Reflection;

public class Test {

	public static void Main ()
	{	
		bool stop = false;

		Console.CancelKeyPress += new ((sender, ev) => {
		  ev.Cancel = true;
		  stop = true;
		});

		var c0 = new C();
		int i = 0;
		while (!stop) {
		  Body (ref i);
		}
		Console.WriteLine ("stopping");
		GC.KeepAlive (c0);
	}

	static void Body (ref int i)
	{
		Console.WriteLine($"alive {i}");
		i += 1;
		Thread.Sleep (1000);
#if UPDATE
	        var c = new C();
                var fi = c.GetType().GetField ("MyS");

		var s = fi.GetValue (c); // bad!

		Console.WriteLine ("still alive");
#endif
	}

	class C {

#if UPDATE
		public S MyS;
#endif

		public C() {
#if UPDATE
			MyS = new S {
				D = -1985.0,
				O = new int[2] {15, 17},
			};
#endif
		}

#if UPDATE
		public struct S {
			public double D;
			public object O;
		};
#endif
	}
}
  1. Run dotnet watch (but I believe this would also reproduce with EnC in Visual Studio)
  2. Change // #define UPDATE to #define UPDATE and save (or hit "Apply Changes" in VS)

Expected result:

The hot reload change is applied and the application keeps running.

Actual result:

dotnet watch 🚀 Started
alive 0
alive 1
alive 2
alive 3
alive 4
alive 5
alive 6
dotnet watch ⌚ File changed: ./Program.cs.
alive 7
dotnet watch 🔥 Hot reload of changes succeeded.
alive 8
dotnet watch ❌ Exited with error code 139
dotnet watch ⏳ Waiting for a file to change before restarting dotnet...
dotnet watch 🛑 Shutdown requested. Press Ctrl+C again to force exit.

That is, the child process - dotnet running the user code crashed with exit code 139.

In #76462 we actually get a good combination of error messages from a CoreCLR builds on OSX and Windows, respectively:

Mac:

Assert failure(PID 21236 [0x000052f4], Thread: 191148 [0x2eaac]): IS_ALIGNED(src, sizeof(SIZE_T))
    File: /Users/runner/work/1/s/src/coreclr/classlibnative/bcltype/arraynative.cpp Line: 736
    Image: /private/tmp/helix/working/B02E09C7/p/dotnet

Windows:

Fatal error. Internal CLR error. (0x80131506)
   at System.RuntimeFieldHandle.GetValue(System.Reflection.RtFieldInfo, System.Object, System.RuntimeType, System.RuntimeType, Boolean ByRef)
   at System.Reflection.RtFieldInfo.GetValue(System.Object)
   at System.Reflection.Metadata.ApplyUpdateTest+<>c.<TestAddInstanceField>b__10_0()
   at System.RuntimeMethodHandle.InvokeMethod(System.Object, Void**, System.Signature, Boolean)
   at System.Reflection.MethodInvoker.InterpretedInvoke(System.Object, IntPtr*)
   at System.Reflection.MethodInvoker.Invoke(System.Object, IntPtr*, System.Reflection.BindingFlags)
   at System.Reflection.MethodInvoker.InlinedInvoke(System.Object, IntPtr*, System.Reflection.BindingFlags)
   at System.Reflection.RuntimeMethodInfo.Invoke(System.Object, System.Reflection.BindingFlags, System.Reflection.Binder, System.Object[], System.Globalization.CultureInfo)
   at System.Reflection.MethodBase.Invoke(System.Object, System.Object[])
   at Microsoft.DotNet.RemoteExecutor.Program.Main(System.String[])

Which points to InvokeUtil::GetFieldValue

if (pField->IsStatic())
p = pField->GetCurrentStaticAddress();
else {
p = (*((BYTE**)target)) + pField->GetOffset() + sizeof(Object);
}
GCPROTECT_END();
// copy the field to the unboxed object.
// note: this will be done only for the non-remoting case
if (p) {
CopyValueClass(obj->GetData(), p, fieldType.AsMethodTable());

This looks wrong - p = (*((BYTE**)target)) + pField->GetOffset() + sizeof(Object); for fields added by EnC - they aren't at some offset, they're allocated entirely separately from the target object.

By the way, the same wrong logic is also in InvokeUtil::SetValidField so probably RtFieldInfo.SetField/RuntimeFieldHandle.SetField has issues too.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Type

No type

Projects

No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions