views:

220

answers:

2

I just saw this question:

Understanding .NET’s “SecurityAction” parameter for permissions

And I have a question. With the following code:

private void button1_Click(object sender, EventArgs e)
{
    Layer1();
    MessageBox.Show("OK");
}

private void Layer1()
{
    try
    {
        Layer2();
    }
    catch (SecurityException)
    {
        MessageBox.Show("Caught");
    }
    Layer2b();
}

private void Layer2()
{
    new System.Security.Permissions.FileIOPermission(PermissionState.Unrestricted).Deny();
    GC.Collect();
    Layer3();
}

private void Layer2b()
{
    Layer3();
}

[FileIOPermission(SecurityAction.LinkDemand, Write=@"C:\temp")]
private void Layer3()
{
    using (FileStream stream = new FileStream(@"C:\temp\test.txt", FileMode.Create))
    {
    }
}

why does the code produce a security exception with the call to Layer2? How is the permission object treated, I'd imagine that the garbage collector would destroy the object, since I don't have an active reference to it, but the code says Caught, and then OK, so clearly the permission denial is in effect for the call through Layer2.

What gives? What am I missing? I'll admit to being a total beginner when it comes to the security/permission system in .NET so forgive me if this question is really basic.

Does a security permission/denial like this flag the stack or something? Otherwise, why is it not in effect for Layer2b? It's the same thread, so clearly, while it isn't killed by garbage collection, it is getting removed/destroyed/cleaned out at some point.

A: 

Upon first look, I would guess that the permission object is still in scope, as it is defined inside the method, it falls out of scope after the completion of the Layer2 method, thus allowing the last line of your application to function.

As noted by the accepted answer, this is becuase it is in scope for the current stack, related to standard object scope, you just don't manage the reference. That is the best way to remember it

Mitchel Sellers
No, that can definitely not be it. An object that you do not have an active reference to will get garbage collected if the collector is run, and I explicitly force it. Since I do not use the object any more (no references) it should be collected, and I guess it is, it just tweaked the stack first.
Lasse V. Karlsen
I apologize for my wording, it is LIKE an object, but YOU do not manage the reference. It stays on the stack until the method exits in the case of your example. Acting like a variable declaration.
Mitchel Sellers
+2  A: 

Calling .Deny() on a CodeAccessPermission will cause the .NET Security runtime to set the deny flag on the security object for the current stack frame for that permission. So even if you call GC.Collect() after calling .Deny(), it doesn't really matter, the permission will stay in effect. The permission object is just a representation of state of the part of the .NET security runtime at a point in time (a stack frame).

Just use .NET Reflector to learn more.

Strelok
I did try to use reflector, but I only dived in on the code in those methods, guess I need to dive further into the permission objects.
Lasse V. Karlsen