Endless Regular Expressions
Regular expressions are an extremely useful tool for processing text. But since a regular expression is a small program that is interpreted or compiled, it requires the same care as other parts of your code. If you're a careful coder, you won't write code that executes endlessly. Neither should you write regular expressions that execute endlessly.
You should avoid the commonly used regular expression operators * and + (which match zero-or-more and one-or-more items respectively). Replace these with length-constrained versions {0, n} and {1, n} where n is some value that is as small as possible while still being large enough for your specific use.
We could say that it's negligent to use * or + in code that operates on untrusted text and leave other uses of * and + to your own good judgement, but that's too complicated for me, so I'll say:
Never use * or +. Replace with length-constrained versions {0, n} and {1, n}.
However, using length-constrained operators is not the only thing to consider when protecting yourself from regular expression denial-of-service (ReDoS) attacks because you can still write expressions that take exponential time even with constrained lengths.
The behavior described in the ReDoS article doesn't just apply when there are malicious actors or when the regular expression is being supplied by a user. For a real-life example of a regular expression performance problem found in normal conditions see Carpe Aqua.
If your regular expression locks up your machine or your regular expression never stops executing or runs endlessly, you can use your understanding of what can cause exponential running time to correct your regex to avoid the bug. Length constraints may help all by themselves if you can create them with n <= 5, but you may also need to adjust the expression.
The workaround used in the Carpe Aqua post is not the right solution to the problem. The regex causing the problem needs to be fixed. The parentheses matching shows classic hallmarks of being an "evil regex" subexpression and there isn't a length constraint that can be applied to the existing expression that will have a small enough value for n such that exponential behavior will cease being a problem. The approach to matching parentheses needs to be removed or replaced. In .NET code a better solution would be to use balancing groups.