Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Check if a string is a literal string known at compile time?

Tags:

string

c#

I am writing a library, and I have a method which takes in a Dictionary. The value of the dictionary is untrusted/insecure, but the key is trusted and if an end-user were given the ability to enter an arbitrary key name then "bad things" could happen.

So when other developers use this library function, I want to force them to know the key name at compile time. So something like this would be allowed:

string userInput = Console.ReadLine(); 
Dictionary<string, string> something = new Dictionary<string, string>();   
something.Add("MyKey", userInput);    

Because "MyKey" is a string literal, known at compile time. But something like this would either raise a compile or runtime exception:

string userInput = Console.ReadLine();
string userKey = Console.ReadLine(); 
Dictionary<string, string> something = new Dictionary<string, string>();   
something.Add(userKey, userInput);    

Because user input was used for the key (userKey) and thus it was unknown at compile time.

I've looked in GetType() and there is nothing that really distinguishes between a literal string and a string created at runtime.

like image 755
Safari Jones Avatar asked Jun 24 '15 20:06

Safari Jones


2 Answers

You can use string.IsInterned to determine if the string is interned. All compile time literals will be interned by default, but you can turn this off using a compiler flag.

This is a runtime check, not a compile time check.

Also note that non-compile time literals can be interned using the string.Intern function, so technically you can have non-literal strings pass your test. But if your program is either not interning strings at any point, or only ever interning strings you know are safe, then this may work.


Another option, if all of your keys are supposed to be known at compile time, is to not have the key be a string at all. Make the key be an enumeration, for example, so that you know that the only values that can ever be used as keys are on a list you've fixed at compile time.

like image 116
Servy Avatar answered Sep 28 '22 01:09

Servy


Not extensively tested, but by using expressions instead of direct values, you could test the type of value being passed. e.g.

void Add(Expression<Func<string>> fn)
{
        if (fn.Body.NodeType != ExpressionType.Constant)
            throw new ArgumentException("Only literal strings are allowed");

        //and extra check if the value itself is interned
        var val = fn.Compile()();
        if (string.IsInterned(val) == null)
            throw new ArgumentException("Only literal strings are allowed");

}

Then the developer has to pass the argument as a lambda:

  Add(() => "Test"); //Valid
  string somestring = "Test";
  Add(() => somestring); //Error
like image 44
Me.Name Avatar answered Sep 28 '22 03:09

Me.Name