Skip to content
This repository was archived by the owner on Nov 20, 2018. It is now read-only.

Commit 0da88e0

Browse files
committed
Avoid double escaping in PathString
1 parent f264659 commit 0da88e0

File tree

3 files changed

+39
-6
lines changed

3 files changed

+39
-6
lines changed

src/Microsoft.AspNetCore.Http.Abstractions/Internal/PathStringHelper.cs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,5 +28,20 @@ public static bool IsValidPathChar(char c)
2828
{
2929
return c < ValidPathChars.Length && ValidPathChars[c];
3030
}
31+
32+
public static bool IsPercentEncodedChar(string str, int index)
33+
{
34+
return index < str.Length - 2
35+
&& str[index] == '%'
36+
&& IsHexadecimalChar(str[index + 1])
37+
&& IsHexadecimalChar(str[index + 2]);
38+
}
39+
40+
public static bool IsHexadecimalChar(char c)
41+
{
42+
return ('0' <= c && c <= '9')
43+
|| ('A' <= c && c <= 'F')
44+
|| ('a' <= c && c <= 'f');
45+
}
3146
}
3247
}

src/Microsoft.AspNetCore.Http.Abstractions/PathString.cs

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ public bool HasValue
5353
}
5454

5555
/// <summary>
56-
/// Provides the path string escaped in a way which is correct for combining into the URI representation.
56+
/// Provides the path string escaped in a way which is correct for combining into the URI representation.
5757
/// </summary>
5858
/// <returns>The escaped path value</returns>
5959
public override string ToString()
@@ -77,9 +77,12 @@ public string ToUriComponent()
7777
var start = 0;
7878
var count = 0;
7979
var requiresEscaping = false;
80-
for (int i = 0; i < _value.Length; ++i)
80+
var i = 0;
81+
82+
while (i < _value.Length)
8183
{
82-
if (PathStringHelper.IsValidPathChar(_value[i]))
84+
var isPercentEncodedChar = PathStringHelper.IsPercentEncodedChar(_value, i);
85+
if (PathStringHelper.IsValidPathChar(_value[i]) || isPercentEncodedChar)
8386
{
8487
if (requiresEscaping)
8588
{
@@ -96,7 +99,16 @@ public string ToUriComponent()
9699
count = 0;
97100
}
98101

99-
count++;
102+
if (isPercentEncodedChar)
103+
{
104+
count += 3;
105+
i += 3;
106+
}
107+
else
108+
{
109+
count++;
110+
i++;
111+
}
100112
}
101113
else
102114
{
@@ -116,6 +128,7 @@ public string ToUriComponent()
116128
}
117129

118130
count++;
131+
i++;
119132
}
120133
}
121134

@@ -146,6 +159,7 @@ public string ToUriComponent()
146159
}
147160
}
148161

162+
149163
/// <summary>
150164
/// Returns an PathString given the path as it is escaped in the URI format. The string MUST NOT contain any
151165
/// value that is not a path.
@@ -279,7 +293,7 @@ public bool StartsWithSegments(PathString other, StringComparison comparisonType
279293
}
280294

281295
/// <summary>
282-
/// Adds two PathString instances into a combined PathString value.
296+
/// Adds two PathString instances into a combined PathString value.
283297
/// </summary>
284298
/// <returns>The combined PathString value</returns>
285299
public PathString Add(PathString other)
@@ -297,7 +311,7 @@ public PathString Add(PathString other)
297311
}
298312

299313
/// <summary>
300-
/// Combines a PathString and QueryString into the joined URI formatted string value.
314+
/// Combines a PathString and QueryString into the joined URI formatted string value.
301315
/// </summary>
302316
/// <returns>The joined URI formatted string value</returns>
303317
public string Add(QueryString other)

test/Microsoft.AspNetCore.Http.Abstractions.Tests/PathStringTests.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,10 @@ public void StartsWithSegmentsWithRemainder_DoesMatchUsingSpecifiedComparison(st
195195
[InlineData("pct-encoding", "/单行道", "/%E5%8D%95%E8%A1%8C%E9%81%93")]
196196
[InlineData("mixed1", "/index/单行道=(x*y)[abc]", "/index/%E5%8D%95%E8%A1%8C%E9%81%93=(x*y)%5Babc%5D")]
197197
[InlineData("mixed2", "/index/单行道=(x*y)[abc]_", "/index/%E5%8D%95%E8%A1%8C%E9%81%93=(x*y)%5Babc%5D_")]
198+
[InlineData("encoded", "/http%3a%2f%2f[foo]%3A5000/", "/http%3a%2f%2f%5Bfoo%5D%3A5000/")]
199+
[InlineData("encoded", "/http%3a%2f%2f[foo]%3A5000/%", "/http%3a%2f%2f%5Bfoo%5D%3A5000/%25")]
200+
[InlineData("encoded", "/http%3a%2f%2f[foo]%3A5000/%2", "/http%3a%2f%2f%5Bfoo%5D%3A5000/%252")]
201+
[InlineData("encoded", "/http%3a%2f%2f[foo]%3A5000/%2F", "/http%3a%2f%2f%5Bfoo%5D%3A5000/%2F")]
198202
public void ToUriComponentEscapeCorrectly(string category, string input, string expected)
199203
{
200204
var path = new PathString(input);

0 commit comments

Comments
 (0)