Merge pull request #2106 from lambdageek/dev/bug-29108-part1
authorJoão Matos <joao@tritao.eu>
Wed, 14 Oct 2015 15:34:31 +0000 (16:34 +0100)
committerJoão Matos <joao@tritao.eu>
Wed, 14 Oct 2015 15:34:31 +0000 (16:34 +0100)
GetCallingAssembly() skip past reflection. Fix #29108 - part 1

mcs/class/corlib/Test/System.Reflection/AssemblyTest.cs
mono/metadata/icall.c

index 867efc7379d78f83eb79a8a31a28388a49099d31..7a09dcae67032906ba6e673b0dbe6a995da7a8b8 100644 (file)
@@ -42,6 +42,7 @@ using System.Reflection.Emit;
 #endif
 using System.Threading;
 using System.Runtime.Serialization;
+using System.Runtime.CompilerServices;
 using System.Security;
 using System.Linq;
 using System.Resources;
@@ -1233,6 +1234,67 @@ namespace MonoTests.System.Reflection
                        } catch (ArgumentException) {}
                }
 
+               class GetCallingAssemblyCallee {
+                       static int _dummy;
+
+                       static void sideEffect () {
+                               _dummy++;
+                       }
+
+                       // GetCallingAssembly may see an unpredictable
+                       // view of the stack if it's called in tail
+                       // position, or if its caller or the caller's
+                       // caller is inlined.  So we put in a side
+                       // effect to get out of tail position, and we
+                       // tag the methods NoInlining to discourage
+                       // the inliner.
+                       [MethodImplAttribute (MethodImplOptions.NoInlining)]
+                       public static Assembly Leaf () {
+                               var a = Assembly.GetCallingAssembly ();
+                               sideEffect();
+                               return a;
+                       }
+
+                       [MethodImplAttribute (MethodImplOptions.NoInlining)]
+                       public static Assembly DirectCall () {
+                               var a = Leaf();
+                               sideEffect();
+                               return a;
+                       }
+
+                       [MethodImplAttribute (MethodImplOptions.NoInlining)]
+                       public static Assembly InvokeCall () {
+                               var ty = typeof (GetCallingAssemblyCallee);
+                               var mi = ty.GetMethod("Leaf");
+                               var o = mi.Invoke(null, null);
+                               sideEffect();
+                               return (Assembly)o;
+                       }
+               }
+
+               [Test]
+               public void GetCallingAssembly_Direct() {
+                       var a = GetCallingAssemblyCallee.DirectCall ();
+                       Assert.IsNotNull (a);
+
+                       Assert.AreEqual (GetType().Assembly, a);
+               }
+
+               [Test]
+               public void GetCallingAssembly_SkipsReflection () {
+                       // check that the calling assembly is this
+                       // one, not mscorlib (aka, the reflection
+                       // API).
+                       var a = GetCallingAssemblyCallee.InvokeCall ();
+                       Assert.IsNotNull (a);
+
+                       var invokeAssembly =
+                               typeof (MethodInfo).Assembly;
+                       Assert.AreNotEqual (invokeAssembly, a);
+
+                       Assert.AreEqual (GetType().Assembly, a);
+               }
+
 #if NET_4_5
                [Test]
                public void DefinedTypes_Equality ()
index 432f7e9b4237210403b9ccc82e2e02528f222b35..0eb6dc749e94613493447f4a687780d895628af2 100644 (file)
@@ -4627,7 +4627,7 @@ ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
        dest = NULL;
        mono_stack_walk_no_il (get_executing, &dest);
        m = dest;
-       mono_stack_walk_no_il (get_caller, &dest);
+       mono_stack_walk_no_il (get_caller_no_reflection, &dest);
        if (!dest)
                dest = m;
        return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);