Browse Source

Validate uses of display-class variable copies before removing them

pull/2005/head
Siegfried Pammer 5 years ago
parent
commit
101aba3362
  1. 68
      ICSharpCode.Decompiler/IL/Transforms/TransformDisplayClassUsage.cs

68
ICSharpCode.Decompiler/IL/Transforms/TransformDisplayClassUsage.cs

@ -170,18 +170,42 @@ namespace ICSharpCode.Decompiler.IL.Transforms
} }
} }
} }
}
bool ValidateDisplayClassUses(ILVariable v, DisplayClass displayClass, bool readOnly = false)
{
foreach (var ldloc in v.LoadInstructions) {
if (!ValidateUse(displayClass, ldloc))
return false;
}
foreach (var ldloca in v.AddressInstructions) {
if (!ValidateUse(displayClass, ldloca))
return false;
}
return true;
bool ValidateDisplayClassUses(ILVariable v, DisplayClass displayClass) bool ValidateUse(DisplayClass container, ILInstruction use)
{ {
foreach (var ldloc in v.LoadInstructions) { IField field;
if (!ValidateUse(displayClass, ldloc)) switch (use.Parent) {
return false; case LdFlda ldflda when ldflda.MatchLdFlda(out _, out field):
} var keyField = (IField)field.MemberDefinition;
foreach (var ldloca in v.AddressInstructions) { if (!container.VariablesToDeclare.TryGetValue(keyField, out VariableToDeclare variable) || variable == null) {
if (!ValidateUse(displayClass, ldloca)) if (readOnly)
return false;
variable = AddVariable(container, null, field);
}
container.VariablesToDeclare[keyField] = variable;
return variable != null;
case StObj stobj when stobj.MatchStObj(out var target, out ILInstruction value, out _) && value == use:
if (target.MatchLdFlda(out var load, out field) && load.MatchLdLocRef(out var otherVariable) && displayClasses.TryGetValue(otherVariable, out var otherDisplayClass)) {
if (otherDisplayClass.VariablesToDeclare.TryGetValue((IField)field.MemberDefinition, out var declaredVar))
return declaredVar.CanPropagate;
}
return true;
default:
return false; return false;
} }
return true;
} }
} }
@ -285,8 +309,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
private Block FindDisplayStructInitBlock(ILVariable v) private Block FindDisplayStructInitBlock(ILVariable v)
{ {
var root = v.Function.Body; var root = v.Function.Body;
var block = Visit(root)?.Ancestors.OfType<Block>().FirstOrDefault(); return Visit(root)?.Ancestors.OfType<Block>().FirstOrDefault();
return block;
ILInstruction Visit(ILInstruction inst) ILInstruction Visit(ILInstruction inst)
{ {
@ -417,28 +440,6 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return variable; return variable;
} }
bool ValidateUse(DisplayClass container, ILInstruction use)
{
IField field;
switch (use.Parent) {
case LdFlda ldflda when ldflda.MatchLdFlda(out _, out field):
var keyField = (IField)field.MemberDefinition;
if (!container.VariablesToDeclare.TryGetValue(keyField, out VariableToDeclare variable) || variable == null) {
variable = AddVariable(container, null, field);
}
container.VariablesToDeclare[keyField] = variable;
return variable != null;
case StObj stobj when stobj.MatchStObj(out var target, out ILInstruction value, out _) && value == use:
if (target.MatchLdFlda(out var load, out field) && load.MatchLdLocRef(out var otherVariable) && displayClasses.TryGetValue(otherVariable, out var displayClass)) {
if (displayClass.VariablesToDeclare.TryGetValue((IField)field.MemberDefinition, out var declaredVar))
return declaredVar.CanPropagate;
}
return true;
default:
return false;
}
}
private void Transform(ILFunction function) private void Transform(ILFunction function)
{ {
VisitILFunction(function); VisitILFunction(function);
@ -630,8 +631,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
} }
return; return;
} }
// TODO : this is dangerous! if (inst.Value.MatchLdLocRef(out var otherVariable) && displayClasses.TryGetValue(otherVariable, out displayClass) && ValidateDisplayClassUses(inst.Variable, displayClass)) {
if (inst.Value.MatchLdLocRef(out var otherVariable) && displayClasses.TryGetValue(otherVariable, out displayClass)) {
instructionsToRemove.Add(inst); instructionsToRemove.Add(inst);
displayClasses.Add(inst.Variable, displayClass); displayClasses.Add(inst.Variable, displayClass);
} }

Loading…
Cancel
Save