.NET Immutability Tip #2: Be careful of unprotected types in the executable.

I've seen this happen quite often.  When developers create their immutable types, they assume the only view the user will ever have is of the type through some interface.  Normally the interfaces are defined before-hand and included in some library that the user is supposed to link to.  This can easily be demonstrated by mocking up an IWorldView interface and then using this in our user code.

// Interfaces.dll
public interface IWorldView {
    int WorldSizeX { get; }
    int WorldSizeY { get; }
}

// UserPlugin.dll
public class UserClassConsumingIWorldView {
    public void EngineCallMe(IWorldView iwv) {
        // do some work
        int area = iwv.WorldSizeX * iwv.WorldSizeY;
    }
}

From the code above, you would assume that the user sees the world through IWorldView goggles.  That might not be the case.  When they develop their plug-in they have access to your executable as well.  While some .NET languages won't let you link against executables, C# will.  This can lead to some access elevation in that the user might be able to case IWorldView to a type with more access.

using System;

// Game.exe
public class WorldView : IWorldView {
    private int _worldSizeX;
    private int _worldSizeY;

    public int WorldSizeX { get { return this._worldSizeX; } }
    public int WorldSizeY { get { return this._worldSizeY; } }
   
    public void ResetWorldSize(int x, int y) {
        this._worldSizeX = x;
        this._worldSizeY = y;
    }
   
    private static void Main() { }
}

Woops, we defined our WorldView class as public making it available to the outside world.  Now the UserPlugin can cast to this guy and make use of ResetWorldSize().

using System;

public class UserClassConsumingIWorldView {
    public void EngineCallMe(IWorldView iwv) {
        // do some work
        int area = iwv.WorldSizeX * iwv.WorldSizeY;
        ((WorldView) iwv).ResetWorldSize(0, 0);
    }
}

You won't make this mistake twice, believe me.  Making the WorldView class internal will fix any issues with this possible casting and put you on your way.  In this case we assumed immutability of the world view because we thought we had control over the user's access when we really didn't through a common programming mistake.  Users in the VB world might never recognize this error, since they wouldn't be able to include Game.exe as a reference to begin with.

Published Saturday, April 10, 2004 10:48 PM by Justin Rogers

Comments

No Comments

Leave a Comment

(required) 
(required) 
(optional)
(required)