12

Partially from a curious breaking things point of view and partially from a safeguarding against potential problems. Imagine what is the worst that can happen by calling the following (or something similar, but string.Empty is a good examples):

typeof(String).GetField("Empty", 
    BindingFlags.Public | 
    BindingFlags.NonPublic | 
    BindingFlags.Static | 
    BindingFlags.GetField
).SetValue(null, "foo" );

This would cause problems when there's code somewhere that does x = myClass.bar ?? string.Empty.

Is there any way (akin to different app domains or similar) to protect against (or detect) someone changing values like String.Empty or perhaps the SqlDateTime.MinValue (or other similar readonly fields in .NET)?

Mogsdad
  • 44,709
  • 21
  • 151
  • 275
Seph
  • 8,472
  • 10
  • 63
  • 94
  • Related? http://stackoverflow.com/questions/4447939/is-it-possible-to-disable-reflection-from-a-net-assembly – harold Mar 25 '12 at 13:47
  • 8
    You can't prevent trusted code from doing bad stuff. And untrusted code can't modify `string.Empty`. And the shooting yourself in the foot is pretty explicit in this case. – CodesInChaos Mar 25 '12 at 13:53
  • 1
    By the way, isn't `Int.MaxValue` a *constant* field? – harold Mar 25 '12 at 13:57
  • 7
    String.Empty is *readonly*, not *const*. That's a very significant optimization at runtime, a direct pointer load and no garbage collection. Fast and safe are often conflicting goals. There are not exactly a lot of questions at SO from programmers that accidentally corrupted String.Empty, this is not a real problem. The SO faq needs to apply here: `practical, answerable questions based on actual problems that you face`. – Hans Passant Mar 25 '12 at 16:05
  • 9
    @HansPassant, I guess its not about String.Empty, but such code can lead to security issue, read only means read only, if I set some hash key or things like that assuming no one will modify, I will leave a security hole. I guess .net runtime should maintain reflection consistency at runtime same as that of compile time. And I really do not think that this question does not fit in SO criteria, it is very well a problem. – Akash Kava Mar 26 '12 at 08:07
  • @AkashKava How is it a "security" issue? If you're loading and running untrusted code into your process _and_ letting it use reflection APIs then you have a lot more to worry about than `readonly` fields being mutated, besides, [the code is already on the other side of the airtight hatchway](https://devblogs.microsoft.com/oldnewthing/20060508-22/?p=31283). – Dai Nov 16 '21 at 06:52

1 Answers1

7

You could define your own const fields in your assembly like so:

internal const string Empty = "";

And then perform a check against String.Empty, but it's pretty much a futile effort.

You'd have to perform a check everywhere you access String.Empty and effectively replace it (since you'd check at the point of comparison, there's no point in actually using String.Empty over your version anymore).

Since it's const, the value couldn't be changed, which is good, but at the same time, if the value of String.Empty does ever change (however unlikely), you'll have to make the change to your value, and then recompile everything that references that field.

Of course, you could make your version readonly, but then you'd be vulnerable to having the value changed through reflection, and you're right back where you started.

Add to that the fact that if String.Empty was changed, not only would comparisons against the field be affected, but I'd imagine a tremendous number of methods in the BCL would just not work properly; looking through Reflector, it would seem it's referenced a few hundred times in mscorlib (.NET 4.0) alone:

references to String.Empty in mscorlib 4.0

So that said, you could try and guarantee that the value wasn't changed, but it just isn't practical (it will be an eternal game of cat-and-mouse), chances are, from the perspective of your program, if the value of String.Empty was changed, the world would end, and the program would die a horrible death fairly quickly almost as soon as it was changed.

casperOne
  • 73,706
  • 19
  • 184
  • 253