roslyn: Using the new C# 7.2 'in' parameters can lead to memory corruptions

Version Used: Microsoft Visual Studio Enterprise 2017, Version 15.5.0 Microsoft ® Visual C# Compiler version 2.6.0.62329 (5429b35d)

Steps to Reproduce:

  1. Compile reproduction project (will share privately)
  2. Run console application
  3. Observe crash when it attempts to print the values

Expected Behavior: It should print the strings it found to the console output

Actual Behavior: AccessViolationException when referencing the strings

Description With the release of Visual Studio 15.5 and C# 7.2 ‘in’ support, we sprinkled this around parts of our code base. When running the unit tests to confirm everything still worked, we found a big portion of them now failed with varying reasons. Some manifested as OutOfMemoryException, others as AccessViolationException and a few NullReferenceExceptions (one even appeared to be thrown inside String.IsNullOrEmpty) After confirming everything still worked in our other branch, I began digging into this in an attempt to find the root cause, but ended up only getting more and more confused. I was able to create a small reproduction console app that references a single library project containing our custom message parser, but don’t really know how to move forward from here.

I have created a zip file (220KB) of the reproduction project, which includes the source code and the outputted binaries I got, and was hoping someone here could take a look to see if they can find the cause.

I was only able to get permission to share the code in a private manner, so I’m afraid I can’t just upload it or link to it here. I can either upload it to a more private environment, or share a download link via E-mail, Slack/Twitter DM, etc.

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Reactions: 1
  • Comments: 23 (15 by maintainers)

Most upvoted comments

that opens the way to a really simple repro:

  1. clone https://github.com/gulbanana-bugs/repro-csharp72-in-minimal
  2. dotnet run
  3. observe segfault

Or inline:

static void Main() => new[]{ 0 }.Select(InMethod).ToList();
static int InMethod(in int param) => param;

Ok. To conclude issues here (some organization and filing bugs):

  1. The issue that for delegate parameters, the compiler doesn’t match in methods with val methods correctly. This is a duplicate of #23319 and was fixed in #23397.
  2. The issue of passing optional in parameters by value. I’ve copied the repro here into a separate issue (#23691) and assigned to myself to investigate further.
  3. The issue of passing this to in parameters. I’ve copied the repro here into another separate issue (#23692) and assigned to myself to investigate further.

Since the original root cause here is already fixed (as noted in the first point), I’ll close this, and we should follow up on respective issues. Thanks all for the reports!

One more code: (TergetFrameworks net46;netcoreapp2.1)

using System;

class Program
{
    static void Main()
    {
        // buffer overrun
        A(1);

        // throw NullReference or AccessViolation Exception
        B(1, 2);
    }

    static void A(in double x = 1, in string y = "") => Console.WriteLine(y);
    static double B(in float x, in float y, in float z = 1.0f) => x * y * z;

}

Thanks all for narrowing down the problem.

From discussion with @tannergooding, there are two separate bugs: (1) default values are passed by-val instead of in, (2) the compiler incorrectly matches a method with an in parameter to a by-val delegate signature.

Assigning to @OmarTawfik since Vlad is out. Thanks