5

I have ASP.NET MVC webpage where I use DataAnnotation to validate forms at client side. One of the view classes have a property that looks like this :

[StringLength(100, MinimumLength = 3, ErrorMessage = "Länken måste vara mellan 3 och 100 tecken lång")]
[Display(Name = "Länk")]
[RegularExpression(@"^(http(s)?://([\w-]+.)+[\w-]+(/[\w- ./?%&=])?)?$", ErrorMessage="Länkgen är inte giltlig")]
        public string Url { get; set; }

In the view I use this code for the propertie :

@Html.LabelFor(c => c.Url, true)
@Html.TextBoxFor(c => c.Url, new { @class = "tb1", @Style = "width:400px;" })
@Html.ValidationMessageFor(model => model.Url)

When pasting in a URL like this :

http://95rockfm.com/best-voicemail-giving-play-by-play-of-car-accident/

The webpage will lockup and I can´t do anything on the wepage. If I however paste this in :

http://95rockfm.com/best-voicemail-giving-play-by-play-of-car-accident

It works just fine.

These javascript file is included at the bottom of the webpage :

<script type="text/javascript" src="/Scripts/jquery.qtip.min.js"></script>
<script src="/Scripts/jquery-1.7.1.min.js"></script>
<script src="/Scripts/jquery-ui-1.8.20.min.js"></script>
<script src="/Scripts/jquery.validate.min.js"></script>
<script src="/Scripts/jquery.validate.unobtrusive.min.js"></script>

The exact same problem accures both in IE and Chrome. IE will however came back and say that a script took to long and a button to stop the script. But when switching input control the script will run again and look the webpage.

Im not using any custom stuff so why do I get this?

Banshee
  • 15,376
  • 38
  • 128
  • 219
  • 3
    This phenomenon called [Catastrophic Backtracking](http://www.regular-expressions.info/catastrophic.html). I cannot fix your regexp (I'm not good with them) to avoid this error but there are a lot of similar question on SO: http://stackoverflow.com/questions/14723667/javascript-hang-when-matching-regular-expression-using-ie-chrome http://stackoverflow.com/questions/17116675/why-does-this-regex-make-chrome-hang http://stackoverflow.com/questions/2407870/javascript-regex-hangs-using-v8 Another article: http://davetayls.me/blog/2012/10/11/its-a-regexp-catastrophe/ – nemesv Sep 22 '13 at 19:23

2 Answers2

5

. in regular expressions matches any character (and, in fact, this period is what matches the slash after the domain in your URLs). You need to escape it or put it in a character class, to match a period. Like so:

@"^(http(s)?://([\w-]+\.)+[\w-]+(/[\w- ./?%&=])?)?$"

or so:

@"^(http(s)?://([\w-]+[.])+[\w-]+(/[\w- ./?%&=])?)?$"

If you don't do that, and the pattern cannot find a match, you have a nested repetition, with an exponential amount of possible combinations. As nemesv linked you in a comment, this leads to catastrophic backtracking. However, if you are matching a literal period inside the group, then each repetition of the entire group has to end with a period, and hence there is no exponential amount of combinations.

To see what "exponential amount of combinations" means, I'll just link to two former answers of mine (one from today, actually):

One more thing though, why your pattern fails (catastrophic backtracking is mostly a problem for failing matches): you require only a single character after the first slash. You probably wanted to allow an arbitrarily long path and query string, so add a + to that character class:

@"^(http(s)?://([\w-]+[.])+[\w-]+(/[\w- ./?%&=]+)?)?$"

However, in general, why reinvent the wheel instead of just googling for established URL regex patterns.

Community
  • 1
  • 1
Martin Ender
  • 43,427
  • 11
  • 90
  • 130
2

MVC already has URL validation using UrlAttribute:

[Url]
public string Url { get; set; }

If you are using MVC 4 it will also create an HTML 5 <input type="url"> element.

The client side validation will use jQuery Validation's URL rule, which is still a regex, but a much better one (for example, it supports more Unicode characters).

Kobi
  • 135,331
  • 41
  • 252
  • 292