2

In the .Net security blog article on SafeHandles, it mentions that you need to apply the ReliabilityContract attribute to the signature of the native method that closes the handle.

When we inherit from SafeHandle we have to declare a constructor, ReleaseHandle method and IsInvalid property, all of which have the ReliabilityContract applied in the base class (I used Reflector to have a look at SafeHandle):

[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
protected SafeHandle(IntPtr invalidHandleValue, bool ownsHandle);

[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
protected abstract bool ReleaseHandle();

public abstract bool IsInvalid { [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] get; }

ReliabilityContract has its inherited property set to false - which I think means that the methods we override will no longer have the attribute -- so, do we need to re-apply the attribute?

Glorfindel
  • 21,988
  • 13
  • 81
  • 109
jo0ls
  • 389
  • 1
  • 9
  • 2
    You make a promise that you've tested the heck out of your code and verified that it doesn't corrupt the state of the custom CLR host that relies on critical finalizers. Did you? If you don't actually run on such a host (SQL Server, really) then it doesn't really matter. – Hans Passant Oct 29 '11 at 12:38
  • Having had some difficulties with the same subject yesterday, I would like to add the following: The source code of `SafeHandle` (as per time of this writing) states that *every method* you are calling from `ReleaseHandle()` (and not only the native method which closes the handle) should have that `ReliabilityContract`. Please note also that handles are not *necessarily* closed by native methods; but even when they are closed by managed methods, the managed methods should have that `ReliabilityContract` as well. – Binarus Feb 09 '17 at 13:58

1 Answers1

2

Yes, you have to re-apply the attribute because the ReliabilityContract has its inherited property set to false and that means methods in derived classes won't have the attribute applied.

Take a look at the below code. If you set the Inherited named parameter to false, the Method1 in the derived class does not have the attribute applied. After that, set the same parameter (Inherited) to true and run it again.

[AttributeUsage(AttributeTargets.Method, Inherited=false)]
public class MyAttribute : Attribute { }

class BaseClass
{
    [My] // MyAttribute applied to base class
    public virtual void Method1() { }
}

class DerivatedClass : BaseClass
{
    // MyAttribute not applied to derivate class
    public override void Method1() { }
}

public class Program
{
    static void Main(string[] args)
    {
        var attributes = typeof(DerivatedClass)
            .GetMethod("Method1")
            .GetCustomAttributes(true);

        foreach (var attr in attributes)
        {
            Console.Write(attr.ToString());
        }
    }
} 
aevitas
  • 3,753
  • 2
  • 28
  • 39
lontivero
  • 5,235
  • 5
  • 25
  • 42