Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
Daniel Grunwald
@dgrunwald
Hmm looks like it's really that simple. The other helper functions involved are shared with the code for compound assignments/preincrement, and that already supports floats.
Daniel Grunwald
@dgrunwald
There's also #947 which is a bit more complicated, i guess the current code only works for byte*/sbyte*.
Chicken-Bones
@Chicken-Bones
I'll PR it sometime this week, with some test cases.
Chicken-Bones
@Chicken-Bones
I'm really struggling to conceive of a piece of code requiring the fix in icsharpcode/ILSpy@6c0216b
There's no test case or issue number
Daniel Grunwald
@dgrunwald
Hmm I think it's related to the two commits immediately preceding that one
Daniel Grunwald
@dgrunwald
I'm pretty sure the commit message is talking about the "Only the last instruction in a block may have an unreachable endpoint" assertion in Block.CheckInvariant; but I can't remember which test case ran into that assertion
Daniel Grunwald
@dgrunwald
@Chicken-Bones I can reproduce the assertion using the ILSpy version immediately prior to that commit on the assembly from #1364
Daniel Grunwald
@dgrunwald

paraphrasing the ILAst of the obfuscated code, before "Duplicate block exit" + "Extract else block" the control flow looks like this:

if (...) {
   call Something()
} else {
   while (true) {
      if (...)
        return;
   }
}
return;

and after it looks like this:

if (...) {
   call Something()
   return;
}
while (true) {
    if (...)
      return;
 }
return;
Chicken-Bones
@Chicken-Bones
            if (!b)
            {
                Console.WriteLine();
            }
            while (true)
            {
                for (int i = 0; i < 10; i++)
                    Console.WriteLine();

                if (b)
                    return;

                for (int i = 0; i < 10; i++)
                    Console.WriteLine();
            }
I tried this before asking, but it decompiles fine, I'll go grab the assembly from the issue
Chicken-Bones
@Chicken-Bones
I suppose more recent commits have improved the handling of dead code
it should be impossible to actually hit the condition there now
I could replace it with an assertion, or just leave it
Chicken-Bones
@Chicken-Bones
I stumbled across https://github.com/csmith-project/creduce today, awesome concept, might try it out in the future
Daniel Grunwald
@dgrunwald
creduce is great, I use it a lot at work to minimize reproducers for our C++ compiler
customers can send in 5 MB of boost header mess and creduce usually manages to cut it down to 10 to 20 lines of code
Chicken-Bones
@Chicken-Bones
An annoyance I found while doing test cases for something else:
public void Issue1524V3(string str)
{
    if (!string.IsNullOrEmpty(str))
    {
        return;
    }
    if (int.TryParse(str, out int id))
    {
        Console.WriteLine(new Func<int>(() => id));
    }
}

public void Issue1524V4(string str)
{
    if (string.IsNullOrEmpty(str))
    {
        if (int.TryParse(str, out int id))
        {
            Console.WriteLine(new Func<int>(() => id)); 
        }
    }
}
The first version decompiles with a short-circuit. Intended behaviour.
The second decompiles with an early return (how the first is written).
This is because the compiler emits the display class constructor and local variable store in different locations in the two
In the first version, the stloc V_1(newobj <>c__DisplayClass10_0..ctor()) is before the first if
In the second, it's between the two, preventing them from being merged.
TransformDisplayClassUsage removes the display class init and store, but it runs after ConditionDetection
The only solutions I can think of are either re-ordering the transforms, or running ConditionDetection (or a part of it) again
I don't know enough about the inter-transform dependencies to know if reordering would be very bad
It's not a major issue by any means, but it's an inconsistency which isn't ideal. Perhaps the lingering store prevents other transforms working properly as well
Stargazing Koishi
@sgkoishi
Do I need to put the .net framework libraries to somewhere if I want to decompile a netfx targeted file in net core linux environment?
Like say, copy all files from C:\Windows\Microsoft.NET\Framework64\v4.0.30319 to the linux machine and AssemblyResolver.AddSearchDirectory?
Siegfried Pammer
@siegfriedpammer
@sgkoishi yes, I think that would be necessary
Daniel Grunwald
@dgrunwald
@sgkoishi you could also use the equivalent mono assemblies or otherwise "similar enough" assemblies. ILSpy is mostly interested in having type definitions for types used in the assembly being decompiled -- most critically it needs to tell whether a typeref refers to a struct, class or enum. We also use the list of available methods to ensure we emit enough casts to uniquely identify the overload that's supposed to be called. There's also a bunch of other minor stuff.
ILSpy itself uses the .NET runtime assemblies (from the GAC) so that you can use "go to definition" and see the source code for those .NET methods. But the decompiler itself would also be happy with reference assemblies that have the public types and methods without implementation.
Mykola Morozov
@mcmikecreations
Hi everyone! I've been a happy user of the ILSpy CSharpDecompiler, specifically the decompiled node tree. But I've been wondering, is there any method to transform raw c# code (text files) into the SyntaxTree node tree? I understand I can create a parser myself, but I'm curious if it already exists.
Stanislav LukeŇ°
@exyi
@mcmikecreations I guess you can use the Roslyn API to parse C# files into a syntax tree, here is some intro text: https://docs.microsoft.com/en-us/dotnet/csharp/roslyn-sdk/get-started/syntax-analysis It is a different tree than the ILSpy's one, but the principle is similar. And, in any case, translating the Roslyn tree into ILSpy tree is going to be way simpler than parsing C#