Подтвердить что ты не робот

Log4net не проходит проверку при компиляции

https://github.com/apache/log4net

Я компилирую log4net из исходного кода, но он не проходит проверку:

[IL]: Ошибка: [log4net.dll: log4net.Plugin.RemoteLoggingServerPlugin:: Attach] [offset 0x00000029] Метод не отображается.

Код в порядке:

public interface ILoggerRepository
{
    ...
}

public interface IPlugin
{
    void Attach(ILoggerRepository repository);
}

public abstract class PluginSkeleton : IPlugin
{
    public virtual void Attach(ILoggerRepository repository) { }
}

public class RemoteLoggingServerPlugin : PluginSkeleton
{
    override public void Attach(ILoggerRepository repository)
    {
        base.Attach(repository);
        ...
    }
}

https://github.com/apache/log4net/blob/trunk/src/Plugin/IPlugin.cs

https://github.com/apache/log4net/blob/trunk/src/Plugin/PluginSkeleton.cs

https://github.com/apache/log4net/blob/trunk/src/Plugin/RemoteLoggingServerPlugin.cs

Исследование показывает, что он не смог вызвать RemotingServices.Marshal():

override public void Attach(ILoggerRepository repository)
{
    base.Attach(repository);

    // Create the sink and marshal it
    m_sink = new RemoteLoggingSinkImpl(repository);

    try
    {
         **RemotingServices.Marshal(m_sink, m_sinkUri, typeof(IRemoteLoggingSink));**
    }
    catch(Exception ex)
    {
        LogLog.Error(declaringType, "Failed to Marshal remoting sink", ex);
    }
}

Но здесь нет ничего важного. Более того, вызов RemotingServices.Marshal() с любым типом приводит к тем же проблемам:

Даже если я изменил Attach() на это:

override public void Attach(ILoggerRepository repository)
{
    RemotingServices.Marshal(null, null, typeof(int));
}

Может ли кто-нибудь определить, в чем проблема?

4b9b3361

Ответ 1

Проблема связана с тем, что с прозрачностью .NET 4 уровня 2 был введен. (Подробнее см. http://msdn.microsoft.com/en-us/library/dd233102.aspx.)

В методе override public void Attach(ILoggerRepository repository) отсутствует SecuritySafeCriticalAttribute. Добавление атрибута:

#if NET_4_0
    [System.Security.SecuritySafeCritical]
#endif
    override public void Attach(ILoggerRepository repository)
    {
        // ...
    }

сделает проверку проверки IL. (Также см. http://msdn.microsoft.com/en-us/library/bb397858.aspx для получения дополнительной информации.)

Обновление: Чтобы пролить немного света на то, почему проверка завершается с ошибкой (что может быть не сразу понято, просто прочитав статьи в приведенных ссылках), вот короткое объяснение.

RemotingServices.Marshal применяется атрибут [SecuritySafeCritical]. Поэтому можно предположить, что вызов метода из прозрачного метода будет разрешен. Однако RemotingServices.Marshal возвращает объект типа System.Runtime.Remoting.ObjRef, и указанный тип аннотируется с атрибутом [SecurityCritical].
Если код log4net сохранит ссылку на возвращаемое значение в локальной переменной, Code Analysis обнаружит ошибку и выдаст CA2140 предупреждение ("Прозрачный код не должен ссылаться на важные элементы безопасности ").
Теперь, очевидно, в соответствии с правилами прозрачности безопасности прозрачный метод не может вызывать безопасный критически важный метод, если вызываемый метод возвращает критический тип безопасности, даже если прозрачный метод не сохраняет ссылку на возвращаемый объект, как показано в следующем примере:

public class TransparencyRulesDemo
{
    [SecuritySafeCritical]
    public void SafeGetCritical()
    {
        GetCritical();
    }

    public void TransparentGetCritical()
    {
        // Below line will trigger a CA2140 warning if uncommented...
        // var critical = GetCritical();

        // ...the following line on the other hand will not produce any warning
        // but will lead to IL verification errors and MethodAccessExceptions if
        // called from transparent code.
        GetCritical();
    }

    [SecuritySafeCritical]
    public Critical GetCritical()
    {
        return new Critical();
    }
}

[SecurityCritical]
public class Critical
{

} 

Это кстати. делает атрибут [SecuritySafeCritical] на RemotingServices.Marshal бессмысленным.