Avoid double escaping in PathString

This commit is contained in:
John Luo 2017-04-02 17:32:24 -07:00
parent f264659c95
commit 0da88e0dda
3 changed files with 39 additions and 6 deletions

View File

@ -28,5 +28,20 @@ namespace Microsoft.AspNetCore.Http.Internal
{
return c < ValidPathChars.Length && ValidPathChars[c];
}
public static bool IsPercentEncodedChar(string str, int index)
{
return index < str.Length - 2
&& str[index] == '%'
&& IsHexadecimalChar(str[index + 1])
&& IsHexadecimalChar(str[index + 2]);
}
public static bool IsHexadecimalChar(char c)
{
return ('0' <= c && c <= '9')
|| ('A' <= c && c <= 'F')
|| ('a' <= c && c <= 'f');
}
}
}

View File

@ -53,7 +53,7 @@ namespace Microsoft.AspNetCore.Http
}
/// <summary>
/// Provides the path string escaped in a way which is correct for combining into the URI representation.
/// Provides the path string escaped in a way which is correct for combining into the URI representation.
/// </summary>
/// <returns>The escaped path value</returns>
public override string ToString()
@ -77,9 +77,12 @@ namespace Microsoft.AspNetCore.Http
var start = 0;
var count = 0;
var requiresEscaping = false;
for (int i = 0; i < _value.Length; ++i)
var i = 0;
while (i < _value.Length)
{
if (PathStringHelper.IsValidPathChar(_value[i]))
var isPercentEncodedChar = PathStringHelper.IsPercentEncodedChar(_value, i);
if (PathStringHelper.IsValidPathChar(_value[i]) || isPercentEncodedChar)
{
if (requiresEscaping)
{
@ -96,7 +99,16 @@ namespace Microsoft.AspNetCore.Http
count = 0;
}
count++;
if (isPercentEncodedChar)
{
count += 3;
i += 3;
}
else
{
count++;
i++;
}
}
else
{
@ -116,6 +128,7 @@ namespace Microsoft.AspNetCore.Http
}
count++;
i++;
}
}
@ -146,6 +159,7 @@ namespace Microsoft.AspNetCore.Http
}
}
/// <summary>
/// Returns an PathString given the path as it is escaped in the URI format. The string MUST NOT contain any
/// value that is not a path.
@ -279,7 +293,7 @@ namespace Microsoft.AspNetCore.Http
}
/// <summary>
/// Adds two PathString instances into a combined PathString value.
/// Adds two PathString instances into a combined PathString value.
/// </summary>
/// <returns>The combined PathString value</returns>
public PathString Add(PathString other)
@ -297,7 +311,7 @@ namespace Microsoft.AspNetCore.Http
}
/// <summary>
/// Combines a PathString and QueryString into the joined URI formatted string value.
/// Combines a PathString and QueryString into the joined URI formatted string value.
/// </summary>
/// <returns>The joined URI formatted string value</returns>
public string Add(QueryString other)

View File

@ -195,6 +195,10 @@ namespace Microsoft.AspNetCore.Http
[InlineData("pct-encoding", "/单行道", "/%E5%8D%95%E8%A1%8C%E9%81%93")]
[InlineData("mixed1", "/index/单行道=(x*y)[abc]", "/index/%E5%8D%95%E8%A1%8C%E9%81%93=(x*y)%5Babc%5D")]
[InlineData("mixed2", "/index/单行道=(x*y)[abc]_", "/index/%E5%8D%95%E8%A1%8C%E9%81%93=(x*y)%5Babc%5D_")]
[InlineData("encoded", "/http%3a%2f%2f[foo]%3A5000/", "/http%3a%2f%2f%5Bfoo%5D%3A5000/")]
[InlineData("encoded", "/http%3a%2f%2f[foo]%3A5000/%", "/http%3a%2f%2f%5Bfoo%5D%3A5000/%25")]
[InlineData("encoded", "/http%3a%2f%2f[foo]%3A5000/%2", "/http%3a%2f%2f%5Bfoo%5D%3A5000/%252")]
[InlineData("encoded", "/http%3a%2f%2f[foo]%3A5000/%2F", "/http%3a%2f%2f%5Bfoo%5D%3A5000/%2F")]
public void ToUriComponentEscapeCorrectly(string category, string input, string expected)
{
var path = new PathString(input);