In metadata:
authorRobert Jordan <robertj@gmx.net>
Wed, 17 Sep 2008 10:52:47 +0000 (10:52 -0000)
committerRobert Jordan <robertj@gmx.net>
Wed, 17 Sep 2008 10:52:47 +0000 (10:52 -0000)
2008-09-17  Robert Jordan  <robertj@gmx.net>

* marshal.c (mono_marshal_get_ldflda_wrapper): Add support for
context bound objects. Fixes #415577.

Code is contributed under MIT/X11 license.

In tests:
2008-09-17  Robert Jordan  <robertj@gmx.net>

* Makefile.am: Add test for #415577.

svn path=/trunk/mono/; revision=113274

mono/metadata/ChangeLog
mono/metadata/marshal.c
mono/tests/ChangeLog
mono/tests/Makefile.am
mono/tests/bug-415577.cs [new file with mode: 0644]

index d5d4305e6096524633de0ec7d139e4b0e432c830..20f0a58457d63e4e76eb2a19756c4fad8ffb6a87 100644 (file)
@@ -1,4 +1,11 @@
 
+2008-09-17  Robert Jordan  <robertj@gmx.net>
+
+       * marshal.c (mono_marshal_get_ldflda_wrapper): Add support for
+       context bound objects. Fixes #415577.
+
+       Code is contributed under MIT/X11 license.
+
 Tue Sep 16 21:03:58 CEST 2008 Paolo Molaro <lupus@ximian.com>
 
        * icall-def.h, threads-types.h, threads.c: fixed SpinWait()
index 08542192eb6b28e8354ac1cb6d263f6ac4d5c1b6..9bef1870ee7c5a6f68503f5d772aa8aabfffe582 100644 (file)
@@ -1347,6 +1347,27 @@ mono_mb_emit_xdomain_check (MonoMethodBuilder *mb, int branch_code)
        return pos;
 }
 
+static int
+mono_mb_emit_contextbound_check (MonoMethodBuilder *mb, int branch_code)
+{
+       static int offset = -1;
+       static guint8 mask;
+
+       if (offset < 0)
+               mono_marshal_find_bitfield_offset (MonoClass, contextbound, &offset, &mask);
+
+       mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoTransparentProxy, remote_class));
+       mono_mb_emit_byte (mb, CEE_LDIND_REF);
+       mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoRemoteClass, proxy_class));
+       mono_mb_emit_byte (mb, CEE_LDIND_REF);
+       mono_mb_emit_ldflda (mb, offset);
+       mono_mb_emit_byte (mb, CEE_LDIND_U1);
+       mono_mb_emit_icon (mb, mask);
+       mono_mb_emit_byte (mb, CEE_AND);
+       mono_mb_emit_icon (mb, 0);
+       return mono_mb_emit_branch (mb, branch_code);
+}
+
 static void
 mono_mb_emit_cominterop_call (MonoMethodBuilder *mb, MonoMethodSignature *sig, MonoMethod* method)
 {
@@ -5288,7 +5309,7 @@ mono_marshal_get_ldflda_wrapper (MonoType *type)
        MonoClass *klass;
        GHashTable *cache;
        char *name;
-       int t, pos0;
+       int t, pos0, pos1, pos2, pos3;
 
        type = mono_type_get_underlying_type (type);
        t = type->type;
@@ -5331,12 +5352,50 @@ mono_marshal_get_ldflda_wrapper (MonoType *type)
        sig->params [3] = &mono_defaults.int_class->byval_arg;
        sig->ret = &mono_defaults.int_class->byval_arg;
 
+       /* if typeof (this) != transparent_proxy goto pos0 */
        mono_mb_emit_ldarg (mb, 0);
        pos0 = mono_mb_emit_proxy_check (mb, CEE_BNE_UN);
 
-       /* FIXME: Only throw this if the object is in another appdomain */
+       /* if same_appdomain goto pos1 */
+       mono_mb_emit_ldarg (mb, 0);
+       pos1 = mono_mb_emit_xdomain_check (mb, CEE_BEQ);
+
        mono_mb_emit_exception_full (mb, "System", "InvalidOperationException", "Attempt to load field address from object in another appdomain.");
 
+       /* same app domain */
+       mono_mb_patch_branch (mb, pos1);
+
+       /* if typeof (this) != contextbound goto pos2 */
+       mono_mb_emit_ldarg (mb, 0);
+       pos2 = mono_mb_emit_contextbound_check (mb, CEE_BEQ);
+
+       /* if this->rp->context == mono_context_get goto pos3 */
+       mono_mb_emit_ldarg (mb, 0);
+       mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoTransparentProxy, rp));
+       mono_mb_emit_byte (mb, CEE_LDIND_REF);
+       mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoRealProxy, context));
+       mono_mb_emit_byte (mb, CEE_LDIND_REF);
+       mono_mb_emit_icall (mb, mono_context_get);
+       pos3 = mono_mb_emit_branch (mb, CEE_BEQ);
+
+       mono_mb_emit_exception_full (mb, "System", "InvalidOperationException", "Attempt to load field address from object in another context.");
+
+       mono_mb_patch_branch (mb, pos2);
+       mono_mb_patch_branch (mb, pos3);
+
+       /* return the address of the field from this->rp->unwrapped_server */
+       mono_mb_emit_ldarg (mb, 0);
+       mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoTransparentProxy, rp));
+       mono_mb_emit_byte (mb, CEE_LDIND_REF);
+       mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoRealProxy, unwrapped_server));
+       mono_mb_emit_byte (mb, CEE_LDIND_REF);
+       mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
+       mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
+       mono_mb_emit_ldarg (mb, 3);
+       mono_mb_emit_byte (mb, CEE_ADD);
+       mono_mb_emit_byte (mb, CEE_RET);
+
+       /* not a proxy: return the address of the field directly */
        mono_mb_patch_branch (mb, pos0);
 
        mono_mb_emit_ldarg (mb, 0);
index 3f4f8de7179fd0784890d2493f4720cb40ecad3b..41252f7aa36ed364bcdf56f93676eb2cdd2c6c06 100644 (file)
@@ -1,3 +1,8 @@
+
+2008-09-17  Robert Jordan  <robertj@gmx.net>
+
+       * Makefile.am: Add test for #415577.
+
 2008-09-16  Zoltan Varga  <vargaz@gmail.com>
 
        * bug-426309.2.il: New test.
index 3e14baa3c4e12b8922693f1d65b19236241a1e75..d4d8af6d15969d48ac1af9a3ad1bd8f7ef7ceb51 100644 (file)
@@ -310,7 +310,8 @@ BASE_TEST_CS_SRC=           \
        modules.cs      \
        bug-81673.cs    \
        bug-81691.cs    \
-       bug-80307.cs
+       bug-80307.cs    \
+       bug-415577.cs
 
 if AMD64
 TEST_CS_SRC = $(BASE_TEST_CS_SRC) async-exc-compilation.cs
diff --git a/mono/tests/bug-415577.cs b/mono/tests/bug-415577.cs
new file mode 100644 (file)
index 0000000..2195bcc
--- /dev/null
@@ -0,0 +1,102 @@
+using System;
+using System.Threading;
+using System.Runtime.Remoting;
+using System.Runtime.Remoting.Activation;
+using System.Runtime.Remoting.Contexts;
+using System.Runtime.Remoting.Messaging;
+
+public class MyContextAttribute: Attribute, IContextAttribute  {
+       public void GetPropertiesForNewContext (IConstructionCallMessage msg)
+       {
+       }
+
+       public bool IsContextOK (Context ctx, IConstructionCallMessage msg)
+       {
+               return false;
+       }
+}
+
+// CBO class whose objects are always in the corrent context
+class UnlockedCbo : ContextBoundObject {
+       public int Counter;
+
+
+       void Inc (ref int a)
+       {
+               a++;
+       }
+
+       public void Inc ()
+       {
+               Inc (ref Counter);
+       }
+}
+
+// CBO class whose objects are always out of context
+[MyContext]
+class LockedCbo : UnlockedCbo {
+}
+
+class Mbr : MarshalByRefObject {
+       public int Counter;
+
+       void Inc (ref int a)
+       {
+               a++;
+       }
+
+       public void Inc ()
+       {
+               Inc (ref Counter);
+       }
+}
+
+class Test {
+       static int Main ()
+       {
+               // warning CS0197 is expected several times
+               
+               UnlockedCbo uc = new UnlockedCbo ();
+               Interlocked.Increment (ref uc.Counter);
+               uc.Inc ();
+
+               LockedCbo lc = new LockedCbo ();
+               try {
+                       Interlocked.Increment (ref lc.Counter);
+                       return 1;
+               } catch (InvalidOperationException) {
+               }
+
+               lc.Inc ();
+
+               if (lc.Counter != 1)
+                       return 2;
+
+               Mbr m = new Mbr ();
+               Interlocked.Increment (ref m.Counter);
+               m.Inc ();
+
+               if (m.Counter != 2)
+                       return 3;
+
+               Mbr rm = (Mbr) CreateRemote (typeof (Mbr));
+               try {
+                       Interlocked.Increment (ref rm.Counter);
+                       return 4;
+               } catch (InvalidOperationException) {
+               }
+
+               rm.Inc ();
+
+               if (rm.Counter != 1)
+                       return 5;
+
+               return 0;
+       }
+
+       static object CreateRemote (Type t)
+       {
+               AppDomain d = AppDomain.CreateDomain ("foo");
+               return d.CreateInstanceAndUnwrap (t.Assembly.FullName, t.FullName);
+       }
+}