diff --git a/src/Compilers/Core/Portable/MetadataReader/MetadataDecoder.cs b/src/Compilers/Core/Portable/MetadataReader/MetadataDecoder.cs
index 6bab659cf86b6..e0468ea5aeb07 100644
--- a/src/Compilers/Core/Portable/MetadataReader/MetadataDecoder.cs
+++ b/src/Compilers/Core/Portable/MetadataReader/MetadataDecoder.cs
@@ -504,9 +504,13 @@ private TypeSymbol GetTypeByNameOrThrow(
if (tokenType == HandleKind.AssemblyReference)
{
- // TODO: Can refer to the containing assembly?
isNoPiaLocalType = false;
- return LookupTopLevelTypeDefSymbol(Module.GetAssemblyReferenceIndexOrThrow((AssemblyReferenceHandle)tokenResolutionScope), ref fullName);
+ var assemblyRef = (AssemblyReferenceHandle)tokenResolutionScope;
+ if (assemblyRef.IsNil)
+ {
+ throw new BadImageFormatException();
+ }
+ return LookupTopLevelTypeDefSymbol(Module.GetAssemblyReferenceIndexOrThrow(assemblyRef), ref fullName);
}
if (tokenType == HandleKind.ModuleReference)
diff --git a/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/Metadata/PE/HasUnsupportedMetadata.vb b/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/Metadata/PE/HasUnsupportedMetadata.vb
index f6ea3ba00e86e..b9714181c75a1 100644
--- a/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/Metadata/PE/HasUnsupportedMetadata.vb
+++ b/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/Metadata/PE/HasUnsupportedMetadata.vb
@@ -1,16 +1,13 @@
' 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.Runtime.CompilerServices
-Imports CompilationCreationTestHelpers
+Imports System.Collections.Immutable
Imports Microsoft.CodeAnalysis.Test.Utilities
-Imports Microsoft.CodeAnalysis.Text
Imports Microsoft.CodeAnalysis.VisualBasic
Imports Microsoft.CodeAnalysis.VisualBasic.Symbols.Metadata.PE
Imports Microsoft.CodeAnalysis.VisualBasic.Symbols
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
Imports Roslyn.Test.Utilities
-
Namespace Microsoft.CodeAnalysis.VisualBasic.UnitTests.Symbols.Metadata.PE
Public Class HasUnsupportedMetadata : Inherits BasicTestBase
@@ -435,6 +432,86 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.UnitTests.Symbols.Metadata.PE
Assert.True(tok.HasUnsupportedMetadata)
End Sub
+ '''
+ ''' Throw a (handled) BadImageFormatException from MetadataDecoder
+ ''' for a TypeRef assembly resolution scope with Nil AssemblyRef.
+ '''
+
+
+ Public Sub ResolutionScopeNilAssembly()
+ Dim options = TestOptions.ReleaseDll.WithDeterministic(True)
+ Dim comp1 = CreateCompilationWithMscorlib(
+{"Public Class A
+End Class"},
+ options:=options,
+ assemblyName:="4D94B345-92CE-46BB-891E-048109648A0A")
+ comp1.VerifyDiagnostics()
+ Dim bytes1 = comp1.EmitToArray()
+ Dim ref1 = AssemblyMetadata.CreateFromImage(bytes1).GetReference()
+
+ Dim comp2 = CreateCompilationWithMscorlib(
+{"Public Class B
+ Inherits A
+End Class"},
+ options:=options,
+ assemblyName:="D4954046-BDDC-42C4-98F8-7E5573C16C33",
+ references:=New MetadataReference() {ref1})
+ comp2.VerifyDiagnostics()
+ Dim bytes2 = comp2.EmitToArray()
+ ' Construct an unexpected assembly resolution scope from the valid compilation.
+ ' Metadata contains a single TypeRef with assembly resolution scope where the
+ ' scope is AssemblyRef 2: specifically the TypeRef to base class A. Replace that
+ ' assembly resolution scope with AssemblyRef 0 (the unexpected value). In the
+ ' TypeRef signatures below, 10 and 2 are the assembly scopes (AssemblyRef << 2 | 2).
+ ' (To verify, break in MetadataWriter.SerializeTypeRefTable when emitting comp2.)
+ bytes2 = ReplaceBytes(bytes2, {10, 0, 82, 0, 0, 0}, {2, 0, 82, 0, 0, 0})
+ Dim ref2 = AssemblyMetadata.CreateFromImage(bytes2).GetReference()
+
+ Dim comp3 = CreateCompilationWithMscorlib(
+{"Class C
+ Shared Sub Main()
+ Dim o As New B()
+ End Sub
+End Class"},
+ options:=options,
+ references:=New MetadataReference() {ref2})
+ comp3.VerifyDiagnostics()
+
+ Dim tree = comp3.SyntaxTrees(0)
+ Dim model = comp3.GetSemanticModel(tree)
+ Dim decl = tree.GetRoot().DescendantNodes.OfType(Of ObjectCreationExpressionSyntax).Single()
+ Dim type = DirectCast(model.GetTypeInfo(decl).Type, TypeSymbol)
+ Assert.Equal("B", type.ToTestDisplayString())
+ Assert.False(type.IsErrorType())
+ Assert.True(type.BaseType.IsErrorType()) ' Handled exception decoding base type TypeRef.
+ End Sub
+
+ Private Shared Function ReplaceBytes(bytes As ImmutableArray(Of Byte), before As Byte(), after As Byte()) As ImmutableArray(Of Byte)
+ Dim index = IndexOfBytes(bytes, before, 0)
+ Debug.Assert(index >= 0)
+ Debug.Assert(IndexOfBytes(bytes, before, index + 1) < 0)
+ Dim builder = ArrayBuilder(Of Byte).GetInstance()
+ builder.AddRange(bytes.Take(index))
+ builder.AddRange(after)
+ builder.AddRange(bytes.Skip(index + before.Length))
+ Return builder.ToImmutableAndFree()
+ End Function
+
+ Private Shared Function IndexOfBytes(bytes As ImmutableArray(Of Byte), pattern As Byte(), startIndex As Integer) As Integer
+ Dim n = bytes.Length
+ Dim m = pattern.Length
+ For i = startIndex To n - m - 1
+ For j = 0 To m - 1
+ If bytes(i + j) <> pattern(j) Then
+ GoTo EndOfLoop
+ End If
+ Next
+ Return i
+EndOfLoop:
+ Next
+ Return -1
+ End Function
+
End Class
End Namespace