[Mono-bugs] [Bug 565143] New: calli incorectly marshals byte[]
bugzilla_noreply at novell.com
bugzilla_noreply at novell.com
Wed Dec 16 08:59:54 EST 2009
http://bugzilla.novell.com/show_bug.cgi?id=565143
http://bugzilla.novell.com/show_bug.cgi?id=565143#c0
Summary: calli incorectly marshals byte[]
Classification: Mono
Product: Mono: Runtime
Version: 2.6.x
Platform: x86
OS/Version: Windows 7
Status: NEW
Severity: Normal
Priority: P5 - None
Component: interop
AssignedTo: mono-bugs at lists.ximian.com
ReportedBy: tomas.matousek at microsoft.com
QAContact: mono-bugs at lists.ximian.com
Found By: ---
Blocker: ---
Created an attachment (id=332921)
--> (http://bugzilla.novell.com/attachment.cgi?id=332921)
Repro
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1;
Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729;
Media Center PC 6.0; InfoPath.3; MS-RTC LM 8; MALC)
calli instruction doesn't correctly marshal parameters of type byte[]. It
should marhsal the array as a pointer to its first element. Instead it passes a
wrong pointer so the array length is rewritten if the buffer is written to.
The below code works if it injects instructions:
il.Emit(OpCodes.Ldc_I4_0);
il.Emit(OpCodes.Ldelema, typeof(byte));
after each byte[] array parameter load.
--- code ---
using System;
using System.ComponentModel;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Permissions;
namespace IronRuby.StandardLibrary.Win32API {
public class Win32API {
delegate int F(IntPtr a, int b, int c, int d, int e, byte[] f);
public static void Main() {
DynamicMethod calli = EmitCalliStub();
var f = (F)calli.CreateDelegate(typeof(F));
IntPtr ftn = GetFunction("shell32", "SHGetFolderPath");
byte[] path = new byte[1000];
f(ftn, 0, 0x0023, 0, 1, path);
Console.WriteLine(path.Length);
}
[DllImport("kernel32.dll")]
private static extern IntPtr LoadLibrary(string lpFileName);
[DllImport("kernel32.dll")]
private static extern IntPtr GetProcAddress(IntPtr module, string
lpProcName);
private static IntPtr GetFunction(string/*!*/ libraryName, string/*!*/
functionName) {
IntPtr library = LoadLibrary(libraryName);
if (library == IntPtr.Zero) {
throw new Win32Exception();
}
string procName = functionName;
IntPtr function = GetProcAddress(library, procName);
if (function == IntPtr.Zero) {
function = GetProcAddress(library, procName + "A");
if (library == IntPtr.Zero) {
throw new Win32Exception();
}
}
return function;
}
private static DynamicMethod/*!*/ EmitCalliStub() {
var returnType = typeof(int);
var parameterTypes = new Type[1 + 5];
// target function ptr:
parameterTypes = new[] {
typeof(IntPtr),
typeof(int),
typeof(int),
typeof(int),
typeof(int),
typeof(byte[])
};
DynamicMethod dm = new DynamicMethod("calli", returnType,
parameterTypes, DynamicModule);
var il = dm.GetILGenerator();
var signature =
SignatureHelper.GetMethodSigHelper(CallingConvention.Winapi, returnType);
// calli args:
for (int i = 1; i < parameterTypes.Length; i++) {
il.Emit(OpCodes.Ldarg, i);
signature.AddArgument(parameterTypes[i]);
}
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Calli, signature);
il.Emit(OpCodes.Ret);
return dm;
}
private static ModuleBuilder _dynamicModule;
private static ModuleBuilder DynamicModule {
get {
if (_dynamicModule == null) {
var attributes = new[] {
new
CustomAttributeBuilder(typeof(UnverifiableCodeAttribute).GetConstructor(Type.EmptyTypes),
new object[0]),
new
CustomAttributeBuilder(typeof(PermissionSetAttribute).GetConstructor(new Type[]
{ typeof(SecurityAction) }),
new object[]{ SecurityAction.Demand },
new PropertyInfo[] {
typeof(PermissionSetAttribute).GetProperty("Unrestricted") },
new object[] { true }
)
};
string name = "DynamicAssembly";
var assembly =
AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName(name),
AssemblyBuilderAccess.Run, attributes);
assembly.DefineVersionInfoResource();
_dynamicModule = assembly.DefineDynamicModule(name);
}
return _dynamicModule;
}
}
}
}
Reproducible: Always
Steps to Reproduce:
1. compile and run the above code or run the attached .exe
Actual Results:
24948 (or some other random number != 1000)
Expected Results:
1000
--
Configure bugmail: http://bugzilla.novell.com/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are the QA contact for the bug.
You are the assignee for the bug.
More information about the mono-bugs
mailing list