Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 16 additions & 1 deletion Confuser.Renamer/Analyzers/VTableAnalyzer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,22 @@ private static void SetupOverwriteReferences(INameService service, ICollection<M
methodDef.Overrides.Add(new MethodOverride(methodDef, target));
}
else if (target is IMemberDef targetDef) {
CreateOverrideReference(service, methodDef, targetDef);
// Reaching this place means that a slot of the base type is overwritten by a specific interface.
// In case the this type is implementing the interface responsible for this, we need to declare
// this as an override reference. If the base type is implementing the interface (as well), this
// declaration is redundant.
var overrideRefRequired = true;
if (targetDef.DeclaringType.IsInterface) {
var baseTypeDef = thisType.BaseType?.ResolveTypeDef();
if (!(baseTypeDef is null)) {
var baseTypeVTable = service.GetVTables()[baseTypeDef];
if (baseTypeVTable.InterfaceSlots.TryGetValue(targetDef.DeclaringType.ToTypeSig(), out var ifcSlots)) {
overrideRefRequired = !ifcSlots.Contains(slot);
}
}
}
if (overrideRefRequired)
CreateOverrideReference(service, methodDef, targetDef);
}
}

Expand Down
18 changes: 3 additions & 15 deletions Confuser.Renamer/VTable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ public class VTable {
internal VTable(TypeSig type) {
Type = type;
Slots = new List<VTableSlot>();
InterfaceSlots = new Dictionary<TypeSig, IList<VTableSlot>>();
InterfaceSlots = new Dictionary<TypeSig, IList<VTableSlot>>(TypeEqualityComparer.Instance);
}

public TypeSig Type { get; private set; }
Expand All @@ -107,23 +107,11 @@ internal VTable(TypeSig type) {
public IDictionary<TypeSig, IList<VTableSlot>> InterfaceSlots { get; private set; }

class VTableConstruction {
class TypeSigComparer : IEqualityComparer<TypeSig> {
public bool Equals(TypeSig x, TypeSig y) {
return new SigComparer().Equals(x, y);
}

public int GetHashCode(TypeSig obj) {
return new SigComparer().GetHashCode(obj);
}

public static readonly TypeSigComparer Instance = new TypeSigComparer();
}

// All virtual method slots, excluding interfaces
public List<VTableSlot> AllSlots = new List<VTableSlot>();
// All visible virtual method slots (i.e. excluded those being shadowed)
public Dictionary<VTableSignature, VTableSlot> SlotsMap = new Dictionary<VTableSignature, VTableSlot>();
public Dictionary<TypeSig, ILookup<VTableSignature, VTableSlot>> InterfaceSlots = new Dictionary<TypeSig, ILookup<VTableSignature, VTableSlot>>(TypeSigComparer.Instance);
public Dictionary<TypeSig, ILookup<VTableSignature, VTableSlot>> InterfaceSlots = new Dictionary<TypeSig, ILookup<VTableSignature, VTableSlot>>(TypeEqualityComparer.Instance);
}

public IEnumerable<VTableSlot> FindSlots(IMethod method) {
Expand Down Expand Up @@ -252,7 +240,7 @@ public static VTable ConstructVTable(TypeDef typeDef, VTableStorage storage) {

// Populate result V-table
ret.InterfaceSlots = vTbl.InterfaceSlots.ToDictionary(
kvp => kvp.Key, kvp => (IList<VTableSlot>)kvp.Value.SelectMany(g => g).ToList());
kvp => kvp.Key, kvp => (IList<VTableSlot>)kvp.Value.SelectMany(g => g).ToList(), TypeEqualityComparer.Instance);

foreach (var slot in vTbl.AllSlots) {
ret.Slots.Add(slot);
Expand Down
36 changes: 33 additions & 3 deletions Confuser2.sln
Original file line number Diff line number Diff line change
Expand Up @@ -111,11 +111,15 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "244_ClrProtection", "Tests\
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "244_ClrProtection.Test", "Tests\244_ClrProtection.Test\244_ClrProtection.Test.csproj", "{3ADB8BB1-AE14-49DA-A7E1-1C0D9BEB76E9}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "306_ComplexClassStructureRename.Lib", "Tests\306_ComplexClassStructureRename.Lib\306_ComplexClassStructureRename.Lib.csproj", "{FD93D181-2EC5-4863-8A8F-5F8C84C06B35}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "306_ComplexClassStructureRename.Lib", "Tests\306_ComplexClassStructureRename.Lib\306_ComplexClassStructureRename.Lib.csproj", "{FD93D181-2EC5-4863-8A8F-5F8C84C06B35}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "306_ComplexClassStructureRename", "Tests\306_ComplexClassStructureRename\306_ComplexClassStructureRename.csproj", "{1B52A3D9-014C-4CBF-BB98-09080D9A8D16}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "306_ComplexClassStructureRename", "Tests\306_ComplexClassStructureRename\306_ComplexClassStructureRename.csproj", "{1B52A3D9-014C-4CBF-BB98-09080D9A8D16}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "306_ComplexClassStructureRename.Test", "Tests\306_ComplexClassStructureRename.Test\306_ComplexClassStructureRename.Test.csproj", "{13431429-2DB6-480F-B73F-CA019FE759E3}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "306_ComplexClassStructureRename.Test", "Tests\306_ComplexClassStructureRename.Test\306_ComplexClassStructureRename.Test.csproj", "{13431429-2DB6-480F-B73F-CA019FE759E3}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "342_InterfaceRenamingLoop", "Tests\342_InterfaceRenamingLoop\342_InterfaceRenamingLoop.csproj", "{382B6332-4A57-458D-96EB-B312688A7604}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "342_InterfaceRenamingLoop.Test", "Tests\342_InterfaceRenamingLoop.Test\342_InterfaceRenamingLoop.Test.csproj", "{EC62CE1D-ADD7-419A-84A9-D6A04E866197}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Expand Down Expand Up @@ -727,6 +731,30 @@ Global
{13431429-2DB6-480F-B73F-CA019FE759E3}.Release|x64.Build.0 = Release|Any CPU
{13431429-2DB6-480F-B73F-CA019FE759E3}.Release|x86.ActiveCfg = Release|Any CPU
{13431429-2DB6-480F-B73F-CA019FE759E3}.Release|x86.Build.0 = Release|Any CPU
{382B6332-4A57-458D-96EB-B312688A7604}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{382B6332-4A57-458D-96EB-B312688A7604}.Debug|Any CPU.Build.0 = Debug|Any CPU
{382B6332-4A57-458D-96EB-B312688A7604}.Debug|x64.ActiveCfg = Debug|Any CPU
{382B6332-4A57-458D-96EB-B312688A7604}.Debug|x64.Build.0 = Debug|Any CPU
{382B6332-4A57-458D-96EB-B312688A7604}.Debug|x86.ActiveCfg = Debug|Any CPU
{382B6332-4A57-458D-96EB-B312688A7604}.Debug|x86.Build.0 = Debug|Any CPU
{382B6332-4A57-458D-96EB-B312688A7604}.Release|Any CPU.ActiveCfg = Release|Any CPU
{382B6332-4A57-458D-96EB-B312688A7604}.Release|Any CPU.Build.0 = Release|Any CPU
{382B6332-4A57-458D-96EB-B312688A7604}.Release|x64.ActiveCfg = Release|Any CPU
{382B6332-4A57-458D-96EB-B312688A7604}.Release|x64.Build.0 = Release|Any CPU
{382B6332-4A57-458D-96EB-B312688A7604}.Release|x86.ActiveCfg = Release|Any CPU
{382B6332-4A57-458D-96EB-B312688A7604}.Release|x86.Build.0 = Release|Any CPU
{EC62CE1D-ADD7-419A-84A9-D6A04E866197}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{EC62CE1D-ADD7-419A-84A9-D6A04E866197}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EC62CE1D-ADD7-419A-84A9-D6A04E866197}.Debug|x64.ActiveCfg = Debug|Any CPU
{EC62CE1D-ADD7-419A-84A9-D6A04E866197}.Debug|x64.Build.0 = Debug|Any CPU
{EC62CE1D-ADD7-419A-84A9-D6A04E866197}.Debug|x86.ActiveCfg = Debug|Any CPU
{EC62CE1D-ADD7-419A-84A9-D6A04E866197}.Debug|x86.Build.0 = Debug|Any CPU
{EC62CE1D-ADD7-419A-84A9-D6A04E866197}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EC62CE1D-ADD7-419A-84A9-D6A04E866197}.Release|Any CPU.Build.0 = Release|Any CPU
{EC62CE1D-ADD7-419A-84A9-D6A04E866197}.Release|x64.ActiveCfg = Release|Any CPU
{EC62CE1D-ADD7-419A-84A9-D6A04E866197}.Release|x64.Build.0 = Release|Any CPU
{EC62CE1D-ADD7-419A-84A9-D6A04E866197}.Release|x86.ActiveCfg = Release|Any CPU
{EC62CE1D-ADD7-419A-84A9-D6A04E866197}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -774,6 +802,8 @@ Global
{FD93D181-2EC5-4863-8A8F-5F8C84C06B35} = {356BDB31-853E-43BB-8F9A-D8AC08F69EBB}
{1B52A3D9-014C-4CBF-BB98-09080D9A8D16} = {356BDB31-853E-43BB-8F9A-D8AC08F69EBB}
{13431429-2DB6-480F-B73F-CA019FE759E3} = {356BDB31-853E-43BB-8F9A-D8AC08F69EBB}
{382B6332-4A57-458D-96EB-B312688A7604} = {356BDB31-853E-43BB-8F9A-D8AC08F69EBB}
{EC62CE1D-ADD7-419A-84A9-D6A04E866197} = {356BDB31-853E-43BB-8F9A-D8AC08F69EBB}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {0D937D9E-E04B-4A68-B639-D4260473A388}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net461</TargetFramework>
<RootNamespace>InterfaceRenamingLoop.Test</RootNamespace>
<IsPackable>false</IsPackable>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\342_InterfaceRenamingLoop\342_InterfaceRenamingLoop.csproj" />
<ProjectReference Include="..\Confuser.UnitTest\Confuser.UnitTest.csproj" />
</ItemGroup>

</Project>
35 changes: 35 additions & 0 deletions Tests/342_InterfaceRenamingLoop.Test/InterfaceRenamingLoopTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Confuser.Core;
using Confuser.Core.Project;
using Confuser.Renamer;
using Confuser.UnitTest;
using Xunit;
using Xunit.Abstractions;

namespace InterfaceRenamingLoop.Test {
public class InterfaceRenamingLoopTest : TestBase {
public InterfaceRenamingLoopTest(ITestOutputHelper outputHelper) : base(outputHelper) { }

[Theory]
[MemberData(nameof(RenameInterfaceLoopTestData))]
[Trait("Category", "Protection")]
[Trait("Protection", "rename")]
[Trait("Issue", "https://github.com/mkaring/ConfuserEx/issues/342")]
public async Task RenameInterfaceLoop(string renameMode) =>
await Run(
"342_InterfaceRenamingLoop.exe",
Array.Empty<string>(),
new SettingItem<Protection>("rename") {
{ "mode", renameMode }
},
$"_{renameMode}"
);

public static IEnumerable<object[]> RenameInterfaceLoopTestData() {
foreach (var renameMode in new[] { nameof(RenameMode.Unicode), nameof(RenameMode.Debug), nameof(RenameMode.Sequential) })
yield return new object[] { renameMode };
}
}
}
10 changes: 10 additions & 0 deletions Tests/342_InterfaceRenamingLoop/342_InterfaceRenamingLoop.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net461</TargetFramework>
<RootNamespace>InterfaceRenamingLoop</RootNamespace>
<StartupObject>InterfaceRenamingLoop.Program</StartupObject>
</PropertyGroup>

</Project>
7 changes: 7 additions & 0 deletions Tests/342_InterfaceRenamingLoop/CBase.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace InterfaceRenamingLoop {
internal class CBase {
public virtual void TestEvent(int code, string description) {

}
}
}
10 changes: 10 additions & 0 deletions Tests/342_InterfaceRenamingLoop/ClassA.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace InterfaceRenamingLoop {
internal class ClassA : CBase, IAEvents {
public void TestA(int errorCode) {

}
public override void TestEvent(int code, string description) {

}
}
}
10 changes: 10 additions & 0 deletions Tests/342_InterfaceRenamingLoop/ClassB.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace InterfaceRenamingLoop {
internal class ClassB : ClassA {
}
}
6 changes: 6 additions & 0 deletions Tests/342_InterfaceRenamingLoop/IAEvents.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace InterfaceRenamingLoop {
internal interface IAEvents {
void TestA(int errorCode);
void TestEvent(int errorCode, string description);
}
}
16 changes: 16 additions & 0 deletions Tests/342_InterfaceRenamingLoop/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using System;

namespace InterfaceRenamingLoop {
public class Program {
internal static int Main(string[] args) {
Console.WriteLine("START");

var test = new ClassB();
test.TestEvent(0, "TEST");

Console.WriteLine("END");

return 42;
}
}
}