log4net не проходит проверку при компиляции - PullRequest
13 голосов
/ 28 ноября 2011

https://github.com/apache/log4net

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

[IL]: ошибка: [log4net.dll: log4net.Plugin.RemoteLoggingServerPlugin :: Attach] [смещение 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));
}

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

1 Ответ

5 голосов
/ 11 января 2012

Проблема связана с тем, что в .NET 4 Level 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 бессмысленным.

...