JIT: Fix noway_assert when inlining
authorAndy Ayers <andya@microsoft.com>
Fri, 17 Mar 2017 07:21:50 +0000 (00:21 -0700)
committerAndy Ayers <andya@microsoft.com>
Fri, 17 Mar 2017 17:39:04 +0000 (10:39 -0700)
The jit keeps track of which inline arguments can be modified via starg
during the inlinee IL prescan to ensure that a temp is used to represent
such arguments in the inlined body. There is a noway_assert the a starg
is procecssed during importation that double-checks that a temp is really
being used, and this assert was firing.

The prescan guraded the starg tracking with a check to avoid an out-of-bounds
write into the argument table when scanning bad IL with bogus argument numbers.
The predicate was checking the argument number against lvaTableCount.
Unfortunately for inlinees this value is not related to the number of arguments.
In particular it some rare cases it may be an underestimate so the prescan might
end up failing to note a starg. If the the jit then tries to inline and the
caller passes a constant, the assert will then fire.

Fix is to update the guard to use the number of callee arguments. This is
known to be less than the table size by earlier checks.

Added a test case.

Closes dotnet/coreclr#9891.

Commit migrated from https://github.com/dotnet/coreclr/commit/0380bad51faf5ef608208f1ead8294dcf8519ce0

src/coreclr/src/jit/flowgraph.cpp
src/coreclr/tests/src/JIT/Regression/JitBlue/GitHub_9891/GitHub_9891.cs [new file with mode: 0644]
src/coreclr/tests/src/JIT/Regression/JitBlue/GitHub_9891/GitHub_9891.csproj [new file with mode: 0644]

index 8bd267c..0cc0d56 100644 (file)
@@ -4535,17 +4535,22 @@ void Compiler::fgFindJumpTargets(const BYTE* codeAddr, IL_OFFSET codeSize, BYTE*
                 }
 
                 varNum = (sz == sizeof(BYTE)) ? getU1LittleEndian(codeAddr) : getU2LittleEndian(codeAddr);
-                varNum = compMapILargNum(varNum); // account for possible hidden param
 
-                // This check is only intended to prevent an AV.  Bad varNum values will later
-                // be handled properly by the verifier.
-                if (varNum < lvaTableCnt)
+                if (isInlining)
                 {
-                    if (isInlining)
+                    if (varNum < impInlineInfo->argCnt)
                     {
                         impInlineInfo->inlArgInfo[varNum].argHasStargOp = true;
                     }
-                    else
+                }
+                else
+                {
+                    // account for possible hidden param
+                    varNum = compMapILargNum(varNum); 
+
+                    // This check is only intended to prevent an AV.  Bad varNum values will later
+                    // be handled properly by the verifier.
+                    if (varNum < lvaTableCnt)
                     {
                         // In non-inline cases, note written-to locals.
                         lvaTable[varNum].lvArgWrite = 1;
diff --git a/src/coreclr/tests/src/JIT/Regression/JitBlue/GitHub_9891/GitHub_9891.cs b/src/coreclr/tests/src/JIT/Regression/JitBlue/GitHub_9891/GitHub_9891.cs
new file mode 100644 (file)
index 0000000..72a6bbc
--- /dev/null
@@ -0,0 +1,31 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+
+// Noway assert where an inlinee modified a parameter with index > 16,
+// and caller that had few args or locals passed in a constant for
+// that parameter.
+
+class B
+{
+    int X(
+        int a01, int a02, int a03, int a04,
+        int a05, int a06, int a07, int a08,
+        int a09, int a10, int a11, int a12,
+        int a13, int a14, int a15, int a16,
+        int a17, int a18, int a19, int a20)
+    {
+        a20 = a19;
+        return a20;
+    }
+
+    public static int Main(string[] args)
+    {
+        B b = new B();
+        int v = b.X(1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
+            11, 12, 13, 14, 15, 16, 17, 18, 19, 20);
+        return v + 81;
+    }
+}
diff --git a/src/coreclr/tests/src/JIT/Regression/JitBlue/GitHub_9891/GitHub_9891.csproj b/src/coreclr/tests/src/JIT/Regression/JitBlue/GitHub_9891/GitHub_9891.csproj
new file mode 100644 (file)
index 0000000..6b8b07a
--- /dev/null
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <AssemblyName>$(MSBuildProjectName)</AssemblyName>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{95DFC527-4DC1-495E-97D7-E94EE1F7140D}</ProjectGuid>
+    <OutputType>Exe</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <FileAlignment>512</FileAlignment>
+    <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+    <ReferencePath>$(ProgramFiles)\Common Files\microsoft shared\VSTT\11.0\UITestExtensionPackages</ReferencePath>
+    <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir>
+
+    <NuGetPackageImportStamp>7a9bfb7d</NuGetPackageImportStamp>
+  </PropertyGroup>
+  <!-- Default configurations to help VS understand the configurations -->
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+  </PropertyGroup>
+  <ItemGroup>
+    <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
+      <Visible>False</Visible>
+    </CodeAnalysisDependentAssemblyPaths>
+  </ItemGroup>
+  <PropertyGroup>
+    <DebugType></DebugType>
+    <Optimize>True</Optimize>
+  </PropertyGroup>
+  <ItemGroup>
+    <Compile Include="$(MSBuildProjectName).cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+  </ItemGroup>
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+  <PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' ">
+  </PropertyGroup> 
+</Project>