Skip to content

IndexOutOfRangeException in WinMD assembly resolution #58319

@andrew-boyarshin

Description

@andrew-boyarshin

Description

<PackageReference Include="System.Reflection.MetadataLoadContext" Version="6.0.0-preview.7.21377.19" />
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;

// Get the array of runtime assemblies.
// This will allow us to at least inspect types depending only on BCL.
var runtimeAssemblies = Directory.GetFiles(RuntimeEnvironment.GetRuntimeDirectory(), "*.dll");

// Create the list of assembly paths consisting of runtime assemblies and the input file.
const string? metadataFile = @"C:\Windows\System32\WinMetadata\Windows.Foundation.winmd";
List<string> paths = new(runtimeAssemblies.Append(metadataFile));

// Create MetadataLoadContext that can resolve assemblies using the created list.
PathAssemblyResolver resolver = new(paths);
MetadataLoadContext mlc = new(resolver);

foreach (var type in mlc.LoadFromAssemblyPath(metadataFile).GetTypes())
{
    var _ = type.IsValueType;
}

AssemblyReferenceHandle is "virtual" (Treatment is TypeRefTreatment.SystemDelegate, that gives AssemblyReferenceHandle.VirtualIndex.System_Runtime (0) RowID), but EcmaResolver is not prepared to handle that properly, instead, it tries to use AssemblyRefTable (MetadataTable), which obviously fails.

A bit of context:

case HandleKind.AssemblyReference:
{
AssemblyReferenceHandle arh = (AssemblyReferenceHandle)scope;
RoAssembly assembly = arh.ResolveAssembly(module);

public T GetOrAdd(EntityHandle handle, C context, Func<EntityHandle, C, T> factory)
{
Debug.Assert(!handle.IsNil);
Debug.Assert(factory != null);
int index = handle.GetToken().GetTokenRowNumber() - 1;
T?[] table = _table;
T? result = Volatile.Read(ref table[index]);

Configuration

.NET SDK 6.0.100-rc.2.21428.3, Windows 10.0.22000 x64

Regression?

Unlikely, but I don't know for sure.

Other information

System.IndexOutOfRangeException: Index was outside the bounds of the array.
   at System.Reflection.TypeLoading.Ecma.MetadataTable`2.GetOrAdd(EntityHandle handle, C context, Func`3 factory)
   at System.Reflection.TypeLoading.Ecma.EcmaResolver.ResolveToAssemblyOrExceptionAssembly(AssemblyReferenceHandle handle, EcmaModule module)
   at System.Reflection.TypeLoading.Ecma.EcmaResolver.TryResolveAssembly(AssemblyReferenceHandle handle, EcmaModule module, Exception& e)
   at System.Reflection.TypeLoading.Ecma.EcmaResolver.ResolveAssembly(AssemblyReferenceHandle handle, EcmaModule module)
   at System.Reflection.TypeLoading.Ecma.EcmaResolver.ComputeTypeRefResolution(TypeReferenceHandle handle, EcmaModule module)
   at System.Reflection.TypeLoading.Ecma.EcmaResolver.<>c.<.cctor>b__15_1(EntityHandle h, EcmaModule m)
   at System.Reflection.TypeLoading.Ecma.MetadataTable`2.GetOrAdd(EntityHandle handle, C context, Func`3 factory)
   at System.Reflection.TypeLoading.Ecma.EcmaResolver.ResolveTypeRef(TypeReferenceHandle handle, EcmaModule module)
   at System.Reflection.TypeLoading.Ecma.EcmaResolver.ResolveTypeDefRefOrSpec(EntityHandle handle, EcmaModule module, TypeContext& typeContext)
   at System.Reflection.TypeLoading.Ecma.EcmaDefinitionType.SpecializeBaseType(RoType[] instantiation)
   at System.Reflection.TypeLoading.RoDefinitionType.ComputeBaseTypeWithoutDesktopQuirk()
   at System.Reflection.TypeLoading.RoType.ComputeBaseType()
   at System.Reflection.TypeLoading.RoType.GetRoBaseType()
   at System.Reflection.TypeLoading.RoType.get_BaseType()
   at System.Reflection.TypeLoading.RoType.ComputeBaseTypeClassification()
   at System.Reflection.TypeLoading.RoType.GetBaseTypeClassification()
   at System.Reflection.TypeLoading.RoType.IsValueTypeImpl()
   at System.Type.get_IsValueType()

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions