Yep. I've found an honest-to-goodness bug in the framework. And it's genuine, too. Not one of your "my code's not working, .net's broken" bugs. Nope. I've got proof.
Uri.IsHexEncoding checks for the pattern %hexhex is at a particular offset in a string. So you can write something like this to check if a string is uri encoded:
public bool IsUriEncoded(string uri)
{
for(int i=0;i<uri.Length;i++)
{
if(Uri.IsHexEncoding(uri,i))
return true;
}
return false;
}
For a string such as "/path/%2f/hello", it will return true. For a string such as "/path/%xx/hello", it will return false.
Fancy finding a bug? Get your mince pies round this - it's the source for Uri.IsHexEncoding (this snippet brought to you by the letter "Reflector"):
public static bool IsHexEncoding(string pattern, int index)
{
if(((pattern.Length - index) >= 3)
&& ((pattern[index] == '%')
&& (Uri.EscapedAscii(pattern[index + 1],
pattern[index + 1]) != 0xffff)))
{
return true;
}
return false;
}
Spotted it yet? Try the string "%2y". It returns true.
The second parameter to Uri.EscapedAscii should be "pattern[index + 2]", not "pattern[index + 1]".
My feeling is that this method would be mostly used in a security checking context, so it's really important it works correctly.
So, a proper bug. I've reported it as a bug on Microsoft Connect (log in required). I've even added a comment to the msdn docs page (which is a really rather cool feature). I couldn't be more helpful even if I went round everyone's computers and fixed their code for them.
PS. It's dead easy to work around. You'll probably call it in a loop like the one above. Just change the line calling Uri.IsHexEncoding to:
if(uri[i]=='%' && Uri.IsHexDigit[i+1] && Uri.IsHexDigit[i+2)
return true;