[Mono-list] ByValStr Marshaling bug
Jerome Laban
jlaban@wanadoo.fr
Wed, 26 Feb 2003 14:48:38 +0100
This is a multi-part message in MIME format.
------=_NextPart_000_0283_01C2DDA6.257A0AE0
Content-Type: multipart/alternative;
boundary="----=_NextPart_001_0284_01C2DDA6.257A0AE0"
------=_NextPart_001_0284_01C2DDA6.257A0AE0
Content-Type: text/plain;
charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable
Hi everyone,
I ran into a problem while using the ByValStr attribute on a =
marshaled structure.
The problem was simple : I was doing the marshaling by hand using =
Marshal.StructureToPtr and Marshal.PtrToStructure and the memory pointed =
by the IntPtr was not always "clean". The method mono_to_byvalstr was =
assuming that the destination memory was set to zero, and when it was =
not, there was garbage after the correct string data.
The fix is simple, just moved the memset a few lines before. Also, =
the microsoft runtime is setting the destination memory to zero, thus =
removing any garbage.
The fix is included in this post along with a test for the fix.
Could someone test it and commit it ?
Thanks,
Jerome.
------=_NextPart_001_0284_01C2DDA6.257A0AE0
Content-Type: text/html;
charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML><HEAD>
<META http-equiv=3DContent-Type content=3D"text/html; =
charset=3Diso-8859-1">
<META content=3D"MSHTML 6.00.2800.1141" name=3DGENERATOR>
<STYLE></STYLE>
</HEAD>
<BODY bgColor=3D#ffffff>
<DIV><FONT size=3D2>Hi everyone,</FONT></DIV>
<DIV><FONT size=3D2></FONT> </DIV>
<DIV><FONT size=3D2> I ran into a problem while using =
the=20
ByValStr attribute on a marshaled structure.</FONT></DIV>
<DIV><FONT size=3D2></FONT> </DIV>
<DIV><FONT size=3D2>The problem was simple : I was doing the marshaling =
by hand=20
using <FONT face=3D"Courier New">Marshal.StructureToPtr</FONT> and <FONT =
face=3D"Courier New">Marshal.PtrToStructure</FONT> and the memory =
pointed by the=20
<FONT face=3D"Courier New">IntPtr</FONT> was not always "clean". The =
method <FONT=20
face=3D"Courier New">mono_to_byvalstr</FONT> was assuming that the =
destination=20
memory was set to zero, and when it was not, there was garbage after the =
correct=20
string data.</FONT></DIV>
<DIV><FONT size=3D2></FONT> </DIV>
<DIV><FONT size=3D2> The fix is simple, just moved the =
memset a=20
few lines before. Also, the microsoft runtime is setting the destination =
memory=20
to zero, thus removing any garbage.</FONT></DIV>
<DIV><FONT size=3D2></FONT> </DIV>
<DIV><FONT size=3D2>The fix is included in this post along with a =
test for=20
the fix.</FONT></DIV>
<DIV><FONT size=3D2></FONT> </DIV>
<DIV><FONT size=3D2>Could someone test it and commit it =
?</FONT></DIV>
<DIV><FONT size=3D2></FONT> </DIV>
<DIV><FONT size=3D2>Thanks,</FONT></DIV>
<DIV><FONT size=3D2>Jerome.</FONT></DIV></BODY></HTML>
------=_NextPart_001_0284_01C2DDA6.257A0AE0--
------=_NextPart_000_0283_01C2DDA6.257A0AE0
Content-Type: application/octet-stream;
name="marshal5.cs"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
filename="marshal5.cs"
using System;=0A=
using System.Runtime.InteropServices;=0A=
=0A=
public class Test =0A=
{=0A=
[DllImport ("libtest.so", EntryPoint=3D"mono_test_byvalstr_gen")]=0A=
public static extern IntPtr mono_test_byvalstr_gen();=0A=
=0A=
[DllImport ("libtest.so", EntryPoint=3D"mono_test_byvalstr_check")]=0A=
public static extern int mono_test_byvalstr_check(IntPtr data, string =
correctString);=0A=
=0A=
[StructLayout (LayoutKind.Sequential)]=0A=
public struct ByValStrStruct =0A=
{=0A=
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=3D100)]=0A=
public string a;=0A=
}=0A=
=0A=
public unsafe static int Main () =0A=
{=0A=
string testString =3D "A small string";=0A=
=0A=
IntPtr udata =3D mono_test_byvalstr_gen();=0A=
=0A=
ByValStrStruct data =3D new ByValStrStruct();=0A=
data.a =3D testString;=0A=
=0A=
Marshal.StructureToPtr(data, udata, false);=0A=
=0A=
return mono_test_byvalstr_check(udata, testString);=0A=
}=0A=
}=0A=
=0A=
------=_NextPart_000_0283_01C2DDA6.257A0AE0
Content-Type: application/octet-stream;
name="byvalstr.diff"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
filename="byvalstr.diff"
Index: mono/metadata/marshal.c=0A=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=0A=
RCS file: /mono/mono/mono/metadata/marshal.c,v=0A=
retrieving revision 1.84=0A=
diff -u -r1.84 marshal.c=0A=
--- mono/metadata/marshal.c 8 Feb 2003 07:53:49 -0000 1.84=0A=
+++ mono/metadata/marshal.c 26 Feb 2003 13:35:58 -0000=0A=
@@ -167,8 +167,9 @@=0A=
g_assert (dst !=3D NULL);=0A=
g_assert (size > 0);=0A=
=0A=
+ memset (dst, 0, size);=0A=
+=0A=
if (!src) {=0A=
- memset (dst, 0, size);=0A=
return;=0A=
}=0A=
=0A=
Index: mono/tests/libtest.c=0A=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=0A=
RCS file: /mono/mono/mono/tests/libtest.c,v=0A=
retrieving revision 1.17=0A=
diff -u -r1.17 libtest.c=0A=
--- mono/tests/libtest.c 23 Jan 2003 18:08:18 -0000 1.17=0A=
+++ mono/tests/libtest.c 26 Feb 2003 13:35:58 -0000=0A=
@@ -258,3 +258,30 @@=0A=
return 1;=0A=
}=0A=
#endif=0A=
+=0A=
+typedef struct {=0A=
+ char a[100];=0A=
+} ByValStrStruct;=0A=
+=0A=
+ByValStrStruct *=0A=
+mono_test_byvalstr_gen (void)=0A=
+{=0A=
+ ByValStrStruct *ret;=0A=
+ int i;=0A=
+ =0A=
+ ret =3D g_malloc(sizeof(ByValStrStruct));=0A=
+ memset(ret, 'a', sizeof(ByValStrStruct)-1);=0A=
+ ret->a[sizeof(ByValStrStruct)-1] =3D 0;=0A=
+=0A=
+ return ret;=0A=
+}=0A=
+=0A=
+int=0A=
+mono_test_byvalstr_check (ByValStrStruct* data, char* correctString)=0A=
+{=0A=
+ int ret;=0A=
+=0A=
+ ret =3D strcmp(data->a, correctString);=0A=
+ g_free(data);=0A=
+ return (ret !=3D 0);=0A=
+}=0A=
------=_NextPart_000_0283_01C2DDA6.257A0AE0--