<!-- mobian-agent-page publisher="dailydev" canonical="https://daily.dev/posts/the-regex-that-froze-a-shipped-app-for-two-minutes-wtsmla40m" -->

---
title: The regex that froze a shipped app for two minutes
description: A real-world case study of a ReDoS (Regular Expression Denial of Service) bug in a shipped Dart app, where a URL-validation regex with nested quantifiers...
canonical: https://daily.dev/posts/the-regex-that-froze-a-shipped-app-for-two-minutes-wtsmla40m
twitter:card: summary_large_image
twitter:site: @dailydotdev
og:type: website
og:site_name: daily.dev
og:title: The regex that froze a shipped app for two minutes | daily.dev
og:description: A real-world case study of a ReDoS (Regular Expression Denial of Service) bug in a shipped Dart app, where a URL-validation regex with nested quantifiers...
og:url: https://daily.dev/posts/the-regex-that-froze-a-shipped-app-for-two-minutes-wtsmla40m
og:image: https://api.daily.dev/og/posts/WTsMLa40M.png
og:image:alt: The regex that froze a shipped app for two minutes
og:image:width: 1200
og:image:height: 630
og:locale: en
---

> ## Documentation Index
> Fetch the complete documentation index at: https://daily.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# The regex that froze a shipped app for two minutes

**[Medium](https://daily.dev/sources/medium_js)** · 4 min read · 0 upvotes · 0 comments

## Summary

A real-world case study of a ReDoS (Regular Expression Denial of Service) bug in a shipped Dart app, where a URL-validation regex with nested quantifiers caused a two-minute freeze. The post explains why backtracking regex engines exhibit exponential worst-case behavior, demonstrates the performance cliff with benchmarks (28 chars = 2.7s, 30 chars = 11s), and proposes using Google's RE2 library via the Dart `re2` package as a linear-time alternative. RE2 matches a million characters in ~3ms versus 11 seconds for 30 characters with the built-in engine. The recommendation is to use RE2 specifically at trust boundaries where pattern or input is not fully controlled.

## Full article

daily.dev links to this article rather than hosting it. Read it at the original source: <https://medium.com/@developeryusufihsan/the-regex-that-froze-a-shipped-app-for-two-minutes-cf980f30e174>

## Questions this post answers

### Why does a regex like (a+)+$ freeze my app when matching certain strings?

Nested quantifiers, one repetition inside another, cause backtracking regex engines to explore an exponential number of paths when a string almost but doesn't quite match. In Dart, matching (a+)+$ against a string of 28 a's followed by a b takes about 2.7 seconds; at 30 characters it takes 11 seconds, since each two-character increase roughly quadruples the time. This is a ReDoS, a regular-expression denial of service, and it affects backtracking engines like those in JavaScript, Python, and Java too.

_daily.dev surfaces practical writeups like this for developers hardening input validation against ReDoS._

### How can I avoid catastrophic backtracking in regex without rewriting every pattern?

Run the match on a linear-time engine like Google's RE2 instead of a backtracking engine. RE2 compiles patterns to a finite automaton and matches in time linear to input length, guaranteeing no exponential blowup, at the cost of dropping backreferences and lookaround support. For Dart, the re2 package binds RE2 via dart:ffi; it matched a million-character adversarial string in about 2.9 ms versus 11 seconds for just 30 characters with the built-in RegExp.

_Developers weighing regex engines for untrusted input can track approaches like RE2 through daily.dev._

### Where should I use RE2 instead of the built-in regex engine in my application?

Use RE2 or another linear-time engine specifically at trust boundaries: validating a URL, email, or identifier from the network, applying a redaction or filter rule configured by someone else, or scanning a log line an attacker can influence. For patterns and input you fully control, the built-in backtracking RegExp is faster to reach for and supports backreferences that RE2 lacks.

_daily.dev helps developers compare tooling tradeoffs like RE2 versus backtracking regex before shipping._

## Similar posts on daily.dev

- [Regex Are Not the Problem. Strings Are.](https://daily.dev/posts/regex-are-not-the-problem-strings-are--lvxxdmy46) · ITNEXT · 0 upvotes · 0 comments
- [finding all regex matches has always been O\(n²\). even in the engines built to prevent it](https://daily.dev/posts/finding-all-regex-matches-has-always-been-o-n-even-in-the-engines-built-to-prevent-it-6av6qyuxr) · Hacker News · 4 upvotes · 0 comments
- [CVE-2026-67987 \(ruby\_llm\): Polynomial-Time Regular Expression Denial of Service \(ReDoS\) vulnerability](https://daily.dev/posts/cve-2026-67987-ruby-llm-polynomial-time-regular-expression-denial-of-service-redos-vulnerabilit-jhkapfn4u) · RUBYLAND · 0 upvotes · 0 comments
- [what 262,715 regex questions on stack overflow haven't answered](https://daily.dev/posts/what-262-715-regex-questions-on-stack-overflow-haven-t-answered-p5elhkiyv) · Lobsters · 4 upvotes · 0 comments
- [CVE-2026-45756: JsonPath Evaluates Attacker-Controlled Regular Expressions in match\(\)/search\(\) Without Limits: ReDoS \(Symfony Blog\)](https://daily.dev/posts/cve-2026-45756-jsonpath-evaluates-attacker-controlled-regular-expressions-in-match-search-witho-orpmyxxfl) · Symfony · 0 upvotes · 0 comments

---

Tags: [#security](https://daily.dev/tags/security), [#dart](https://daily.dev/tags/dart)

[View this post on daily.dev](https://daily.dev/posts/the-regex-that-froze-a-shipped-app-for-two-minutes-wtsmla40m)

```json
{"@context":"https://schema.org","@graph":[{"@type":"Organization","@id":"https://daily.dev/#organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180},"sameAs":["https://twitter.com/dailydotdev","https://github.com/dailydotdev","https://www.linkedin.com/company/daily-dev-ltd"]},{"@type":"WebSite","@id":"https://daily.dev/#website","url":"https://daily.dev","name":"daily.dev","publisher":{"@id":"https://daily.dev/#organization"},"potentialAction":{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https://daily.dev/search?q={search_term_string}"},"query-input":"required name=search_term_string"}}]}
{"@context":"https://schema.org","@type":"TechArticle","headline":"The regex that froze a shipped app for two minutes","url":"https://daily.dev/posts/the-regex-that-froze-a-shipped-app-for-two-minutes-wtsmla40m","mainEntityOfPage":{"@type":"WebPage","@id":"https://daily.dev/posts/the-regex-that-froze-a-shipped-app-for-two-minutes-wtsmla40m"},"datePublished":"2026-07-22T21:09:30.291Z","dateModified":"2026-09-13T18:27:46.589Z","description":"A real-world case study of a ReDoS (Regular Expression Denial of Service) bug in a shipped Dart app, where a URL-validation regex with nested quantifiers...","image":"https://media.daily.dev/image/upload/f_auto,q_auto/v1/posts/d6ab0a9a223ee01bc82d647f54feb2d2?_a=AQAEuop","thumbnailUrl":"https://media.daily.dev/image/upload/f_auto,q_auto/v1/posts/d6ab0a9a223ee01bc82d647f54feb2d2?_a=AQAEuop","isAccessibleForFree":true,"articleSection":"Medium","inLanguage":"en","publisher":{"@type":"Organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180}},"author":{"@type":"Organization","name":"Medium","logo":"https://media.daily.dev/image/upload/t_logo,f_auto/v1/logos/medium","url":"https://daily.dev/sources/medium_js"},"commentCount":0,"discussionUrl":"https://daily.dev/posts/the-regex-that-froze-a-shipped-app-for-two-minutes-wtsmla40m","interactionStatistic":[{"@type":"InteractionCounter","interactionType":{"@type":"LikeAction"},"userInteractionCount":0},{"@type":"InteractionCounter","interactionType":{"@type":"CommentAction"},"userInteractionCount":0}],"keywords":"security,dart","timeRequired":"PT4M"}
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://daily.dev"},{"@type":"ListItem","position":2,"name":"Medium","item":"https://daily.dev/sources/medium_js"},{"@type":"ListItem","position":3,"name":"The regex that froze a shipped app for two minutes"}]}
{"@context":"https://schema.org","@type":"FAQPage","@id":"https://daily.dev/posts/the-regex-that-froze-a-shipped-app-for-two-minutes-wtsmla40m#faq","mainEntity":[{"@type":"Question","name":"Why does a regex like (a+)+$ freeze my app when matching certain strings?","acceptedAnswer":{"@type":"Answer","text":"Nested quantifiers, one repetition inside another, cause backtracking regex engines to explore an exponential number of paths when a string almost but doesn't quite match. In Dart, matching (a+)+$ against a string of 28 a's followed by a b takes about 2.7 seconds; at 30 characters it takes 11 seconds, since each two-character increase roughly quadruples the time. This is a ReDoS, a regular-expression denial of service, and it affects backtracking engines like those in JavaScript, Python, and Java too. daily.dev surfaces practical writeups like this for developers hardening input validation against ReDoS."}},{"@type":"Question","name":"How can I avoid catastrophic backtracking in regex without rewriting every pattern?","acceptedAnswer":{"@type":"Answer","text":"Run the match on a linear-time engine like Google's RE2 instead of a backtracking engine. RE2 compiles patterns to a finite automaton and matches in time linear to input length, guaranteeing no exponential blowup, at the cost of dropping backreferences and lookaround support. For Dart, the re2 package binds RE2 via dart:ffi; it matched a million-character adversarial string in about 2.9 ms versus 11 seconds for just 30 characters with the built-in RegExp. Developers weighing regex engines for untrusted input can track approaches like RE2 through daily.dev."}},{"@type":"Question","name":"Where should I use RE2 instead of the built-in regex engine in my application?","acceptedAnswer":{"@type":"Answer","text":"Use RE2 or another linear-time engine specifically at trust boundaries: validating a URL, email, or identifier from the network, applying a redaction or filter rule configured by someone else, or scanning a log line an attacker can influence. For patterns and input you fully control, the built-in backtracking RegExp is faster to reach for and supports backreferences that RE2 lacks. daily.dev helps developers compare tooling tradeoffs like RE2 versus backtracking regex before shipping."}}]}
```

