-
Notifications
You must be signed in to change notification settings - Fork 5.4k
Closed
Description
Local variable gets modified by an unrelated function call, with .NET Core 3.0. Admittedly the type in question is a bit weird, lifted from a CoreCLR test case.
In the code snippet below, "instance" mutates from being an object of type GenInt to a List<FieldInfo> magically. Calling GetAllInstanceFields shouldn't modified the local of the caller.
Observed output:
ClrIssueRepro.GenInt
System.Object
Expected output:
ClrIssueRepro.GenInt
ClrIssueRepro.GenInt
Here is the code snippet:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
#pragma warning disable 649, 169
namespace ClrIssueRepro
{
[StructLayout(LayoutKind.Sequential)]
public class GenBase<T>
{
public T Fld10;
public int _int0 = 0;
public double _double0 = 0;
public string _string0 = "string0";
public Guid _Guid0 = new Guid();
public T Fld11;
public int _int1 = int.MaxValue;
public double _double1 = double.MaxValue;
public string _string1 = "string1";
public Guid _Guid1 = new Guid(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11);
public T Fld12;
}
[StructLayout(LayoutKind.Explicit)]
public class GenInt : GenBase<int>
{
[FieldOffset(0)] public int sFld10;
[FieldOffset(16)] public int _sint0 = 0;
[FieldOffset(24)] public double _sdouble0 = 0;
[FieldOffset(32)] public string _sstring0 = "string0";
[FieldOffset(40)] public Guid _sGuid0 = new Guid();
[FieldOffset(56)] public int sFld11;
[FieldOffset(72)] public int _sint1 = int.MaxValue;
[FieldOffset(80)] public double _sdouble1 = double.MaxValue;
[FieldOffset(88)] public string _sstring1 = "string1";
[FieldOffset(96)] public Guid _sGuid1 = new Guid(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11);
[FieldOffset(112)] public int sFld12;
}
class Program
{
private static FieldInfo[] GetAllInstanceFields(Type type)
{
List<FieldInfo> result = new List<FieldInfo>();
for (Type t = type; t != null; t = t.BaseType)
{
// Stop iterating once we get to System.ValueType. There should be no fields in it
// or System.Object, it's base class. This is ok to do for desktop & ProjectN.
if (t == typeof(ValueType))
{
break;
}
FieldInfo[] fieldsOnType = t.GetFields(
BindingFlags.Public |
BindingFlags.NonPublic |
BindingFlags.Instance |
BindingFlags.DeclaredOnly);
result.AddRange(fieldsOnType);
}
return result.ToArray();
}
private static object CreateInstance(Type t)
{
return t.IsValueType ? Activator.CreateInstance(t) : FormatterServices.GetUninitializedObject(t);
}
static void Main(string[] args)
{
Type type = typeof(GenInt);
object instance = CreateInstance(type);
// instance is of type GenInt.
Console.WriteLine(instance.GetType());
System.Reflection.FieldInfo[] fields = GetAllInstanceFields(type);
// is it still?
Console.WriteLine(instance.GetType());
Debugger.Break();
}
}
}
Reactions are currently unavailable