[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>&nbsp;</DIV>
<DIV><FONT size=3D2>&nbsp;&nbsp;&nbsp; I ran into a problem while using =
the=20
ByValStr attribute on a marshaled structure.</FONT></DIV>
<DIV><FONT size=3D2></FONT>&nbsp;</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>&nbsp;</DIV>
<DIV><FONT size=3D2>&nbsp;&nbsp;&nbsp; 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>&nbsp;</DIV>
<DIV><FONT size=3D2>The fix is included in this post along&nbsp;with a =
test for=20
the fix.</FONT></DIV>
<DIV><FONT size=3D2></FONT>&nbsp;</DIV>
<DIV><FONT size=3D2>Could someone test it&nbsp;and commit it =
?</FONT></DIV>
<DIV><FONT size=3D2></FONT>&nbsp;</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--