icsharpcode / ILSpy

.NET Decompiler with support for PDB generation, ReadyToRun, Metadata (&more) - cross-platform!
21.45k stars 3.35k forks source link

decompile bug on "switch case statement " in C# style #375

Closed phtzy closed 7 years ago

phtzy commented 11 years ago

on de decompiled code :(ILSpy version 2.1.0.1603) switch (text2) { { Thread thread = new Thread(new ParameterizedThreadStart(this.getaaa)); thread.Start(parameter); break; }

  {
     Thread thread2 = new Thread(new ParameterizedThreadStart(this.getbbb));
     thread2.Start(parameter);
     break;
   }
       ..............................

You can see, the "case" is missed.

the right decompile code should be: switch (text2) { case 9Gm9Ll2ahtCEvld3rY.Ygi2Fh0hm(69476): { Thread thread = new Thread(new ParameterizedThreadStart(this.getaaa)); thread.Start(parameter); break; } case 9Gm9Ll2ahtCEvld3rY.Ygi2Fh0hm(69506): { Thread thread2 = new Thread(new ParameterizedThreadStart(this.getbbb)); thread2.Start(parameter); break; } ..............................

9Gm9Ll2ahtCEvld3rY.Ygi2Fh0hm(int) will return a string.

some IL codes is ; IL_0076: ldc.i4.7 IL_0077: newobj instance void class [mscorlib]System.Collections.Generic.Dictionary2<string, int32>::.ctor(int32) IL_007c: dup IL_007d: ldc.i4 69476 IL_0082: call string ECo8dAxFuP8Y8VDWW5.9Gm9Ll2ahtCEvld3rY::Ygi2Fh0hm$PST0600074C(int32) IL_0087: ldc.i4.0 IL_0088: call instance void class [mscorlib]System.Collections.Generic.Dictionary2<string, int32>::Add(!0, !1) IL_008d: dup IL_008e: ldc.i4 69506 IL_0093: call string ECo8dAxFuP8Y8VDWW5.9Gm9Ll2ahtCEvld3rY::Ygi2Fh0hm$PST0600074C(int32) IL_0098: ldc.i4.1 IL_0099: call instance void class [mscorlib]System.Collections.Generic.Dictionary`2<string, int32>::Add(!0, !1) IL_009e: dup

.................. IL_00fa: volatile. IL_00fc: ldsfld class [mscorlib]System.Collections.Generic.Dictionary2<string, int32> '<PrivateImplementationDetails>{2B8056D3-4E82-4E47-B144-61AE0A93CF1C}'::'$$method0x600021c-1' IL_0101: ldloc.s 12 IL_0103: ldloca.s 13 IL_0105: call instance bool class [mscorlib]System.Collections.Generic.Dictionary2<string, int32>::TryGetValue(!0, !1&) IL_010a: brfalse IL_021e

        IL_010f: ldloc.s 13
        IL_0111: switch (IL_0137, IL_0158, IL_0179, IL_019a, IL_01bb, IL_01dc, IL_01fd)

        IL_0132: br IL_021e

        IL_0137: ldarg.0
        IL_0138: ldftn instance void Test.ClassTest::getaaa(object)
        IL_013e: newobj instance void [mscorlib]System.Threading.ParameterizedThreadStart::.ctor(object, native int)
        IL_0143: newobj instance void [mscorlib]System.Threading.Thread::.ctor(class [mscorlib]System.Threading.ParameterizedThreadStart)
        IL_0148: stloc.s 4
        IL_014a: ldloc.s 4
        IL_014c: ldloc.3
        IL_014d: callvirt instance void [mscorlib]System.Threading.Thread::Start(object)
        IL_0152: nop
        IL_0153: br IL_021e

        IL_0158: ldarg.0
        IL_0159: ldftn instance void Test.ClassTest::getbbb(object)
        IL_015f: newobj instance void [mscorlib]System.Threading.ParameterizedThreadStart::.ctor(object, native int)
        IL_0164: newobj instance void [mscorlib]System.Threading.Thread::.ctor(class [mscorlib]System.Threading.ParameterizedThreadStart)
        IL_0169: stloc.s 5
        IL_016b: ldloc.s 5
        IL_016d: ldloc.3
        IL_016e: callvirt instance void [mscorlib]System.Threading.Thread::Start(object)
        IL_0173: nop
        IL_0174: br IL_021e

..........

What can I do?

Orvid commented 11 years ago

The code your working with was obfuscated, and it encrypted the strings that would normally be loaded to populate the dictionary for a switch-case statement on a string, invoking a method isn't a valid way to get a condition for a case statement in C#... It would probably show up a bit better if you were to first decrypt the strings in the assembly before you tried to decompile it.

dilijev commented 11 years ago

At any rate, would it be unreasonable to display what the code might have been, in obfuscated form, and display a warning that the disassembly for the file is not valid and cannot be compiled (along with suggestion to de-obfuscate or similar)?

Orvid commented 11 years ago

It certainly wouldn't be unreasonable, but I'm not sure if the current API would allow for it without breaking changes, because, if it isn't currently this way, case statements would need to be representable by an arbitrary expression rather than just a constant value (which is all that's valid in C#).

dgrunwald commented 11 years ago

What should happen here is that the whole switch-on-string-pattern should not be applied if the labels aren't constants. So the code would keep using an explicit dictionary and switch over integers.

dilijev commented 11 years ago

Oh yeah, it would make more sense if it generated equivalent code (and there obviously must be) which actually works, even if it's not a switch.

dgrunwald commented 7 years ago

This was likely fixed in the new decompiler engine (which just landed on the master branch).