← Home ← Codex ← DEBT ← Engine
Browse by Category
+ added · updated 7d
← Back to glossary

Atomic Groups

Regex PHP 4.0+ Advanced
debt(d6/e3/b3/t7)
d6 Detectability Operational debt — how invisible misuse is to your safety net

Closest to 'specialist tool catches' (d5), bumped +1 because while redos-detector/recheck/semgrep can flag catastrophic backtracking patterns, detecting semantic differences from misplaced atomic groups typically escapes standard scanners and only surfaces under targeted ReDoS testing or careful review.

e3 Effort Remediation debt — work required to fix once spotted

Closest to 'simple parameterised fix' (e3), per quick_fix: wrap the offending greedy subpattern in (?>...). It's more than a one-line swap because you must identify the correct subexpression and verify semantics didn't change, but it stays localized to the regex string.

b3 Burden Structural debt — long-term weight of choosing wrong

Closest to 'localised tax' (b3), the atomic group lives inside a single regex pattern in one component; it doesn't propagate architectural weight across the codebase even though applies_to spans multiple contexts.

t7 Trap Cognitive debt — how counter-intuitive correct behaviour is

Closest to 'serious trap' (t7), grounded in misconception: developers assume (?>...) is purely a performance tweak like (?:...) but it changes match semantics by discarding backtrack positions, causing legitimate matches to fail — this contradicts the intuition built from non-capturing groups.

About DEBT scoring →

Also Known As

atomic group possessive group non-backtracking group (?>...)

TL;DR

Non-capturing groups written (?>...) that prevent backtracking once matched, locking in progress to avoid catastrophic slowdown.

Explanation

An atomic group (?>...) matches like a non-capturing group but throws away all backtracking positions inside the group once it has matched successfully. This means the regex engine will not re-enter the group to try alternative matches, even if the overall pattern later fails. Atomic groups are a possessive form of grouping — the engine commits to the match and moves on. They are supported natively in PCRE (PHP), Java, .NET, Ruby, Perl, and PCRE2. JavaScript's built-in RegExp does not support them, and Python's standard `re` module does not either (the third-party `regex` module does). Atomic groups are the primary tool for defusing catastrophic backtracking in patterns that would otherwise explore exponential alternatives. A common example: matching an HTML attribute value with `(?>[^"]*)"` prevents the engine from backtracking through the character class if the closing quote is missing — instead of trying every possible split of the string, it fails fast. Atomic groups often replace possessive quantifiers (`a*+`, `a++`) since (?>a*) is equivalent to a*+ but works in engines that lack possessive support. They are also useful for optimising alternations where you know the first successful branch is the correct one and further exploration is wasted work.

Common Misconception

Atomic groups are just a performance optimisation with no semantic effect. In reality they change what the pattern matches: by discarding backtracking positions, they can cause an overall match to fail where a normal group would have succeeded by trying alternatives — the semantics differ, not just the speed.

Why It Matters

Atomic groups are one of the few tools that turn catastrophic O(2^n) backtracking into linear-time failure, directly mitigating ReDoS vulnerabilities in user-facing regex validators. Correctly placed atomic groups can make the difference between a millisecond match and a request that hangs a worker.

Common Mistakes

  • Confusing (?>...) with (?:...) — the latter is merely non-capturing, the former also disables backtracking inside.
  • Placing atomic groups around alternations where later branches were intended as fallbacks, causing legitimate matches to fail.
  • Assuming atomic groups work in every regex flavour — older JavaScript engines and Python's `re` module do not support them (Python's `regex` third-party module does).
  • Wrapping the wrong subexpression: putting (?>...) around a fixed literal has no effect because there is nothing to backtrack over.
  • Using atomic groups everywhere as a blanket optimisation instead of profiling to find the real backtracking hotspot.

Code Examples

💡 Note
Wrapping the inner `a+` in an atomic group `(?>a+)` prevents the regex engine from backtracking through previously matched characters when the outer `+` quantifier fails, changing catastrophic exponential behavior to linear time on non-matching input.
✗ Vulnerable
<?php
// Vulnerable to catastrophic backtracking on long non-matching input.
// For input like 'aaaaaaaaaaaaaaaaaaaaaaaaaaaa!' the engine tries
// every possible split of the a's before failing - exponential time.
$pattern = '/^(a+)+$/';
$input = str_repeat('a', 30) . '!';
preg_match($pattern, $input); // may hang the request
✓ Fixed
<?php
// Atomic group prevents the engine from re-splitting the a's.
// Once (?>a+) consumes as many a's as it can, it never gives any back,
// so the outer + cannot generate the exponential alternatives.
$pattern = '/^(?>a+)+$/';
$input = str_repeat('a', 30) . '!';
preg_match($pattern, $input); // fails in linear time

// Real-world: match a quoted attribute value without ReDoS risk
$attr = '/"(?>[^"\\\\]*(?:\\\\.[^"\\\\]*)*)"/';

Added 15 Jul 2026
Edited 24 Jul 2026
Views 43
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
0 pings T 0 pings F 0 pings S 0 pings S 0 pings M 0 pings T 1 ping W 1 ping T 2 pings F 2 pings S 1 ping S 5 pings M 1 ping T 0 pings W 3 pings T 0 pings F 3 pings S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 1 ping F 0 pings S 0 pings S 2 pings M 0 pings T 0 pings W 0 pings T 0 pings F
No pings yet today
No pings yesterday
Bing 6 Google 3 PetalBot 3 Applebot 2 SEMrush 2 Meta AI 2 Unknown AI 1 ChatGPT 1 Ahrefs 1 Perplexity 1
crawler 22
🧱 FUNDAMENTALS — new to this? Start with the ground floor.
Regex general A regex (regular expression) is a pattern you write to search, match, or replace text. It's like a super-powered find-and-replace that can match flexible patterns instead of exact words.

Regex turns hours of manual text hunting into a single line of code. From form validation to log parsing to data cleanup, pattern matching is everywhere in real-world programming.

💡 When a regex misbehaves, check if your special characters need escaping — dots, brackets, and slashes often do.

Ask Codex about Regex →
DEV INTEL Tools & Severity
🟡 Medium ⚙ Fix effort: Medium
⚡ Quick Fix
Wrap the greedy subpattern that causes backtracking in (?>...) so the engine commits to its match and cannot re-explore alternatives
📦 Applies To
PHP 4.0+ web cli queue-worker library
🔗 Prerequisites
🔍 Detection Hints
\((?!\?>)[^)]*[+*]\)[+*]
Auto-detectable: ✓ Yes semgrep redos-detector recheck
⚠ Related Problems
🤖 AI Agent
Confidence: Medium False Positives: High ✗ Manual fix Fix: Medium Context: Function Tests: Update
cwe-1333


✓ schema.org compliant