提交 d6a8f32b 编写于 作者: A Andy Gocke

Catch exceptions when creating a stream for signing

This change is meant to address crashes like the ones in bug 1140649. The
crashes seem to happen due to exceptions thrown while getting a temporary
output stream to write the PE file to. I have been unable to reproduce
the conditions for the crash themselves -- they only seem to happen on
a Japanese language Windows with a Japanese language copy of Visual Studio.
This fix addresses their symptom by wrapping the CreateInputStream call
during signing with a try/catch and then surfacing the exception as a
diagnostic for signing failure.

We cannot currently add any more localized resources to stabilization, so
this fix is meant to be as targeted as possible and can only deliver
information through existing resource strings.

(cherry picked from commit 801a10a5)
上级 1d61936d
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
using System;
using System.IO;
using Xunit;
namespace Microsoft.CodeAnalysis.CSharp.UnitTests
{
public partial class InternalsVisibleToAndStrongNameTests : CSharpTestBase
{
/// <summary>
/// A strong name provider which throws an IOException while creating
/// the input stream.
/// </summary>
private class StrongNameProviderWithBadInputStream : StrongNameProvider
{
private StrongNameProvider _underlyingProvider;
public StrongNameProviderWithBadInputStream(StrongNameProvider underlyingProvider)
{
_underlyingProvider = underlyingProvider;
}
public override bool Equals(object other) => this == other;
public override int GetHashCode() => _underlyingProvider.GetHashCode();
internal override Stream CreateInputStream()
{
throw new IOException("This is a test IOException");
}
internal override StrongNameKeys CreateKeys(string keyFilePath, string keyContainerName, CommonMessageProvider messageProvider) =>
_underlyingProvider.CreateKeys(keyFilePath, keyContainerName, messageProvider);
internal override void SignAssembly(StrongNameKeys keys, Stream inputStream, Stream outputStream) =>
_underlyingProvider.SignAssembly(keys, inputStream, outputStream);
}
[Fact]
public void BadInputStream()
{
string src = @"
class C
{
public static void Main(string[] args) { }
}";
var testProvider = new StrongNameProviderWithBadInputStream(s_defaultProvider);
var options = TestOptions.DebugExe
.WithStrongNameProvider(testProvider)
.WithCryptoKeyContainer("RoslynTestContainer");
var comp = CreateCompilationWithMscorlib(src,
options: options);
comp.VerifyEmitDiagnostics(
// error CS7028: Error signing output with public key from container 'RoslynTestContainer' -- This is a test IOException
Diagnostic(ErrorCode.ERR_PublicKeyContainerFailure).WithArguments("RoslynTestContainer", "This is a test IOException").WithLocation(1, 1));
}
}
}
......@@ -18,7 +18,7 @@
namespace Microsoft.CodeAnalysis.CSharp.UnitTests
{
public class InternalsVisibleToAndStrongNameTests : CSharpTestBase
public partial class InternalsVisibleToAndStrongNameTests : CSharpTestBase
{
#region Helpers
......
......@@ -58,7 +58,7 @@
<Reference Include="..\..\..\..\..\packages\Microsoft.DiaSymReader.1.0.4-rc2\lib\net45\Microsoft.DiaSymReader.dll" />
<Reference Include="xunit">
<HintPath>..\..\..\..\..\packages\xunit.1.9.2\lib\net20\xunit.dll</HintPath>
</Reference>
</Reference>
</ItemGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
......@@ -151,6 +151,7 @@
<Compile Include="Emit\EmitErrorTests.cs" />
<Compile Include="Emit\EmitMetadata.cs" />
<Compile Include="Emit\EmitMetadataTestBase.cs" />
<Compile Include="Attributes\EmitTestStrongNameProvider.cs" />
<Compile Include="Emit\EntryPointTests.cs" />
<Compile Include="Emit\NoPiaEmbedTypes.cs" />
<Compile Include="Emit\OptionalArgumentsTests.cs" />
......@@ -205,4 +206,4 @@
<Import Project="..\..\..\..\..\build\Roslyn.Toolsets.Xunit.targets" />
<Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
</ImportGroup>
</Project>
</Project>
\ No newline at end of file
......@@ -1665,8 +1665,17 @@ private static EmitResult ToEmitResultAndFree(DiagnosticBag diagnostics, bool su
{
Debug.Assert(Options.StrongNameProvider != null);
signingInputStream = Options.StrongNameProvider.CreateInputStream();
retStream = signingInputStream;
// Targeted try-catch for errors during CreateInputStream as found in TFS 1140649
// TODO: Put this wrapping in PeWriter to catch all potential PE writing exceptions
try
{
signingInputStream = Options.StrongNameProvider.CreateInputStream();
retStream = signingInputStream;
}
catch (Exception e)
{
throw new Cci.PeWritingException(e);
}
}
else
{
......@@ -1720,6 +1729,12 @@ private static EmitResult ToEmitResultAndFree(DiagnosticBag diagnostics, bool su
diagnostics.Add(MessageProvider.CreateDiagnostic(MessageProvider.ERR_PdbWritingFailed, Location.None, ex.Message));
return false;
}
catch (Cci.PeWritingException e)
{
// Targeted fix for TFS 1140649
// TODO: Add resource and better error message for a variety of PE exceptions
diagnostics.Add(StrongNameKeys.GetError(StrongNameKeys.KeyFilePath, StrongNameKeys.KeyContainer, e.Message, MessageProvider));
}
catch (ResourceException e)
{
diagnostics.Add(MessageProvider.CreateDiagnostic(MessageProvider.ERR_CantReadResource, Location.None, e.Message, e.InnerException.Message));
......
......@@ -14,6 +14,13 @@
namespace Microsoft.Cci
{
internal sealed class PeWritingException : Exception
{
public PeWritingException(Exception inner)
: base(inner.Message, inner)
{ }
}
internal sealed class PeWriter
{
/// <summary>
......
' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
Imports System.IO
Imports Microsoft.CodeAnalysis
Imports Microsoft.CodeAnalysis.VisualBasic
Imports Microsoft.CodeAnalysis.VisualBasic.UnitTests
Partial Public Class InternalsVisibleToAndStrongNameTests
Inherits BasicTestBase
Private Class StrongNameProviderWithBadInputStream
Inherits StrongNameProvider
Private _underlyingProvider As StrongNameProvider
Public Sub New(underlyingProvider As StrongNameProvider)
_underlyingProvider = underlyingProvider
End Sub
Public Overrides Function Equals(other As Object) As Boolean
Return Me Is other
End Function
Public Overrides Function GetHashCode() As Integer
Return _underlyingProvider.GetHashCode()
End Function
Friend Overrides Function CreateInputStream() As Stream
Throw New IOException("This is a test IOException")
End Function
Friend Overrides Function CreateKeys(keyFilePath As String, keyContainerName As String, messageProvider As CommonMessageProvider) As StrongNameKeys
Return _underlyingProvider.CreateKeys(keyFilePath, keyContainerName, messageProvider)
End Function
Friend Overrides Sub SignAssembly(keys As StrongNameKeys, inputStream As Stream, outputStream As Stream)
_underlyingProvider.SignAssembly(keys, inputStream, outputStream)
End Sub
End Class
<Fact>
Public Sub BadInputStream()
Dim testProvider = New StrongNameProviderWithBadInputStream(s_defaultProvider)
Dim options = TestOptions.DebugDll.WithStrongNameProvider(testProvider).WithCryptoKeyContainer("RoslynTestContainer")
Dim comp = CreateCompilationWithMscorlib(
<compilation>
<file name="a.vb"><![CDATA[
Public Class C
Public Sub M()
End Sub
End Class
]]>
</file>
</compilation>, options:=options)
comp.VerifyEmitDiagnostics(
Diagnostic(ERRID.ERR_PublicKeyContainerFailure).WithArguments("RoslynTestContainer", "This is a test IOException").WithLocation(1, 1))
End Sub
End Class
......@@ -13,7 +13,7 @@ Imports Microsoft.CodeAnalysis.VisualBasic
Imports Microsoft.CodeAnalysis.VisualBasic.UnitTests
Imports Roslyn.Test.Utilities
Public Class InternalsVisibleToAndStrongNameTests
Partial Public Class InternalsVisibleToAndStrongNameTests
Inherits BasicTestBase
#Region "Helpers"
......@@ -417,7 +417,7 @@ End Class
Dim err = other.GetDeclarationDiagnostics().Single()
Assert.Equal(ERRID.ERR_PublicKeyContainerFailure, err.Code)
Assert.Equal(2, Err.Arguments.Count)
Assert.Equal(2, err.Arguments.Count)
Assert.Equal("foo", DirectCast(err.Arguments(0), String))
Assert.True(DirectCast(err.Arguments(1), String).EndsWith(" HRESULT: 0x80090016)", StringComparison.Ordinal))
......@@ -1652,7 +1652,7 @@ End Class
<Fact, WorkItem(1072350, "DevDiv")>
Public Sub Bug1072350()
Dim sourceA As XElement = _
Dim sourceA As XElement =
<compilation name="ClassLibrary2">
<file name="a.vb"><![CDATA[
<Assembly: System.Runtime.CompilerServices.InternalsVisibleTo("X ")>
......@@ -1662,7 +1662,7 @@ End Class]]>
</file>
</compilation>
Dim sourceB As XElement = _
Dim sourceB As XElement =
<compilation name="X">
<file name="b.vb"><![CDATA[
Class B
......@@ -1676,13 +1676,13 @@ End Class]]>
Dim ca = CreateCompilationWithMscorlib(sourceA, options:=TestOptions.ReleaseDll)
CompileAndVerify(ca)
Dim cb = CreateCompilationWithMscorlib(sourceB, options:=TestOptions.ReleaseExe, references:={new VisualBasicCompilationReference(ca)})
Dim cb = CreateCompilationWithMscorlib(sourceB, options:=TestOptions.ReleaseExe, references:={New VisualBasicCompilationReference(ca)})
CompileAndVerify(cb, expectedOutput:="42", emitters:=TestEmitters.CCI).Diagnostics.Verify()
End Sub
<Fact, WorkItem(1072339, "DevDiv")>
Public Sub Bug1072339()
Dim sourceA As XElement = _
Dim sourceA As XElement =
<compilation name="ClassLibrary2">
<file name="a.vb"><![CDATA[
<Assembly: System.Runtime.CompilerServices.InternalsVisibleTo("x")>
......@@ -1692,7 +1692,7 @@ End Class]]>
</file>
</compilation>
Dim sourceB As XElement = _
Dim sourceB As XElement =
<compilation name="x">
<file name="b.vb"><![CDATA[
Class B
......@@ -1706,13 +1706,13 @@ End Class]]>
Dim ca = CreateCompilationWithMscorlib(sourceA, options:=TestOptions.ReleaseDll)
CompileAndVerify(ca)
Dim cb = CreateCompilationWithMscorlib(sourceB, options:=TestOptions.ReleaseExe, references:={new VisualBasicCompilationReference(ca)})
Dim cb = CreateCompilationWithMscorlib(sourceB, options:=TestOptions.ReleaseExe, references:={New VisualBasicCompilationReference(ca)})
CompileAndVerify(cb, expectedOutput:="42", emitters:=TestEmitters.CCI).Diagnostics.Verify()
End Sub
<Fact, WorkItem(1095618, "DevDiv")>
Public Sub Bug1095618()
Dim source As XElement = _
Dim source As XElement =
<compilation name="a">
<file name="a.vb"><![CDATA[
<Assembly: System.Runtime.CompilerServices.InternalsVisibleTo("System.Runtime.Serialization, PublicKey = 10000000000000000400000000000000")>
......
......@@ -106,6 +106,7 @@
<Compile Include="Attributes\AttributeTests_StructLayout.vb" />
<Compile Include="Attributes\AttributeTests_Synthesized.vb" />
<Compile Include="Attributes\AttributeTests_WellKnownAttributes.vb" />
<Compile Include="Attributes\EmitTestStrongNameProvider.vb" />
<Compile Include="Attributes\InternalsVisibleToAndStrongNameTests.vb" />
<Compile Include="BreakingChanges.vb" />
<Compile Include="CodeGen\AnonymousTypesCodeGenTests.vb" />
......@@ -281,4 +282,4 @@
<Import Project="..\..\..\..\..\build\Roslyn.Toolsets.Xunit.targets" />
<Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
</ImportGroup>
</Project>
</Project>
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册