Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unusual C# operators in decompiled source...?

Tags:

syntax

c#

dotpeek

I've just decompiled some 3rd party source to debug an issue, using DotPeek. The output code contains some unusual operators, which AFAIK aren't valid C#, so I'm wondering what they mean...

The extract looks like (with Dotpeek comments included, as they are probably relevant);

protected internal void DoReceive(ref byte[] Buffer, int MaxSize, out int Written)
{
    Written = 0;
    .
    .
    .        
    // ISSUE: explicit reference operation
    // ISSUE: variable of a reference type
    int& local = @Written;
    int num = SomeMethod();
    .
    .
    .
    // ISSUE: explicit reference operation
    ^local = num;
}

So, 3 unusual operators in there... int& = @Written seems to be assigning a pointer to a variable that is named pointlessly with the @ character?

But what is ^local = num; ???

OK, here is the equivalent snippet from ILSpy, which makes more sense, I guess the decompile to C# didn't produce a valid equivalent?

'C#'

 int& local = @Written;
 byte[] numArray2 = this.FInSpool;
 int num = (int) __Global.Min(numArray2 == null ? 0L : (long) numArray2.Length, (long) MaxSize);
 ^local = num;

IL

 byte[] expr_22 = this.FInSpool;
 Written = (int)__Global.Min((long)((expr_22 == null) ? 0 : expr_22.Length), (long)MaxSize);

So, I guess the 'C#' isn't quite valid? That IL would be valid C#, not sure why DotPeek produced the output it did. Perhaps I'll stick to ILSpy for this one...?

like image 264
RJ Lohan Avatar asked Dec 17 '12 22:12

RJ Lohan


2 Answers

If you look at the raw IL (from ildasm, not the C# equivalent via IL Spy), that may help you see what the decompiler is trying to say. 'Out' parameters are represented using a (managed) typed-reference, which isn't explicitly exposed as a type in C#. 'Instances' of this type can normally only be passed as parameters to methods accepting typed references ('ref' or 'out' parameters.) See OpCodes.Mkrefany for more information.

What dotPeek is complaining about is that this 'out' typed reference was stored from the argument into a local variable slot, then written to later via the local slot. The '@' and '^' are placeholders used to indicate this unexpected behavior detected by the decompiler (the one the ISSUE comments describe.)

It's possible the code was compiled from C++/CLI and thus the IL looks different from the typical C# compiler output. It's also possible this is some level of minor obfuscation to confuse decompilers (though I don't think so.) I don't think this is functionally any different from loading the reference from its argument onto the operation stack directly (avoiding the use of a local variable slot), but I could be wrong.

like image 158
Dan Bryant Avatar answered Sep 22 '22 21:09

Dan Bryant


Putting a @ before a name allows you to use a reserved name for a variable, For example if I wanted to have a variable called return I would need to do this.

public int Weird()
{
    int @return = 0;
    return @return;
}

See this SO question for more details.


Putting a ^ before the name ... umm, no clue. (will update as I research I could find any info on what ^ means when not being used as a XOR)

like image 36
Scott Chamberlain Avatar answered Sep 19 '22 21:09

Scott Chamberlain