9

我无法理解如何为 C++/CLI 项目修复 CA2123。这是一个演示该问题的示例项目:

1) 创建一个 C# (.NET 4) 类库

托管类.cs

命名空间 CSharpLibrary {

public interface IManagedClass
{
    void WriteSomething();
}

public class ManagedClass : IManagedClass
{
    public void WriteSomething()
    {
    }
}

}

2)创建一个 C++/CLI 控制台应用程序(VS 2010):

装配信息.cpp

#include "stdafx.h"

using namespace System;
using namespace System::Reflection;
using namespace System::Runtime::CompilerServices;
using namespace System::Runtime::InteropServices;
using namespace System::Security;

[assembly:AssemblyTitleAttribute("CPlusPlusCLIConsoleApp")];
[assembly:AssemblyDescriptionAttribute("")];

[assembly:AssemblyVersionAttribute("1.0.*")];

[assembly:ComVisible(false)];

[assembly:CLSCompliantAttribute(false)];

[assembly:SecurityCritical];

CPlusPlusCLIConsoleApp.h

#pragma once

using namespace CSharpLibrary;
using namespace System::Security;

typedef void* (__cdecl FACTORY_PROC)();

namespace CPlusPlusCLIConsoleApp
{
    public ref class MainClass : public IManagedClass
    {
    public:
        [SecurityCritical]
        virtual void WriteSomething();
    };

};

CPlusPlusCLIConsoleApp.cpp

#include "stdafx.h"
#include "CPlusPlusCLIConsoleApp.h"

using namespace System;

int main(){};

namespace CPlusPlusCLIConsoleApp
{
    [SecurityCritical]
    void MainClass::WriteSomething()
    {
    }
};

启用所有 Microsoft 安全规则后,我收到以下警告:

CA2123 覆盖链接需求应与基本相同

将以下安全属性添加到“MainClass::WriteSomething(void)”以匹配基础方法“IManagedClass::WriteSomething(void)”上的 LinkDemand:“SecurityCriticalAttribute”。

CPlusPlusCLIConsoleApp cpluspluscliconsoleapp.cpp 13

我试图遵循这个StackOverflow 答案的建议,但它没有修复错误。

我知道托管 dll 默认为 SecurityCritical(我不想在我的原始项目中更改它),因为我没有指定任何 SecurityAttribute。为什么 C++ CLI dll 不遵循相同的默认值?

我应该遵循哪些步骤来修复此错误?(基本上我怎样才能在 C++ CLI 中创建 WriteSomething 方法 SecurityCritical)

编辑 1:我在MSDN上问过同样的问题。

编辑 2:联系了微软,这是一种设计行为。C++\CLI 团队只是没有时间为 C++\CLI 实施 Level2 Security。因此 C++\CLI 总是停留在 Level1 Security。可以安全地抑制相同的代码分析警告。

4

1 回答 1

9

这里的根本问题是您的 C# 和 C++ 程序集使用两种不同的透明度模型(请参阅http://blogs.msdn.com/b/shawnfa/archive/2009/11/11/transparency-models-a-tale-of -two-levels.aspxhttp://blogs.msdn.com/b/shawnfa/archive/2009/11/12/differences-between-the-security-rule-sets.aspx了解两个级别的详细信息)。这是因为默认情况下 C# 程序集编译为级别 2,但由于某些明显未记录的原因,编译器会自动将 C++ 程序集强制降至级别 1。不幸的是,后一种行为似乎不可替代。更糟糕的是,它在 VS2012 中似乎并没有改变,而且看起来产品团队也没有考虑很快改变它

鉴于您无法将 C++ 程序集移至级别 2,如果您想将可执行文件保留在 C++ 中并且它必须包含接口实现,则有几个可能可行的选择:

  1. 通过使用 SecurityRulesAttribute 将 C# 程序集移至级别 1。这大概只有在 C++ 控制台应用程序是 C# 库的唯一使用者时才可以接受。
  2. 通过使用 PermissionSetAttribute 将 2 级安全关键性“升级”再现为完全信任链接/继承需求。例如:

    [SecurityCritical]
    [PermissionSet(SecurityAction::LinkDemand, Unrestricted = true)]
    [PermissionSet(SecurityAction::InheritanceDemand, Unrestricted = true)]
    virtual void WriteSomething();
    

提交另一个关于Connect的错误报告(投票给已关闭的错误似乎不是很有用)或在UserVoice上提交功能请求以请求更改编译器行为也可能是值得的。(鉴于 2 级应该是 .NET 4.0 及更高版本的默认设置,锁定到 1 级是非常奇怪的。)

于 2013-07-11T13:09:55.543 回答