Windows update corrupts struct construction in .Net 4.x

225 views Asked by At

Since the installed of a Windows update on 14.9.2017 we have problems creating certain structs in our release builds. I have noticed that compiled code on computers without that update runs as expected ("Wrong start: 1.1.1990..."), on computer with the update in question installed, the code is not working correctly ("Wrong start: 1.1.2000..."). This happens in all versions of the .NET Frameworks starting from version 4.x.

 class Program
    {
        static void Main(string[] args)
        {
            DateTime start1 = new DateTime(1990, 1, 1, 6, 0, 0);
            DateTime end1 = new DateTime(2000, 1, 1, 6, 0, 0);
            var r2 = new DateTimeRange(start1, end1);
            var r3 = new Range<DateTime>(r2.From, r2.To);
            Console.WriteLine($"Wrong start: {r3.From}, correct start: {start1}");
            Console.ReadLine();
        }
    }

   public struct DateTimeRange 
    {
        private Range<DateTime> m_range;

        public DateTimeRange(DateTime from, DateTime to)
        {
            m_range = new Range<DateTime>(from, to);
        }


        public DateTime From
        {
            get { return m_range.From; }
        }

        public DateTime To
        {
            get { return m_range.To; }
        }
    }

    public struct Range<T> where T : struct
    {
        private T m_from;
        private T m_to;


        public Range(T from, T to)
        {
            m_from = from;
            m_to = to;
        }


        public T From
        {
            get { return m_from; }
        }

        public T To
        {
            get { return m_to; }
        }
    }
1

There are 1 answers

1
Hans Passant On

I see it, after rebooting my machine. Definitely quacks like bug in the update. On my machine I see C:\Windows\Microsoft.NET\Framework64\v4.0.30319\corjit.dll, dated 9/6/17, 9:23AM CDT, version 4.7.2110.0.

The bug is specific to the x64 jitter and only occurs in the Release build with the optimizer enabled. It matches the kind of bugs that I've seen in the jitter before, most optimizer bugs in the past were related to code handling structs.

Unfortunately I have a hard time characterizing the bug, the code gen is too beefy and the workaround I found does not seem to make enough difference in the machine code on first glance. But is otherwise the typical way to sail around these kind of optimizer bugs:

using System.Runtime.CompilerServices;
...
    public DateTime From {
        [MethodImpl(MethodImplOptions.NoInlining)]
        get { return m_range.From; }
    }

The other workarounds are forcing 32-bit mode or falling back to the legacy jitter. Please report the bug so they can fix it, let me know if you don't want to take the time and I'll take care of it.