Arguments passed to pinvoked method are altered when the method is inspected

daniel.romero's Avatar

daniel.romero

10 Nov, 2017 03:28 PM

The code generated by a OnMethodBoundaryAspect changes the arguments passed to a pinvoked method.

Unfortunately I'm not able to reproduce it with a native library I've written my self and the for the program to be executable you need a gemalto usb smart card.
It might be reproducable with a different smartcard, to check that try to modify the name of the smart card reader on line 71.

Example:

In the following application the result of the PInvoke call on line 157 changes if the aspect is applied on the "public static extern int SCardTransmit" method.
The result is The Win32 Error Code 0x57 which means invalid parameter, instead of 0.

Aspect:

[PSerializable]
public class MyOnMethodBoundaryAspect : OnMethodBoundaryAspect
{
public override void OnEntry(MethodExecutionArgs args)
{
Console.WriteLine("Method on entry");
}
}

Program:

[MyOnMethodBoundaryAspect]
internal class Program {

...

[DllImport("winscard.dll", SetLastError = true)]
public static extern int SCardTransmit(IntPtr hCard,
ref SCard_IO_Request pioSendRequest,
ref byte SendBuff,
uint SendBuffLen,
IntPtr pioRecvRequest,
out byte RecvBuff,
ref uint RecvBuffLen);

public static T GetApduData<T>(IntPtr cardHandle, byte[] command)
{
...
(Line 157)
var result = (uint) SCardTransmit(cardHandle, ref request, ref command[0], (uint) command.Length,
                IntPtr.Zero, out buffer[0], ref outBytes); <--------- With MyOnMethodBoundaryAspect result = 0x57 (Invalid Parameter), Without aspect result = 0x00
    if (result != 0)
         throw new Exception("Could not transmit command");
...
}
...
}

Applying the aspect generates the following proxy method for SCardTransmit, which is called from the GetApduData instead of directly calling the external method:

.method assembly static int32 '<RetriesLeft.Program.SCardTransmit>b__'(native int hCard,
                                                                        valuetype RetriesLeft.Program/SCard_IO_Request& pioSendRequest,
                                                                        uint8& SendBuff,
                                                                        uint32 SendBuffLen,
                                                                        native int pioRecvRequest,
                                                                        [out] uint8& RecvBuff,
                                                                        uint32& RecvBuffLen) cil managed
{
  .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
  .custom instance void [PostSharp]PostSharp.Aspects.Internals.DebuggerAspectGeneratedCodeAttribute::.ctor() = ( 01 00 00 00 )
  // Code size 74 (0x4a)
  .maxstack 7
  .locals init ([0] int32 CS$1$0__returnValue,
           [1] valuetype RetriesLeft.Program/SCard_IO_Request arg1,
           [2] uint8 arg2,
           [3] uint8 arg3,
           [4] uint32 arg4)
  IL_0000: ldsfld class [Aspects]Aspects.MyOnMethodBoundaryAspect PostSharp.ImplementationDetails_b72b98cf.'<>z__a_1'::a2
  IL_0005: ldnull
  IL_0006: callvirt instance void [Aspects]Aspects.MyOnMethodBoundaryAspect::OnEntry(class [PostSharp]PostSharp.Aspects.MethodExecutionArgs)
  .try
  {
    IL_000b: ldarg.0
    IL_000c: ldarg.1
    IL_000d: ldobj RetriesLeft.Program/SCard_IO_Request
    IL_0012: stloc.1
    IL_0013: ldloca.s arg1
    IL_0015: ldarg.2
    IL_0016: ldind.u1
    IL_0017: stloc.2
    IL_0018: ldloca.s arg2
    IL_001a: ldarg.3
    IL_001b: ldarg.s pioRecvRequest
    IL_001d: ldarg.s RecvBuff
    IL_001f: ldind.u1
    IL_0020: stloc.3
    IL_0021: ldloca.s arg3
    IL_0023: ldarg.s RecvBuffLen
    IL_0025: ldind.u4
    IL_0026: stloc.s arg4
    IL_0028: ldloca.s arg4
    IL_002a: call int32 RetriesLeft.Program::SCardTransmit(native int,
                                                                  valuetype RetriesLeft.Program/SCard_IO_Request&,
                                                                  uint8&,
                                                                  uint32,
                                                                  native int,
                                                                  uint8&,
                                                                  uint32&)
    IL_002f: stloc.0
    IL_0030: leave.s IL_0046
  } // end .try
  finally
  {
    IL_0032: ldarg.1
    IL_0033: ldloc.1
    IL_0034: stobj RetriesLeft.Program/SCard_IO_Request
    IL_0039: ldarg.2
    IL_003a: ldloc.2
    IL_003b: stind.i1
    IL_003c: ldarg.s RecvBuff
    IL_003e: ldloc.3
    IL_003f: stind.i1
    IL_0040: ldarg.s RecvBuffLen
    IL_0042: ldloc.s arg4
    IL_0044: stind.i4
    IL_0045: endfinally
  } // end handler
  IL_0046: br.s IL_0048
  IL_0048: ldloc.0
  IL_0049: ret
} // end of method '<>z__Aspects'::'<RetriesLeft.Program.SCardTransmit>b__'

  1. Support Staff 1 Posted by PostSharp Techn... on 21 Nov, 2017 11:10 AM

    PostSharp Technologies's Avatar

    Hello,

    I'm sorry for a late response.

    We are still investigating the issue and we will try to finish the investigation as soon as possible.

    -jakub

  2. Support Staff 2 Posted by PostSharp Techn... on 21 Nov, 2017 03:35 PM

    PostSharp Technologies's Avatar

    Hello,

    You have run into a special use case that has not been completely supported and tested. The problem arises from passing byte arrays as ref byte into external methods.

    When a method contains a ref parameter, the code generated by PostSharp will create a local copy of the parameter's value and pass the reference to that local value when calling the original method. So, when you pass ref byte into a method, the reference passed to the original method points only to the first element of the array. SCardTransmit expects to read more bytes and fails when encounters incorrect value.

    We're currently investigating whether we can improve support for such a use case. In the meantime we believe it should be possible to work around the issue by changing the signatures of the extern functions. Please try to declare the buffer arguments as pointers IntPtr or as arrays byte[] instead of using ref byte and change the calling code accordingly.

    (filed as internal issue #15659)

    -alex

  3. Support Staff 3 Posted by PostSharp Techn... on 13 Dec, 2017 02:53 PM

    PostSharp Technologies's Avatar

    Hello,

    We're closing the ticket for now as the bug has been internally filed as issue #15659. We will contact you as soon as the bug fix has been released.

    For more details on our support policies and prioritization of bug fixes, please visit https://www.postsharp.net/support/policies

    PostSharp Team

  4. PostSharp Technologies closed this discussion on 13 Dec, 2017 02:53 PM.

Comments are currently closed for this discussion. You can start a new one.

Keyboard shortcuts

Generic

? Show this help
ESC Blurs the current field

Comment Form

r Focus the comment reply box
^ + ↩ Submit the comment

You can use Command ⌘ instead of Control ^ on Mac