Browse Source

Fix #2280: Add additional checks to GenerateVariableName

pull/2289/head
Siegfried Pammer 5 years ago
parent
commit
669fe6417e
  1. 5
      ICSharpCode.Decompiler/CSharp/Transforms/DeclareVariables.cs
  2. 53
      ICSharpCode.Decompiler/IL/Transforms/AssignVariableNames.cs

5
ICSharpCode.Decompiler/CSharp/Transforms/DeclareVariables.cs

@ -202,7 +202,10 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
var v = function.RegisterVariable( var v = function.RegisterVariable(
VariableKind.StackSlot, VariableKind.StackSlot,
type, type,
AssignVariableNames.GenerateVariableName(function, type, stmt.Expression.Annotations.OfType<ILInstruction>().Where(AssignVariableNames.IsSupportedInstruction).FirstOrDefault()) AssignVariableNames.GenerateVariableName(function, type,
stmt.Expression.Annotations.OfType<ILInstruction>()
.Where(AssignVariableNames.IsSupportedInstruction).FirstOrDefault(),
mustResolveConflicts: true)
); );
stmt.Expression = new AssignmentExpression( stmt.Expression = new AssignmentExpression(
new IdentifierExpression(v.Name).WithRR(new ILVariableResolveResult(v, v.Type)), new IdentifierExpression(v.Name).WithRR(new ILVariableResolveResult(v, v.Type)),

53
ICSharpCode.Decompiler/IL/Transforms/AssignVariableNames.cs

@ -52,7 +52,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
}; };
ILTransformContext context; ILTransformContext context;
string[] currentLowerCaseTypeOrMemberNames; List<string> currentLowerCaseTypeOrMemberNames;
Dictionary<string, int> reservedVariableNames; Dictionary<string, int> reservedVariableNames;
Dictionary<MethodDefinitionHandle, string> localFunctionMapping; Dictionary<MethodDefinitionHandle, string> localFunctionMapping;
HashSet<ILVariable> loopCounters; HashSet<ILVariable> loopCounters;
@ -63,7 +63,16 @@ namespace ICSharpCode.Decompiler.IL.Transforms
this.context = context; this.context = context;
reservedVariableNames = new Dictionary<string, int>(); reservedVariableNames = new Dictionary<string, int>();
currentLowerCaseTypeOrMemberNames = CollectAllLowerCaseTypeOrMemberNames(function.Method.DeclaringTypeDefinition).ToArray(); currentLowerCaseTypeOrMemberNames = new List<string>();
var currentLowerCaseMemberNames = CollectAllLowerCaseMemberNames(function.Method.DeclaringTypeDefinition);
foreach (var name in currentLowerCaseMemberNames)
currentLowerCaseTypeOrMemberNames.Add(name);
var currentLowerCaseTypeNames = CollectAllLowerCaseTypeNames(function.Method.DeclaringTypeDefinition);
foreach (var name in currentLowerCaseTypeNames)
{
currentLowerCaseTypeOrMemberNames.Add(name);
AddExistingName(reservedVariableNames, name);
}
localFunctionMapping = new Dictionary<MethodDefinitionHandle, string>(); localFunctionMapping = new Dictionary<MethodDefinitionHandle, string>();
loopCounters = CollectLoopCounters(function); loopCounters = CollectLoopCounters(function);
foreach (var f in function.Descendants.OfType<ILFunction>()) foreach (var f in function.Descendants.OfType<ILFunction>())
@ -147,26 +156,27 @@ namespace ICSharpCode.Decompiler.IL.Transforms
} }
} }
IEnumerable<string> CollectAllLowerCaseTypeOrMemberNames(ITypeDefinition type) static IEnumerable<string> CollectAllLowerCaseMemberNames(ITypeDefinition type)
{ {
foreach (var item in type.GetMembers(m => IsLowerCase(m.Name))) foreach (var item in type.GetMembers(m => IsLowerCase(m.Name)))
yield return item.Name; yield return item.Name;
}
static IEnumerable<string> CollectAllLowerCaseTypeNames(ITypeDefinition type)
{
foreach (var item in type.ParentModule.TopLevelTypeDefinitions) foreach (var item in type.ParentModule.TopLevelTypeDefinitions)
{ {
if (item.Namespace != type.Namespace) if (item.Namespace != type.Namespace)
continue; continue;
if (IsLowerCase(item.Name)) if (IsLowerCase(item.Name))
{
AddExistingName(reservedVariableNames, item.Name);
yield return item.Name; yield return item.Name;
}
} }
}
static bool IsLowerCase(string name) static bool IsLowerCase(string name)
{ {
return name.Length > 0 && char.ToLower(name[0]) == name[0]; return name.Length > 0 && char.ToLower(name[0]) == name[0];
}
} }
bool IsSetOrEventAccessor(IMethod method) bool IsSetOrEventAccessor(IMethod method)
@ -678,7 +688,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return variableType; return variableType;
} }
static Dictionary<string, int> CollectReservedVariableNames(ILFunction function, ILVariable existingVariable) static Dictionary<string, int> CollectReservedVariableNames(ILFunction function,
ILVariable existingVariable, bool mustResolveConflicts)
{ {
var reservedVariableNames = new Dictionary<string, int>(); var reservedVariableNames = new Dictionary<string, int>();
var rootFunction = function.Ancestors.OfType<ILFunction>().Single(f => f.Parent == null); var rootFunction = function.Ancestors.OfType<ILFunction>().Single(f => f.Parent == null);
@ -694,12 +705,18 @@ namespace ICSharpCode.Decompiler.IL.Transforms
AddExistingName(reservedVariableNames, v.Name); AddExistingName(reservedVariableNames, v.Name);
} }
} }
foreach (var f in rootFunction.Method.DeclaringTypeDefinition.GetFields().Select(f => f.Name)) if (mustResolveConflicts)
AddExistingName(reservedVariableNames, f); {
var memberNames = CollectAllLowerCaseMemberNames(function.Method.DeclaringTypeDefinition)
.Concat(CollectAllLowerCaseTypeNames(function.Method.DeclaringTypeDefinition));
foreach (var name in memberNames)
AddExistingName(reservedVariableNames, name);
}
return reservedVariableNames; return reservedVariableNames;
} }
internal static string GenerateForeachVariableName(ILFunction function, ILInstruction valueContext, ILVariable existingVariable = null) internal static string GenerateForeachVariableName(ILFunction function, ILInstruction valueContext,
ILVariable existingVariable = null, bool mustResolveConflicts = false)
{ {
if (function == null) if (function == null)
throw new ArgumentNullException(nameof(function)); throw new ArgumentNullException(nameof(function));
@ -707,7 +724,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
{ {
return existingVariable.Name; return existingVariable.Name;
} }
var reservedVariableNames = CollectReservedVariableNames(function, existingVariable); var reservedVariableNames = CollectReservedVariableNames(function, existingVariable, mustResolveConflicts);
string baseName = GetNameFromInstruction(valueContext); string baseName = GetNameFromInstruction(valueContext);
if (string.IsNullOrEmpty(baseName)) if (string.IsNullOrEmpty(baseName))
@ -756,11 +773,13 @@ namespace ICSharpCode.Decompiler.IL.Transforms
} }
} }
internal static string GenerateVariableName(ILFunction function, IType type, ILInstruction valueContext = null, ILVariable existingVariable = null) internal static string GenerateVariableName(ILFunction function, IType type,
ILInstruction valueContext = null, ILVariable existingVariable = null,
bool mustResolveConflicts = false)
{ {
if (function == null) if (function == null)
throw new ArgumentNullException(nameof(function)); throw new ArgumentNullException(nameof(function));
var reservedVariableNames = CollectReservedVariableNames(function, existingVariable); var reservedVariableNames = CollectReservedVariableNames(function, existingVariable, mustResolveConflicts);
string baseName = valueContext != null ? GetNameFromInstruction(valueContext) ?? GetNameByType(type) : GetNameByType(type); string baseName = valueContext != null ? GetNameFromInstruction(valueContext) ?? GetNameByType(type) : GetNameByType(type);
string proposedName = "obj"; string proposedName = "obj";

Loading…
Cancel
Save