Skip to content

Commit

Permalink
fix: special regex characters were not escaped properly when derived …
Browse files Browse the repository at this point in the history
…a regex from a pattern with wildcard.
  • Loading branch information
skwasjer committed Sep 5, 2024
1 parent d84742e commit d68c901
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 6 deletions.
10 changes: 5 additions & 5 deletions src/MockHttp/Matchers/Patterns/RegexPatternMatcher.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ namespace MockHttp.Matchers.Patterns;

internal class RegexPatternMatcher : PatternMatcher
{
private readonly Regex _regex;

public RegexPatternMatcher
(
#if NET7_0_OR_GREATER
Expand All @@ -20,18 +18,20 @@ string regex

public RegexPatternMatcher(Regex regex)
{
_regex = regex ?? throw new ArgumentNullException(nameof(regex));
Regex = regex ?? throw new ArgumentNullException(nameof(regex));
}

internal Regex Regex { get; }

/// <inheritdoc />
public override bool IsMatch(string value)
{
return _regex.IsMatch(value);
return Regex.IsMatch(value);
}

/// <inheritdoc />
public override string ToString()
{
return _regex.ToString();
return Regex.ToString();
}
}
20 changes: 19 additions & 1 deletion src/MockHttp/Matchers/Patterns/WildcardPatternMatcher.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ namespace MockHttp.Matchers.Patterns;

internal sealed class WildcardPatternMatcher : RegexPatternMatcher
{
private static readonly char[] SpecialRegexChars = ['.', '+', '*', '?', '^', '$', '(', ')', '[', ']', '{', '}', '|', '\\'];

private readonly string _pattern;

public WildcardPatternMatcher(string pattern)
Expand Down Expand Up @@ -47,12 +49,28 @@ private static string GetMatchPattern(string pattern)
IEnumerable<string> matchGroups = pattern
.Split('*')
.Where(s => !string.IsNullOrEmpty(s))
.Select(s => $"({s})");
.Select(s => $"({RegexUriEscape(s)})");

sb.Append(string.Join(".+", matchGroups));

sb.Append(endsWithWildcard ? ".*" : "$");

return sb.ToString();
}

private static string RegexUriEscape(string s)
{
var sb = new StringBuilder();
foreach (char ch in s)
{
if (SpecialRegexChars.Contains(ch))
{
sb.Append('\\');
}

sb.Append(ch);
}

return sb.ToString();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
namespace MockHttp.Matchers.Patterns;

public sealed class WildcardPatternMatcherTests
{
[Theory]
[InlineData("test", "^(test)$")]
[InlineData("test*", "^(test).*")]
[InlineData("*test", ".*(test)$")]
[InlineData("*test*", ".*(test).*")]
[InlineData("*test1*test2*", ".*(test1).+(test2).*")]
[InlineData("/path?*", "^(/path\\?).*")]
[InlineData("/path/file.jpg?q=*&p=1&m=[a,b]", "^(/path/file\\.jpg\\?q=).+(&p=1&m=\\[a,b\\])$")]
[InlineData(".+?^$()[]{}|\\", "^(\\.\\+\\?\\^\\$\\(\\)\\[\\]\\{\\}\\|\\\\)$")]
public void When_creating_matcher_it_should_generate_expected_regex(string wildcardPattern, string expectedRegex)
{
var sut = new WildcardPatternMatcher(wildcardPattern);
sut.Regex.ToString().Should().Be(expectedRegex);
}

[Theory]
[InlineData("test", "test", true)]
[InlineData("test", "testing", false)]
[InlineData("test*", "test", true)]
[InlineData("test*", "testing", true)]
[InlineData("test*", "stress testing", false)]
[InlineData("*test", "test", true)]
[InlineData("*test", "testing", false)]
[InlineData("*test", "stress test", true)]
[InlineData("*test*", "test", true)]
[InlineData("*test*", "testing", true)]
[InlineData("*test*", "stress testing", true)]
[InlineData("*test*", "tes", false)]
[InlineData("*test1*test2*", "test1 test2", true)]
[InlineData("*test1*test2*", "test0 test1 test2 test3", true)]
[InlineData("*test1*test2*", "test test2", false)]
[InlineData("/path?q=*", "/path?q=1", true)]
[InlineData("/path?q=*", "/path?v=1&q=1", false)]
[InlineData("/path/file.jpg?q=*&p=1&m=[a,b]", "/path/file.jpg?q=search%20term&p=1&m=[a,b]", true)]
[InlineData("/path/file.jpg?q=*&p=1&m=[a,b]", "/path/file.jpg?q=search%20term&p=1&m=(a,b)", false)]
[InlineData("/path/file.jpg?q=*&p=*&m=*", "/path/file.jpg?q=search%20term&p=1&m=[a,b]", true)]
public void Given_that_value_matches_pattern_when_matching_it_should_pass(string wildcardPattern, string value, bool expected)
{
var sut = new WildcardPatternMatcher(wildcardPattern);
sut.IsMatch(value).Should().Be(expected);
}
}

0 comments on commit d68c901

Please sign in to comment.