Bug 25087

Summary: System.Uri constructor throws an exception when parsing an HTTP URI with a username or password that contains certain escaped characters
Product: [Mono] Class Libraries Reporter: bugzilla
Component: SystemAssignee: marcos.henrich
Status: RESOLVED FIXED    
Severity: normal CC: masafa, mono-bugs+mono
Priority: ---    
Version: master   
Target Milestone: Untriaged   
Hardware: All   
OS: All   
Tags: Is this bug a regression?: ---
Last known good build:

Description bugzilla 2014-12-04 23:38:46 UTC
This snippet loops though all ASCII characters from 1 to 128 and attempts to create a System.Uri instance from a UriBuilder where the escaped representation of each character is the username portion of the URI.  If an exception is thrown for any character, it is printed to the console.


using System;

class MainClass
{
	public static void Main(string [] args)
	{
		UriBuilder builder = new UriBuilder("http://localhost");
		for (var ch = (char)1; ch < 128; ch++)
		{
			builder.UserName = Uri.EscapeDataString(ch.ToString());
			try
			{
				var unused = builder.Uri;
			}
			catch (Exception e)
			{
				Console.WriteLine("{0}: {1} {2}", e.GetType().Name, builder.UserName, (ch >= 31) ? ch.ToString() : "");
			}
		}
	}
}


Microsoft .NET framework 4.5 does not throw any exceptions and creates all Uri instances as expected.  Under mono 3.10, the program output is:


UriFormatException: %01 
... all the way to ...
UriFormatException: %20  
UriFormatException: %22 "
UriFormatException: %23 #
UriFormatException: %25 %
UriFormatException: %2F /
UriFormatException: %3C <
UriFormatException: %3E >
UriFormatException: %3F ?
NullReferenceException: %40 @
UriFormatException: %5B [
UriFormatException: %5C \
UriFormatException: %5D ]
UriFormatException: %5E ^
UriFormatException: %60 `
UriFormatException: %7B {
UriFormatException: %7C |
UriFormatException: %7D }
UriFormatException: %7F 


Setting builder.Password instead leads to the same exceptions being thrown (except for "@").  This basically prevents a username or password that contains any of the above characters from being used in a URI, and some characters (like # and %) are quite common in passwords.  The offending code is in UriParseComponents.cs on line 339 where certain characters are special-cased (AFTER being unescaped?) and characters which are not in the special-case list (including all of the ones in the output above) cause the parser to immediately punt, which of course prevents the host name from being parsed correctly.

In the case of the "@" character, this looks like a different but related bug.  The NullReferenceException only happens when the FIRST character of the username is an escaped "@" sign.  The bug is in UriParseComponents.cs on line 334 where it assumes that the StringBuilder() has been created when an escaped @ character is encountered, but this is not the case when it is the first character in the username.
Comment 1 marcos.henrich 2014-12-05 11:33:39 UTC
Hi bugzilla@skybound.ca

Thank you for the detailed bug report.

The pull request for this issue can be found in the link below.
https://github.com/mono/mono/pull/1443
Comment 2 marcos.henrich 2014-12-05 11:49:43 UTC
Fixed in master 385bda0cad58f34953cfc0b8e84a3a656a778c25.
https://github.com/mono/mono/commit/385bda0cad58f34953cfc0b8e84a3a656a778c25