locked
System.Security.VerificationException: Operation could destabilize the runtime during code coverage run in visual studio RRS feed

  • Question

  • I have a unit test that basically does the following:

    Creates an app domain using minimum priviledges.  The MarshalByRefObject that is living in the app domain, loads another assembly to execute.  This new assembly basically takes in a data object defined in a separate assembly, and returns a new data object of that type.

    All this works fine in debug mode, or when running w/out code coverage.  The Sandbox assembly is signed.

    The exception that gets thrown is this:

    Test method TestProject1.UnitTest1.TestMethod1 threw exception:
    System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.Security.VerificationException: Operation could destabilize the runtime.

    ClassLibrary3.Bar..ctor()
    ClassLibrary2.Foo.TestMethod(Bar testBar)
    System.RuntimeMethodHandle._InvokeMethodFast(IRuntimeMethodInfo method, Object target, Object[] arguments, SignatureStruct& sig, MethodAttributes methodAttributes, RuntimeType typeOwner)
    System.RuntimeMethodHandle.InvokeMethodFast(IRuntimeMethodInfo method, Object target, Object[] arguments, Signature sig, MethodAttributes methodAttributes, RuntimeType typeOwner)
    System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, Boolean skipVisibilityChecks)
    System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
    System.Reflection.MethodBase.Invoke(Object obj, Object[] parameters)
    ClassLibrary1.RemoteSandBox.Execute(String assemblyPath, String scriptType, String method, Object[] parameters)
    ClassLibrary1.RemoteSandBox.Execute(String assemblyPath, String scriptType, String method, Object[] parameters)
    ClassLibrary1.SandBox.Execute(String assemblyPath, String scriptType, String method, Object[] parameters) in c:\users\la22426\documents\visual studio 2010\Projects\TestProject1\ClassLibrary1\Sandbox.cs: line 43
    TestProject1.UnitTest1.TestMethod1() in c:\users\la22426\documents\visual studio 2010\Projects\TestProject1\TestProject1\UnitTest1.cs: line 21

    Unit Test code:

        [TestClass]
        public class UnitTest1
        {
            [TestMethod]
            public void TestMethod1()
            {
                using (SandBox sandbox = new SandBox())
                {                
                    string assemblyLocation = Path.Combine(Environment.CurrentDirectory, @"..\..\..\ClassLibrary2\bin\Debug\ClassLibrary2.dll");
                    object result = sandbox.Execute(assemblyLocation, "ClassLibrary2.Foo", "TestMethod", new Bar() { X = "test" });
                    Assert.IsNotNull(result);
                }
            }
        }

    Data Object code:

    namespace ClassLibrary3
    {
        [Serializable]
        public class Bar
        {
            public Bar() { }
    
            public string X { get; set; }
        }
    }
    

    Assembly to execute code:

    namespace ClassLibrary2
    {
        public class Foo
        {
            public Bar TestMethod(Bar testBar)
            {
                return new Bar() { X = testBar.X };
            }
        }
    }

    Sandbox code:

    namespace ClassLibrary1
    {
        public class SandBox : IDisposable
        {
            AppDomain Domain { get; set; }
            RemoteSandBox RemoteSandBox { get; set; }
    
            public SandBox()
            {
                var setup = new AppDomainSetup()
                {
                    ApplicationBase = AppDomain.CurrentDomain.BaseDirectory,
                    ApplicationName = Guid.NewGuid().ToString(),
                    DisallowBindingRedirects = true,
                    DisallowCodeDownload = true,
                    DisallowPublisherPolicy = true,
                    //DisallowApplicationBaseProbing = true,
                };
    
                var permissions = new PermissionSet(PermissionState.None);
                permissions.AddPermission(new SecurityPermission(SecurityPermissionFlag.Execution));
                permissions.AddPermission(new ReflectionPermission(PermissionState.Unrestricted));
                this.Domain = AppDomain.CreateDomain(setup.ApplicationName, null, setup, permissions,
                    typeof(RemoteSandBox).Assembly.Evidence.GetHostEvidence<StrongName>());
    
                this.RemoteSandBox = (RemoteSandBox)Activator.CreateInstanceFrom(this.Domain, typeof(RemoteSandBox).Assembly.ManifestModule.FullyQualifiedName, typeof(RemoteSandBox).FullName).Unwrap();
            }
    
            public object Execute(string assemblyPath, string scriptType, string method, params object[] parameters)
            {
                return this.RemoteSandBox.Execute(assemblyPath, scriptType, method, parameters);
            }
    
            public void Dispose()
            {
                if (this.Domain != null)
                {
                    AppDomain.Unload(this.Domain);
                }
            }
        }
    
        class RemoteSandBox : MarshalByRefObject
        {
            public RemoteSandBox()
            {
            }
    
            public object Execute(string assemblyPath, string scriptType, string method, params object[] parameters)
            {
                //we need some file io permissions to load the assembly
                new FileIOPermission(FileIOPermissionAccess.Read | FileIOPermissionAccess.PathDiscovery, assemblyPath).Assert();
                Assembly assembly;
                try
                {
                    assembly = Assembly.LoadFile(assemblyPath);
                }
                finally
                {
                    CodeAccessPermission.RevertAssert();
                }
    
                Type type = assembly.GetType(scriptType, true);
                MethodInfo methodInfo = type.GetMethod(method);
                object instance = (methodInfo.IsStatic) ? null : Activator.CreateInstance(type);
                object returnVal = null;
                returnVal = methodInfo.Invoke(instance, parameters);
                return returnVal;
            }
        }
    }

    Friday, May 11, 2012 3:04 PM

Answers

  • Setting the ruleset to level1 [assembly: SecurityRules(SecurityRuleSet.Level1)] in the data assembly seems to have done the trick.  And I didn't need the SecuritySafeCriticalAttribute.  I also didn't need to set SkipVerificationInFullTrust.

    • Proposed as answer by Kris444 Monday, May 14, 2012 1:50 PM
    • Marked as answer by Mike Feng Tuesday, May 22, 2012 9:34 AM
    Monday, May 14, 2012 1:48 PM

All replies

  • Hi Lars,

    The problem seems to be related to the Code Coverage you activated. Disabling code coverage solves the issue. You could put the following in your AssemblyInfo.cs:

    [assembly: SecurityRules(SecurityRuleSet.Level1, SkipVerificationInFullTrust = true)]

    and reactivate code coverage.

    Hope it helps !!!


    Regards, http://shwetamannjain.blogspot.com

    Sunday, May 13, 2012 5:39 AM
  • Setting the assembly attribute has no afffect - I tried on all assemblies.  Which assembly were you thinking?  Disabling code coverage isn't an option, since I want code coverage numbers to include the unit tests that are executing partial trust scenarios.

    -Lars

    Monday, May 14, 2012 12:49 PM
  • I marked the shared data library with the attributes:

    [assembly: AllowPartiallyTrustedCallers]
    [assembly: SecurityRules(SecurityRuleSet.Level2, SkipVerificationInFullTrust = true)]

    And then marked  the data class Bar with the attribute:

    [SecuritySafeCritical]

    And got a little more insight into what's going on:

    Test method TestProject1.UnitTest1.TestMethod1 threw exception:
    System.MethodAccessException: Attempt by security transparent method 'Microsoft.VisualStudio.Coverage.Init_d2f466df4c65e2a7bb5d7592c49efef0.Register()' to call native code through method 'Microsoft.VisualStudio.Coverage.Init_d2f466df4c65e2a7bb5d7592c49efef0.VSCoverRegisterAssembly(UInt32[], System.String)' failed.  Methods must be security critical or security safe-critical to call native code.

    Microsoft.VisualStudio.Coverage.Init_d2f466df4c65e2a7bb5d7592c49efef0.Register()
    ClassLibrary3.Bar..ctor() in c:\users\xxx\documents\visual studio 2010\Projects\TestProject1\ClassLibrary3\Bar.cs: line 13
    TestProject1.UnitTest1.TestMethod1() in c:\users\xxx\documents\visual studio 2010\Projects\TestProject1\TestProject1\UnitTest1.cs: line 21

    Since the injected code coverage il is doing some native stuff, it's throwing.  Any ideas on how to allow this?

    Monday, May 14, 2012 1:39 PM
  • Setting the ruleset to level1 [assembly: SecurityRules(SecurityRuleSet.Level1)] in the data assembly seems to have done the trick.  And I didn't need the SecuritySafeCriticalAttribute.  I also didn't need to set SkipVerificationInFullTrust.

    • Proposed as answer by Kris444 Monday, May 14, 2012 1:50 PM
    • Marked as answer by Mike Feng Tuesday, May 22, 2012 9:34 AM
    Monday, May 14, 2012 1:48 PM
  • I also needed to add the strong name of the data assembly in the list of fully trusted assemblies when calling AppDomain.CreateDomain.

    Monday, May 14, 2012 1:56 PM
  • The "Operation Could Destabilize the runtime" was fixed for us by installing KB hotfix 2748645

    I would post this as a link but Microsoft thinks a link to one of their websites (support.microsoft.com) might be spam (?)
    support.microsoft.com/kb/2748645

    Anybody still having this problem may want to try that hotfix to see if it fixes .Net 4.0/4.5 without additional work.

    Tuesday, October 29, 2013 8:25 PM
  • Hi Lars,

    Did u get a solution for your problem..?  If so can u please post the solution for this.?

    Even i have struck with the same kinda problem.

    ./Selva

    Friday, January 30, 2015 4:25 AM