Can I test if a regex is valid in C# without throwing exception

Viewed 43988

I allow users to enter a regular expression to match IP addresses, for doing an IP filtration in a related system. I would like to validate if the entered regular expressions are valid as a lot of userse will mess op, with good intentions though.

I can of course do a Regex.IsMatch() inside a try/catch and see if it blows up that way, but are there any smarter ways of doing it? Speed is not an issue as such, I just prefer to avoid throwing exceptions for no reason.

9 Answers

As long as you catch very specific exceptions, just do the try/catch.

Exceptions are not evil if used correctly.

Not without a lot of work. Regex parsing can be pretty involved, and there's nothing public in the Framework to validate an expression.

System.Text.RegularExpressions.RegexNode.ScanRegex() looks to be the main function responsible for parsing an expression, but it's internal (and throws exceptions for any invalid syntax anyway). So you'd be required to reimplement the parse functionality - which would undoubtedly fail on edge cases or Framework updates.

I think just catching the ArgumentException is as good an idea as you're likely to have in this situation.

I've ever been use below function and have no problem with that. It uses exception and timeout both, but it's functional. Of course it works on .Net Framework >= 4.5.

    public static bool IsValidRegexPattern(string pattern, string testText = "", int maxSecondTimeOut = 20)
    {
        if (string.IsNullOrEmpty(pattern)) return false;
        Regex re = new Regex(pattern, RegexOptions.None, new TimeSpan(0, 0, maxSecondTimeOut));
        try { re.IsMatch(testText); }
        catch{ return false; } //ArgumentException or RegexMatchTimeoutException
        return true;
    }

A malformed regex isn't the worst of reasons for an exception.

Unless you resign to a very limited subset of regex syntax - and then write a regex (or a parser) for that - I think you have no other way of testing if it is valid but to try to build a state machine from it and make it match something.

Depending on who the target is for this, I'd be very careful. It's not hard to construct regexes that can backtrack on themselves and eat a lot of CPU and memory -- they can be an effective Denial of Service vector.

In .NET, unless you write your own regular expression parser (which I would strongly advise against), you're almost certainly going to need to wrap the creation of the new Regex object with a try/catch.

This is my solution, that outputs an enum telling whether the pattern is useable, and if yes, then return the compiled regex as an out parameter that you can use directly in your calling code. Regards.

namespace ProgrammingTools.Regex
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text.RegularExpressions;    

    public enum eValidregex { No, Yes, YesButUseCompare }

    public class RegEx_Validate
    {
        public static eValidregex IsValidRX ( string pattern , out Regex RX )
        {
            RX = null; 

            if ( pattern.Length == 0 )
                return eValidregex.No;

            List<char> c1 = new List<char>
            {
                '\\' , '.' , '(' , ')' , '{' , '}' , '^' , '$' , '+' , '*' , '?' , '[' , ']', '|'
            };

            if ( c1.Count( e => pattern.Contains( e ) ) > 0 )
            {
                TimeSpan ts_timeout = new TimeSpan(days: 0,hours: 0,minutes: 0,seconds: 1,milliseconds: 0);

                try
                {
                    RX = new Regex( pattern , RegexOptions.Compiled | RegexOptions.IgnoreCase , ts_timeout );
                    return eValidregex.Yes;
                }
                catch ( ArgumentNullException )
                {
                    return eValidregex.No;
                }
                catch ( ArgumentOutOfRangeException )
                {
                    return eValidregex.No;
                }
                catch ( ArgumentException )
                {
                    return eValidregex.No;
                }
            }
            else
            {
                return eValidregex.YesButUseCompare;
            }

        }

    }

}

By using following method you can check wether your reguler expression is valid or not. here testPattern is the pattern you have to check.

public static bool VerifyRegEx(string testPattern)
{
    bool isValid = true;
    if ((testPattern != null) && (testPattern.Trim().Length > 0))
    {
        try
        {
            Regex.Match("", testPattern);
        }
        catch (ArgumentException)
        {
            // BAD PATTERN: Syntax error
            isValid = false;
        }
    }
    else
    {
        //BAD PATTERN: Pattern is null or blank
        isValid = false;
    }
    return (isValid);
}
Related