Browse Source

Fix crash in TryEncodingV2, if there are multiple extension groups with the same target type, but different extension parameter name.

pull/3648/head
Siegfried Pammer 1 week ago
parent
commit
5f0e767c7d
  1. 46
      ICSharpCode.Decompiler.Tests/TypeSystem/TypeSystemTestCase.cs
  2. 37
      ICSharpCode.Decompiler/TypeSystem/ExtensionInfo.cs

46
ICSharpCode.Decompiler.Tests/TypeSystem/TypeSystemTestCase.cs

@ -785,5 +785,51 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem
{ {
} }
} }
extension(int number)
{
public int Squared => number * number;
}
extension(string input)
{
public void Method() { }
public void Method(char c) { }
public string AsString => input.ToString();
public string Test {
get => "Test";
set { }
}
public static void StaticMethodOnString() { }
public static void StaticMethodOnString(double x) { }
public static string StaticPropertyOnString => "StaticProperty";
public static void GenericMethodOnString<T>(T value)
{
}
}
extension<T>(T input)
{
public void Method() { }
public void Method(char c) { }
public string AsString => input.ToString();
public string Test {
get => "Test";
set { }
}
public static void StaticMethodOnGeneric() { }
public static void StaticMethodOnGeneric(double x) { }
public static string StaticPropertyOnGeneric => "StaticProperty";
public static void GenericMethodOnGeneric<U>(U value)
{
}
}
extension<T, T2>(T input)
{
public void StaticMethodOnGenericTwoParams(T2 x)
{
}
}
} }
} }

37
ICSharpCode.Decompiler/TypeSystem/ExtensionInfo.cs

@ -40,14 +40,14 @@ namespace ICSharpCode.Decompiler.TypeSystem
var metadata = module.MetadataFile.Metadata; var metadata = module.MetadataFile.Metadata;
foreach (var extGroup in extensionContainer.NestedTypes) foreach (var nestedType in extensionContainer.NestedTypes)
{ {
if (TryEncodingV1(extGroup)) if (TryEncodingV1(nestedType))
{ {
continue; continue;
} }
TryEncodingV2(extGroup); TryEncodingV2(nestedType);
} }
bool TryEncodingV1(ITypeDefinition extGroup) bool TryEncodingV1(ITypeDefinition extGroup)
@ -90,23 +90,30 @@ namespace ICSharpCode.Decompiler.TypeSystem
return true; return true;
} }
bool TryEncodingV2(ITypeDefinition extGroup) bool TryEncodingV2(ITypeDefinition extensionGroupsContainer)
{ {
if (!(extGroup is { Kind: TypeKind.Class, IsSealed: true } // there exists one nested type per extension target type
&& extGroup.Name.StartsWith("<G>$", StringComparison.Ordinal))) if (!(extensionGroupsContainer is { Kind: TypeKind.Class, IsSealed: true }
&& extensionGroupsContainer.Name.StartsWith("<G>$", StringComparison.Ordinal)))
{ {
return false; return false;
} }
var markerType = extGroup.NestedTypes.SingleOrDefault(t => t.Name.StartsWith("<M>$", StringComparison.Ordinal) && t.IsStatic); // if there are multiple extension-blocks with the same target type,
var marker = markerType?.Methods.SingleOrDefault(m => m.Name == "<Extension>$" && m.IsStatic && m.Parameters.Count == 1); // but different names for the extension parameter,
// there is a separate markerType, so there are multiple marker types per
if (markerType == null || marker == null) // target type
return false; foreach (var markerType in extensionGroupsContainer.NestedTypes)
{
if (!(markerType.Name.StartsWith("<M>$", StringComparison.Ordinal) && markerType.IsStatic))
continue;
var marker = markerType.Methods.SingleOrDefault(m => m.Name == "<Extension>$" && m.IsStatic && m.Parameters.Count == 1);
if (marker == null)
continue;
TypeDefinition td = metadata.GetTypeDefinition((TypeDefinitionHandle)extGroup.MetadataToken); TypeDefinition td = metadata.GetTypeDefinition((TypeDefinitionHandle)extensionGroupsContainer.MetadataToken);
List<IMethod> extensionMethods = []; List<IMethod> extensionMethods = [];
ITypeParameter[] extensionGroupTypeParameters = new ITypeParameter[extGroup.TypeParameterCount]; ITypeParameter[] extensionGroupTypeParameters = new ITypeParameter[extensionGroupsContainer.TypeParameterCount];
// For easier access to accessors we use SRM // For easier access to accessors we use SRM
foreach (var h in td.GetMethods()) foreach (var h in td.GetMethods())
@ -126,7 +133,9 @@ namespace ICSharpCode.Decompiler.TypeSystem
extensionMethods.Add(method); extensionMethods.Add(method);
} }
CollectImplementationMethods(extGroup, marker, extensionMethods, extensionGroupTypeParameters); CollectImplementationMethods(extensionGroupsContainer, marker, extensionMethods, extensionGroupTypeParameters);
}
return true; return true;
} }

Loading…
Cancel
Save