1+ // Copyright (c) .NET Foundation. All rights reserved.
2+ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3+
4+ using System ;
5+ using System . Text . RegularExpressions ;
6+
7+ namespace NuGetGallery
8+ {
9+ public static class RegexEx
10+ {
11+ // This timeout must be short enough to prevent runaway regular expressions,
12+ // but long enough to prevent reliability issues across all our regular expressions.
13+ private static readonly TimeSpan Timeout = TimeSpan . FromSeconds ( 15 ) ;
14+
15+ /// <summary>
16+ /// Creates a new instance of the <see cref="Regex"/> class with a default timeout configured
17+ /// for the pattern matching method to attempt a match.
18+ /// </summary>
19+ /// <param name="pattern">The regular expression pattern to match.</param>
20+ /// <param name="options">A bitwise combiantion of the enumeration values that modify the expression.</param>
21+ /// <returns>A regular expression instance that can be used to match inputs.</returns>
22+ public static Regex CreateWithTimeout ( string pattern , RegexOptions options )
23+ {
24+ return new Regex ( pattern , options , Timeout ) ;
25+ }
26+
27+ /// <summary>
28+ /// In a specific input string, replaces all substrings that match a specified regular expression.
29+ /// Throws a <see cref="RegexMatchTimeoutException"/> if the timeout is reached.
30+ /// </summary>
31+ /// <param name="input">The string to search for matches.</param>
32+ /// <param name="pattern">The regular expression pattern to match.</param>
33+ /// <param name="evaluator">The handler to replace matches.</param>
34+ /// <param name="options">A bitwise combination that provide options for matching.</param>
35+ /// <returns>A new string with the matches replaced.</returns>
36+ /// <exception cref="RegexMatchTimeoutException">Thrown if the matches exceed the default timeout.</exception>
37+ public static string ReplaceWithTimeout (
38+ string input ,
39+ string pattern ,
40+ string replacement ,
41+ RegexOptions options )
42+ {
43+ return Regex . Replace ( input , pattern , replacement , options , Timeout ) ;
44+ }
45+
46+ /// <summary>
47+ /// In a specific input string, replaces all substrings that match a specified regular expression.
48+ /// </summary>
49+ /// <param name="input">The string to search for matches.</param>
50+ /// <param name="pattern">The regular expression pattern to match.</param>
51+ /// <param name="evaluator">The handler to replace matches.</param>
52+ /// <param name="options">A bitwise combination that provide options for matching.</param>
53+ /// <returns>A new string with the matches replaced, or the original string if the matches timeout.</returns>
54+ public static string ReplaceWithTimeoutOrOriginal (
55+ string input ,
56+ string pattern ,
57+ MatchEvaluator evaluator ,
58+ RegexOptions options )
59+ {
60+ try
61+ {
62+ return Regex . Replace ( input , pattern , evaluator , options , Timeout ) ;
63+ }
64+ catch ( RegexMatchTimeoutException )
65+ {
66+ return input ;
67+ }
68+ }
69+
70+ /// <summary>
71+ /// Searches the input string for the first occurrence of the specified regular expression,
72+ /// using the specified matching options and the default time-out interval.
73+ /// </summary>
74+ /// <param name="input">The string to search for a match.</param>
75+ /// <param name="pattern">The regular expression pattern to match.</param>
76+ /// <param name="options">A bitwise combination of the enumeration values that provide options for matching.</param>
77+ /// <returns>An object that contains information about the match, or <c>null</c> if and only if the match timed out.</returns>
78+ public static Match MatchWithTimeoutOrNull (
79+ string input ,
80+ string pattern ,
81+ RegexOptions options )
82+ {
83+ try
84+ {
85+ return Regex . Match ( input , pattern , options , Timeout ) ;
86+ }
87+ catch ( RegexMatchTimeoutException )
88+ {
89+ return null ;
90+ }
91+ }
92+
93+ /// <summary>
94+ /// Searches the input string for all occurrence of the specified regular expression,
95+ /// using the specified matching options and the default time-out interval.
96+ /// </summary>
97+ /// <param name="input">The string to search for a match.</param>
98+ /// <param name="pattern">The regular expression pattern to match.</param>
99+ /// <param name="options">A bitwise combination of the enumeration values that provide options for matching.</param>
100+ /// <returns>
101+ /// A collection of the matches found by the search.
102+ /// If no matches are found, the method returns an empty collection.
103+ /// If and only if the matches timeout, returns <c>null</c>.</returns>
104+ public static MatchCollection MatchesWithTimeoutOrNull (
105+ string input ,
106+ string pattern ,
107+ RegexOptions options )
108+ {
109+ try
110+ {
111+ return Regex . Matches ( input , pattern , options , Timeout ) ;
112+ }
113+ catch ( RegexMatchTimeoutException )
114+ {
115+ return null ;
116+ }
117+ }
118+ }
119+ }
0 commit comments