How can we help you today? How can we help you today?

'fixed' statements decompiled incorrectly

The following IL:
.method assembly hidebysig static void SectionListFromPage(class MS.Internal.PtsHost.PtsContext ptsContext, native int page, valuetype MS.Internal.PtsHost.UnsafeNativeMethods.PTS/FSPAGEDETAILS& pageDetails, [out] valuetype MS.Internal.PtsHost.UnsafeNativeMethods.PTS/FSSECTIONDESCRIPTION[]& arraySectionDesc) cil managed
{
    .custom instance void [mscorlib]System.Security.SecurityCriticalAttribute::.ctor()
    .maxstack 5
    .locals init (
        [0] int32 num,
        [1] valuetype MS.Internal.PtsHost.UnsafeNativeMethods.PTS/FSSECTIONDESCRIPTION& pinned fssectiondescriptionRef,
        [2] valuetype MS.Internal.PtsHost.UnsafeNativeMethods.PTS/FSSECTIONDESCRIPTION[] fssectiondescriptionArray)
    L_0000: ldarg.3 
    L_0001: ldarg.2 
    L_0002: ldflda valuetype MS.Internal.PtsHost.UnsafeNativeMethods.PTS/FSPAGEDETAILS/nested_u MS.Internal.PtsHost.UnsafeNativeMethods.PTS/FSPAGEDETAILS::u
    L_0007: ldflda valuetype MS.Internal.PtsHost.UnsafeNativeMethods.PTS/FSPAGEDETAILSCOMPLEX MS.Internal.PtsHost.UnsafeNativeMethods.PTS/FSPAGEDETAILS/nested_u::complex
    L_000c: ldfld int32 MS.Internal.PtsHost.UnsafeNativeMethods.PTS/FSPAGEDETAILSCOMPLEX::cSections
    L_0011: newarr MS.Internal.PtsHost.UnsafeNativeMethods.PTS/FSSECTIONDESCRIPTION
    L_0016: stind.ref 
    L_0017: ldarg.3 
    L_0018: ldind.ref 
    L_0019: dup 
    L_001a: stloc.2 
    L_001b: brfalse.s L_0022
    L_001d: ldloc.2 
    L_001e: ldlen 
    L_001f: conv.i4 
    L_0020: brtrue.s L_0027
    L_0022: ldc.i4.0 
    L_0023: conv.u 
    L_0024: stloc.1 
    L_0025: br.s L_002f
    L_0027: ldloc.2 
    L_0028: ldc.i4.0 
    L_0029: ldelema MS.Internal.PtsHost.UnsafeNativeMethods.PTS/FSSECTIONDESCRIPTION
    L_002e: stloc.1 
    L_002f: ldarg.0 
    L_0030: callvirt instance native int MS.Internal.PtsHost.PtsContext::get_Context()
    L_0035: ldarg.1 
    L_0036: ldarg.2 
    L_0037: ldflda valuetype MS.Internal.PtsHost.UnsafeNativeMethods.PTS/FSPAGEDETAILS/nested_u MS.Internal.PtsHost.UnsafeNativeMethods.PTS/FSPAGEDETAILS::u
    L_003c: ldflda valuetype MS.Internal.PtsHost.UnsafeNativeMethods.PTS/FSPAGEDETAILSCOMPLEX MS.Internal.PtsHost.UnsafeNativeMethods.PTS/FSPAGEDETAILS/nested_u::complex
    L_0041: ldfld int32 MS.Internal.PtsHost.UnsafeNativeMethods.PTS/FSPAGEDETAILSCOMPLEX::cSections
    L_0046: ldloc.1 
    L_0047: conv.i 
    L_0048: ldloca.s num
    L_004a: call int32 MS.Internal.PtsHost.UnsafeNativeMethods.PTS::FsQueryPageSectionList(native int, native int, int32, valuetype MS.Internal.PtsHost.UnsafeNativeMethods.PTS/FSSECTIONDESCRIPTION*, int32&)
    L_004f: call void MS.Internal.PtsHost.UnsafeNativeMethods.PTS::Validate(int32)
    L_0054: ldc.i4.0 
    L_0055: conv.u 
    L_0056: stloc.1 
    L_0057: ldarg.2 
    L_0058: ldflda valuetype MS.Internal.PtsHost.UnsafeNativeMethods.PTS/FSPAGEDETAILS/nested_u MS.Internal.PtsHost.UnsafeNativeMethods.PTS/FSPAGEDETAILS::u
    L_005d: ldflda valuetype MS.Internal.PtsHost.UnsafeNativeMethods.PTS/FSPAGEDETAILSCOMPLEX MS.Internal.PtsHost.UnsafeNativeMethods.PTS/FSPAGEDETAILS/nested_u::complex
    L_0062: ldfld int32 MS.Internal.PtsHost.UnsafeNativeMethods.PTS/FSPAGEDETAILSCOMPLEX::cSections
    L_0067: ldloc.0 
    L_0068: ceq 
    L_006a: ldsfld string MS.Internal.PtsHost.ErrorHandler::PTSObjectsCountMismatch
    L_006f: call void MS.Internal.PtsHost.ErrorHandler::Assert(bool, string)
    L_0074: ret 
}

decompiles to:
[SecurityCritical]
internal static unsafe void SectionListFromPage(PtsContext ptsContext, IntPtr page, ref PTS.FSPAGEDETAILS pageDetails, out PTS.FSSECTIONDESCRIPTION[] arraySectionDesc)
{
    int num;
    PTS.FSSECTIONDESCRIPTION[] fssectiondescriptionArray;
    arraySectionDesc = new PTS.FSSECTIONDESCRIPTION[pageDetails.u.complex.cSections];
    if (((fssectiondescriptionArray = arraySectionDesc) != null) && (fssectiondescriptionArray.Length != 0))
    {
        goto Label_0027;
    }
    fixed (PTS.FSSECTIONDESCRIPTION* fssectiondescriptionRef = null)
    {
        goto Label_002F;
    Label_0027:
        fssectiondescriptionRef = fssectiondescriptionArray;
    Label_002F:
        PTS.Validate(PTS.FsQueryPageSectionList(ptsContext.Context, page, pageDetails.u.complex.cSections, fssectiondescriptionRef, out num));
    }
    ErrorHandler.Assert(pageDetails.u.complex.cSections == num, ErrorHandler.PTSObjectsCountMismatch);
}

instead I'd expect the code to decompile without the goto statements, generated guard statement and the fixed statement having a real assignment like so:
        [SecurityCritical]
        internal static unsafe void SectionListFromPage(PtsContext ptsContext, IntPtr page, ref PTS.FSPAGEDETAILS pageDetails, out PTS.FSSECTIONDESCRIPTION[] arraySectionDesc)
        {
            int num;
            PTS.FSSECTIONDESCRIPTION[] fssectiondescriptionArray = arraySectionDesc = new PTS.FSSECTIONDESCRIPTION[pageDetails.u.complex.cSections];            
            fixed (PTS.FSSECTIONDESCRIPTION* fssectiondescriptionRef = fssectiondescriptionArray)
            {
                PTS.Validate(PTS.FsQueryPageSectionList(ptsContext.Context, page, pageDetails.u.complex.cSections, fssectiondescriptionRef, out num));
            }
            ErrorHandler.Assert(pageDetails.u.complex.cSections == num, ErrorHandler.PTSObjectsCountMismatch);
        }
ebnf
0

Comments

3 comments

  • Clive Tong
    Please let me know if I'm wrong, but I think that the code that Reflector generates corresponds to the IL.

    In that case, I think the code you give disagrees with Reflector in the case that pageDetails.u.complex.cSections = 0. The Reflector code would bind fssectiondescriptionRef to null, whereas your code would bind fssectiondescriptionRef to the zero element array.
    Clive Tong
    0
  • ebnf
    Ah yes, the code should be as following:
    [SecurityCritical] 
            internal static unsafe void SectionListFromPage(PtsContext ptsContext, IntPtr page, ref PTS.FSPAGEDETAILS pageDetails, out PTS.FSSECTIONDESCRIPTION[] arraySectionDesc) 
            { 
                int num; 
                PTS.FSSECTIONDESCRIPTION[] fssectiondescriptionArray = arraySectionDesc = new PTS.FSSECTIONDESCRIPTION[pageDetails.u.complex.cSections];            
                if (fssectiondescriptionArray == null || fssectiondescriptionArray.Length == 0) {
                    fixed (PTS.FSSECTIONDESCRIPTION* fssectiondescriptionRef = null) 
                    { 
                        PTS.Validate(PTS.FsQueryPageSectionList(ptsContext.Context, page, pageDetails.u.complex.cSections, fssectiondescriptionRef, out num)); 
                    } 
                } else {
                    fixed (PTS.FSSECTIONDESCRIPTION* fssectiondescriptionRef = fssectiondescriptionArray) 
                    { 
                        PTS.Validate(PTS.FsQueryPageSectionList(ptsContext.Context, page, pageDetails.u.complex.cSections, fssectiondescriptionRef, out num)); 
                    } 
                }
                ErrorHandler.Assert(pageDetails.u.complex.cSections == num, ErrorHandler.PTSObjectsCountMismatch); 
            }
    

    The existing generated code is still wrong because it gives a compile error because it is illegal to rebind the value of a fixed statement.
    ebnf
    0
  • Clive Tong
    Thanks for reporting this. I've logged it as bug RP-725.
    Clive Tong
    0

Add comment

Please sign in to leave a comment.