Let GetTransparentProxy fail clean on load error (bug 36848)
authorAndi McClure <andi.mcclure@xamarin.com>
Tue, 15 Dec 2015 18:47:56 +0000 (13:47 -0500)
committerAndi McClure <andi.mcclure@xamarin.com>
Tue, 15 Dec 2015 18:47:56 +0000 (13:47 -0500)
icall for Remoting.RealProxy.GetTransparentProxy can sometimes attempt
to load an invalid class which is not previously loaded. Currently,
this leads to an assert failure in mono_class_proxy_vtable which does
not expect to be getting an invalid proxy class as input. Fix is for
the icall to load the class early and raise on failure.

A test is included.

mono/metadata/icall.c
mono/tests/Makefile.am
mono/tests/bug-36848-a.cs [new file with mode: 0644]
mono/tests/bug-36848.cs [new file with mode: 0644]

index f2d76301c3c7d267a7cf9b3cf318c473b369a905..817f321be9d72ae84f40a7c64bd14e48a5334a6f 100644 (file)
@@ -5782,6 +5782,11 @@ ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this_obj, MonoStri
        type = ((MonoReflectionType *)rp->class_to_proxy)->type;
        klass = mono_class_from_mono_type (type);
 
+       // mono_remote_class_vtable cannot handle errors well, so force any loading error to occur early
+       mono_class_setup_vtable (klass);
+       if (klass->exception_type)
+               mono_raise_exception (mono_class_get_exception_for_failure (klass));
+
        tp->custom_type_info = (mono_object_isinst (this_obj, mono_defaults.iremotingtypeinfo_class) != NULL);
        tp->remote_class = mono_remote_class (domain, class_name, klass);
 
index d0e26ed52f4f4316ce009951cab79fc34230b557..132af7369c0482999eb778a85a6c04b271e4380c 100644 (file)
@@ -362,6 +362,7 @@ BASE_TEST_CS_SRC=           \
        bug-324535.cs   \
        modules.cs      \
        bug-81673.cs    \
+       bug-36848.cs    \
        bug-81691.cs    \
        bug-80307.cs    \
        bug-415577.cs   \
@@ -1197,6 +1198,12 @@ bug-81673.exe bug-81673-interface.dll: $(srcdir)/bug-81673.cs $(srcdir)/bug-8167
        $(MCS) -out:bug-81673.exe -r:bug-81673-interface.dll $(srcdir)/bug-81673.cs
        $(MCS) -define:WITH_STOP -target:library -out:bug-81673-interface.dll $(srcdir)/bug-81673-interface.cs
 
+EXTRA_DIST += bug-36848-a.cs.cs
+bug-36848.exe bug-36848-a.dll: $(srcdir)/bug-36848.cs $(srcdir)/bug-36848-a.cs
+       $(MCS) -target:library -out:bug-36848-a.dll $(srcdir)/bug-36848-a.cs
+       $(MCS) -r:bug-36848-a.dll -out:bug-36848.exe $(srcdir)/bug-36848.cs
+       $(MCS) -target:library -out:bug-36848-a.dll $(srcdir)/bug-36848-a.cs /define:WITH_STOP
+
 EXTRA_DIST += bug-81691-a.cs bug-81691-b.cs
 bug-81691.exe bug-81691-b.dll: $(srcdir)/bug-81691.cs $(srcdir)/bug-81691-a.cs $(srcdir)/bug-81691-b.cs
        $(MCS) -target:library -out:bug-81691-a.dll $(srcdir)/bug-81691-a.cs
diff --git a/mono/tests/bug-36848-a.cs b/mono/tests/bug-36848-a.cs
new file mode 100644 (file)
index 0000000..5af4354
--- /dev/null
@@ -0,0 +1,12 @@
+using System;
+
+namespace Application
+{
+       public interface IMyInterface
+       {
+               void Run ();
+#if WITH_STOP
+               void Stop ();
+#endif
+       }
+}
diff --git a/mono/tests/bug-36848.cs b/mono/tests/bug-36848.cs
new file mode 100644 (file)
index 0000000..f91447a
--- /dev/null
@@ -0,0 +1,52 @@
+// Load an interface from an invalid DLL and ensure the failure is clean.
+// Notice this is very similar to bug-81673, except the interface is loaded
+// through a transparent proxy instead of directly.
+
+using System;
+using System.Runtime.Remoting;
+using System.Runtime.Remoting.Proxies;
+using System.Runtime.Remoting.Messaging;
+
+namespace Application
+{
+       public class App
+       {
+               public static void Test ()
+               {
+               RemoteProxy remote2 = new RemoteProxy (typeof(App).Assembly.GetType("Application.Remote"));
+               remote2.GetTransparentProxy ();
+               }
+
+               public static int Main ()
+               {
+                       int numCaught = 0;
+
+                       for (int i = 0; i < 10; ++i) {
+                               try {
+                                       Test ();
+                               } catch (Exception) {
+                                       ++numCaught;
+                               }
+                       }
+                       if (numCaught == 10)
+                               return 0;
+                       return 1;
+               }
+       }
+
+       class Remote : MarshalByRefObject, IMyInterface {
+               public void Run ()
+               {
+               }
+       }
+
+       class RemoteProxy : RealProxy {
+               public RemoteProxy (Type t) : base (t) {
+
+               }
+
+               public override IMessage Invoke (IMessage request) {
+                       return null;
+               }
+       }
+}