Urgent.News

What's breaking now, across thousands of outlets.

Tech

A 28-Character String Freezes Your Regex for 3.6 Seconds

Your test suite passes, staging passes, and then one user submits a 28-character string and a Node process pins a core for 3.6 seconds. I measured this today on Node 22 (V8) with /^(a+)+$/ against an input of n letters a followed by a single X that makes the match fail: input result time 20 chars no match 8.6 ms 22 chars no match 34.2 ms 24 chars no match 136.6 ms 26 chars no match 553.7 ms 27…

A 28-character string can freeze a Node.js process for 3.6 seconds when using a specific regular expression pattern. This issue stems from catastrophic backtracking, which occurs when the regex pattern fails to match. The pattern /^(a+)+$/ attempts to match a string of 'a' characters followed by a single 'X' that causes the match to fail. The time taken by the Node process doubles with each additional character in the input string, taking roughly four hours for a 40-character input.

The problem lies in the nested quantifier (a+)+, which allows the regex engine to split the sequence of 'a' characters in every possible way, resulting in 2^(n-1) partitions for n characters. When the match fails, the engine must try all these partitions before giving up, leading to significant performance degradation. Even a seemingly simple email validator regex can exhibit the same slow behavior when appending a "!" to the pattern.

Several attempts to address this issue have proven ineffective. Setting a length limit does not help, as real-world inputs can still reach the problematic length. Specifying an upper bound in the regex pattern also fails, as the number of splits increases exponentially rather than being capped. Possessive quantifiers, which would limit the engine's ability to backtrack, are not available in JavaScript's regex engine.

The recommended solution is to rewrite the regex pattern to have a single, unambiguous way of matching. This can be achieved by using a lookahead assertion and a backreference, such as /^a+$/ which matches a string of one or more 'a' characters without the catastrophic backtracking. This revised pattern can handle even extremely long inputs (35,000 times longer) in a fraction of the time taken by the original pattern.

If rewriting the regex is not feasible, an alternative approach is to emulate an atomic group using a lookahead and a backreference, as shown in the suggested pattern. This method can provide similar performance benefits. It is also important to impose limits on input length, run untrusted patterns within a worker environment with a timeout, or consider using a linear-time regex engine like RE2, which is resistant to catastrophic backtracking.

Written by urgent.news from Dev.to's reporting — not their text. Machine-written — may contain errors; check the original before relying on it.

Read the original at dev.to →

More in Tech

Why Your Mobile App Needs a Scalable Architecture From Day One

Building a mobile app is exciting. You have an idea, a clear vision, and expectations about how users will interact with your product.

  • Scalable architecture ensures app performance with growing user base.
  • Better performance and reliability prevent user abandonment.
  • Modular components allow easy future feature expansion.

7 Patterns From 204 Muse Video Prompts Shared on X, Plus a Node.js Script to Run Them

Over the past few weeks my X feed filled up with Muse Video clips: handheld selfies, vlogs and "boyfriend POV" shorts that look like they were filmed on a phone.

  • Muse Video prompts compiled from 204 X posts, categorized into 13 types
  • Consistent character appearance achieved through reference sheet usage
  • Time-stamped scene breakdown prevents stiff loops and adds rhythm

More from Wednesday 4 November →