From a423e7da9ccd2b513dfc1c8eedd3cc343e05301b Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Fri, 13 Oct 2017 19:41:31 +0200 Subject: [PATCH] Expand checks in ExtractStringValuesFromInitBlock and MatchAddCall --- .../IL/Instructions/PatternMatching.cs | 5 +++ .../IL/Transforms/SwitchOnStringTransform.cs | 37 +++++++++++++++---- 2 files changed, 34 insertions(+), 8 deletions(-) diff --git a/ICSharpCode.Decompiler/IL/Instructions/PatternMatching.cs b/ICSharpCode.Decompiler/IL/Instructions/PatternMatching.cs index 0510b8c87..3382d6926 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/PatternMatching.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/PatternMatching.cs @@ -27,6 +27,11 @@ namespace ICSharpCode.Decompiler.IL return OpCode == OpCode.LdcI4 && ((LdcI4)this).Value == val; } + public bool MatchLdcF(double value) + { + return MatchLdcF(out var v) && v == value; + } + /// /// Matches either LdcI4 or LdcI8. /// diff --git a/ICSharpCode.Decompiler/IL/Transforms/SwitchOnStringTransform.cs b/ICSharpCode.Decompiler/IL/Transforms/SwitchOnStringTransform.cs index 1f7d0f232..670e870c8 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/SwitchOnStringTransform.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/SwitchOnStringTransform.cs @@ -207,7 +207,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms return false; if (!exitBlockJump.MatchBranch(out var nullValueCaseBlock)) return false; - if (!(condition.MatchCompEquals(out var left, out var right) && right.MatchLdNull() && (left.Match(switchValue).Success || left.MatchLdLoc(switchValueVar)))) + if (!(condition.MatchCompEquals(out var left, out var right) && right.MatchLdNull() + && ((SemanticHelper.IsPure(switchValue.Flags) && left.Match(switchValue).Success) || left.MatchLdLoc(switchValueVar)))) return false; var nextBlockJump = instructions.ElementAtOrDefault(i + 1) as Branch; if (nextBlockJump == null || nextBlockJump.TargetBlock.IncomingEdgeCount != 1) @@ -311,15 +312,31 @@ namespace ICSharpCode.Decompiler.IL.Transforms bool ExtractStringValuesFromInitBlock(Block block, out List values, Block targetBlock, IType dictionaryType, IField dictionaryField) { values = null; - if (!(block.Instructions[0].MatchStLoc(out var dictVar, out var newObjDict) && - newObjDict is NewObj newObj && newObj.Arguments.Count >= 1 && newObj.Arguments[0].MatchLdcI4(out var valuesLength))) + // stloc dictVar(newobj Dictionary..ctor(ldc.i4 valuesLength)) + // -or- + // stloc dictVar(newobj Hashtable..ctor(ldc.i4 capacity, ldc.f loadFactor)) + if (!(block.Instructions[0].MatchStLoc(out var dictVar, out var newObjDict) && newObjDict is NewObj newObj)) + return false; + if (!newObj.Method.DeclaringType.Equals(dictionaryType)) return false; + int valuesLength = 0; + if (newObj.Arguments.Count == 2) { + if (!newObj.Arguments[0].MatchLdcI4(out valuesLength)) + return false; + if (!newObj.Arguments[1].MatchLdcF(0.5)) + return false; + } else if (newObj.Arguments.Count == 1) { + if (!newObj.Arguments[0].MatchLdcI4(out valuesLength)) + return false; + } values = new List(valuesLength); int i = 0; - while (i + 1 < block.Instructions.Count - 2 && MatchAddCall(block.Instructions[i + 1], dictVar, i, out var value)) { + while (MatchAddCall(dictionaryType, block.Instructions[i + 1], dictVar, i, out var value)) { values.Add(value); i++; } + // final store to compiler-generated variable: + // volatile.stobj dictionaryType(ldsflda dictionaryField, ldloc dictVar) if (!(block.Instructions[i + 1].MatchStObj(out var loadField, out var dictVarLoad, out var dictType) && dictType.Equals(dictionaryType) && loadField.MatchLdsFlda(out var dictField) && dictField.Equals(dictionaryField)) && dictVarLoad.MatchLdLoc(dictVar)) @@ -332,12 +349,16 @@ namespace ICSharpCode.Decompiler.IL.Transforms /// -or- /// call Add(ldloc dictVar, ldstr value, box System.Int32(ldc.i4 index)) /// - bool MatchAddCall(ILInstruction inst, ILVariable dictVar, int index, out string value) + bool MatchAddCall(IType dictionaryType, ILInstruction inst, ILVariable dictVar, int index, out string value) { value = null; - return inst is Call c && c.Method.Name == "Add" && c.Arguments.Count == 3 && - c.Arguments[0].MatchLdLoc(dictVar) && c.Arguments[1].MatchLdStr(out value) && - (c.Arguments[2].MatchLdcI4(index) || (c.Arguments[2].MatchBox(out var arg, out _) && arg.MatchLdcI4(index))); + if (!(inst is Call c && c.Method.Name == "Add" && c.Arguments.Count == 3)) + return false; + if (!(c.Arguments[0].MatchLdLoc(dictVar) && c.Arguments[1].MatchLdStr(out value))) + return false; + if (!(c.Method.DeclaringType.Equals(dictionaryType) && c.Method.IsStatic)) + return false; + return (c.Arguments[2].MatchLdcI4(index) || (c.Arguments[2].MatchBox(out var arg, out _) && arg.MatchLdcI4(index))); } bool IsStringToIntDictionary(IType dictionaryType)