4

here is the problem case i am writing a little third party library. In this library i have a class like this

public class TestClass
    {
        public int TestField { get; private set; }

        public TestClass( )
        {
            TestField = 1;
        }
    }

Then i have a varialbe form this class like this

 public TestClass test = new TestClass( );

The problem i am facing is that usnig reflection like this

PropertyInfo field = typeof( TestClass ).GetProperty( "TestField" );
            field.SetValue( test, 2, null );

programers can change internal value of this class. this will be very bad thing becouse it can crash the hole library. My question is what is the best way to protect my code form such changes.I know i can use some kind of bool flag so tha value can be changed only ones but this is not very good salution is there a better one?
Best Regards,
Iordan

Ryan R
  • 8,342
  • 15
  • 84
  • 111
IordanTanev
  • 6,130
  • 5
  • 40
  • 49
  • 3
    I really wouldn't worry about it. If someone goes to that much trouble to change a property then I think they are responsible for the consequences. You've marked the setter private. That is all you should do. What situations do you think would arise where a programmer would even try to do this to your library? I think you're leaning toward over design. – Mike Two Apr 25 '10 at 06:39

4 Answers4

6

Please understand that I mean this with all respect:

You are wasting your time. Seriously.

Reflection is not to be considered when specifying an API or contract.

Believe this. It is not possible to stop reflection. If a consumer is bent on peeking into your code and flipping bits that have been hidden for a reason, well, the consequences are on them, not you.

Sky Sanders
  • 36,396
  • 8
  • 69
  • 90
6

You are trying to protect your system from something that is stronger than your code. If you don't trust certain code, run it with partial trust - then when it asks to reflect your type it will be denied.

Reflection (and related techniques like DynamicMethod) can with enough trust get virtually unrestricted access to your data (even, for example, changing the characters of a string without ever re-assigning it); thus you must reduce trust for non-trusted code.

In a similar way, anyone with debugger or admin access to your process (or the dlls it loads) can subvert your code. This is not an interesting attack, as the "hacker" must already have at least as much access than your code (probably more).

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • The attack is interesting in the case of an anti-theft or anti-tampering package. You can't really protect against somebody crashing your app if they have full control over your app, but you can make it much more difficult to modify certain key state that enforces your protection scheme. I don't think this is what the OP is doing, however. – Dan Bryant Apr 25 '10 at 10:26
2

You can even change the private readonly field using reflection. So, your best bet may the const.

Community
  • 1
  • 1
KMån
  • 9,896
  • 2
  • 31
  • 41
0

Use ReadOnly value, if you want a constant value. or just use const.

Use Enum, in case that you have a few 'safe values' that you want to customer (programmer) to choose one of them.

Edit: Apparently, enum not safe enough. you can use readonly field with the following format:

public class SafeValue
{
    private string _value;

    public static readonly SafeValue Value1 = new SafeValue("value1");
    public static readonly SafeValue Value2 = new SafeValue("value2");

    private SafeValue(string value)
    {
        _value = value;
    }

    public override string ToString()
    {
        return _value;
    }
}
Fitzchak Yitzchaki
  • 9,095
  • 12
  • 56
  • 96
  • readonly would work, assuming the value never needs to change once set in the constructor, but how does Enum help? Someone can still change the value through reflection. – Mike Two Apr 25 '10 at 06:40
  • 3
    @Mendy - enums are not validated; I can change your enum value to -142526 and the system won't care. – Marc Gravell Apr 25 '10 at 08:12
  • @Marc interesting. care to say how? – Fitzchak Yitzchaki Apr 25 '10 at 08:22
  • 3
    @Mendy - you can cast any int value. The compiler doesn't check. so 'SomeEnum value = -142526;' Won't compile but `SomeEnum value = (SomeEnum) -142526;` will. Even if -142526 isn't a valid value in `SomeEnum`. – Mike Two Apr 25 '10 at 08:58
  • 1
    @Marc now I'm totally confused. the `readonly` directive compiled into MSIL, but not honored? – Fitzchak Yitzchaki Apr 25 '10 at 09:49
  • readonly can't force the field to never change via Reflection (or direct memory tweaking), but it could create all sorts of interesting side effects due to compiler optimizations assuming the field never changes. – Dan Bryant Apr 25 '10 at 10:17
  • 2
    @Mendy - yup; this is required for remoting and some (not all) forms of serialization – Marc Gravell Apr 25 '10 at 17:23