# Deep static analysis

Deep static analysis decides a property of the program by building a
model of it first. The model is usually how values move between
procedures; for a regular expression it is the automaton a backtracking
engine would run. Either way the finding is high-confidence rather than
a proof.

Security is the usual target and not the only one: the same dataflow
model finds unsafe API patterns and ordinary correctness defects.
[Taint analysis](https://quality.stereobooster.com/taint-analysis.md) is one property expressed
over this model — untrusted input reaching a dangerous sink — and it has
two ways of being checked, statically over the model or dynamically at
runtime.

## What it catches

- **Cross-module dataflow bugs.** A tainted source reaching a distant
  sink, or an unsafe API pattern spanning files: findings a per-file
  linter structurally cannot reach.
- **Catastrophic-backtracking regexes (ReDoS).** A pattern an attacker
  can drive into exponential time, turning a request into a denial of
  service.

## Approaches and tools

### Dataflow and query analysis

Query engines treat the codebase as a database and dataflow analyzers
follow values across calls.

- **[CodeQL](https://codeql.github.com)** (free for OSS) — query-based deep security and
  quality analysis; supports C/C++, C#, Go, Java/Kotlin,
  JavaScript/TypeScript, Python, Ruby, and Swift.
- **[Semgrep](https://semgrep.dev/)** — pattern-based rules across 30+ languages;
  quick to write a rule per bug class your team keeps hitting.

### Regular-expression denial of service (ReDoS)

A backtracking pattern like `(a+)+$` runs in exponential time on a
crafted input. A backtracking engine builds a non-deterministic finite
automaton from the pattern and simulates it (Davis et al. 2018)[^davis2018], and the
blow-up comes from *ambiguous states* — two paths reaching the same
state, so the engine explores what follows twice. Analyzing that
automaton finds the ambiguity; the older `safe-regex` star-height
heuristic only approximates it. Other algorithmic-complexity blow-ups
are *not* statically detectable and belong to [algorithmic complexity
testing](https://quality.stereobooster.com/algorithmic-complexity.md).

- **[recheck](https://makenowjust-labs.github.io/recheck/)** — hybrid automaton-plus-fuzzing analysis
  that returns the actual attack string, for JavaScript and TypeScript,
  wired into CI via
  **[eslint-plugin-redos](https://github.com/makenowjust-labs/eslint-plugin-redos)**.
  **[regexploit](https://github.com/doyensec/regexploit)** scans Python and other regexes.
- **[CodeQL](https://codeql.github.com)** ships `js/redos` and `js/polynomial-redos`
  queries (with Python and Java equivalents), and **[Semgrep](https://semgrep.dev/)**
  ships ReDoS rules.
- *By construction:* the blow-up is a property of the backtracking
  algorithm, not of regular expressions. An engine that simulates a
  finite automaton — **[RE2](https://github.com/google/re2)**, and the Rust `regex` and Go
  `regexp` libraries, which follow RE2's design — matches in time
  linear in the input, so catastrophic backtracking cannot occur. Such
  an engine has no backreferences, because `(.*)\1` is not a regular
  expression at all: it describes a language that is not regular, nor
  even context-free, and matching it is NP-complete (Aho 1990)[^aho1990].
  Perl-derived syntax kept the name while describing a strictly larger
  class of patterns. Where the patterns are genuinely regular, swapping
  the engine is often a better fix than policing individual ones.
- *Escalate past the regex:* a pattern that genuinely needs
  backreferences is a grammar wearing regex syntax, and the fix is a
  parser rather than a longer pattern. Parsing expression grammars
  replace nondeterministic choice with prioritized choice, so a PEG is
  unambiguous by construction, and a linear-time parser can be built for
  any PEG by memoizing (Ford 2002, 2004)[^ford2002] [^ford2004] — more expressive than
  regular languages without the exponential. **[Rosie](https://rosie-lang.org/)**
  packages this as a regex replacement with composable, testable named
  patterns, built on **[LPeg](https://www.inf.puc-rio.br/~roberto/lpeg/)**. The guarantee is not free:
  memoization costs memory linear in the input, and PEG engines that
  skip it keep backtracking — Rosie claims linear runtime "for common
  use cases", not universally.

## When to use, when not

The [overview](https://quality.stereobooster.com/static-analysis.md) carries the shared adoption economics; at the
deep end specifically:

**Use:**

- CodeQL or Semgrep at diff time for security-sensitive code, where a
  cross-module dataflow finding is worth the extra runtime.
- ReDoS analysis on any service that compiles attacker-influenced
  regexes, or a linear-time engine to remove the risk outright.

**Don't:**

- Run the heavy engines on every keystroke; they belong at diff time or
  in CI, not inline in the editor.

## Evidence

**Dataflow and query analysis** — measured recall is low, and where the
finding is shown matters more than how precise it is.

- **Most real bugs go unreported.** Against 594 real bugs from 15 Java
  projects, Error Prone, Infer and SpotBugs together detected 27 — 4.5% —
  while emitting 5,247 warnings on the files involved (Habib and Pradel 2018)[^habib2018]. The
  detectors were largely complementary: 18 of the 27 were found by
  SpotBugs alone, so one tool is not a proxy for the class. The 4.5% is a
  lower bound: the sample contains only defects that reached version
  control, which excludes whatever a detector already stopped upstream.
- **Security recall is no better.** Six C/C++ analyzers, CodeQL among
  them, missed between 47% and 80% of the 192 real vulnerabilities in 27
  open-source projects (1.15 million lines). Combining every tool's output cut the
  miss rate to 30–69%, at the cost of flagging 15 percentage points more
  functions (Lipp et al. 2022)[^lipp2022].
- **Deployment beats precision.** Infer at Facebook reported at under 20%
  false positives and was almost entirely ignored in batch mode — a
  near-zero fix rate. The same analysis at the same false-positive rate
  reached a fix rate above 70% once reported on the diff under review
  (Distefano et al. 2019)[^distefano2019].

**ReDoS** — the vulnerable patterns are documented; the threat and the
fixes are not.

- **Vulnerable patterns are widespread.** Thousands of super-linear
  regexes were found across npm and PyPI, affecting more than 10,000
  modules (Davis et al. 2018)[^davis2018].
- **Automaton analysis over anti-pattern heuristics.** The conventional
  anti-pattern heuristics had few false negatives but many false
  positives, making them necessary but not sufficient signals of
  super-linear behavior (Davis et al. 2018)[^davis2018]. That is the empirical case for
  preferring an automaton-based analyzer to `safe-regex`.
- **Real-world impact is unestablished.** A 2025 systematization found
  that almost no study evaluates whether ReDoS weaknesses can actually be
  weaponized against real systems, and that mainstream engines have since
  added partial or full defenses that render many published threat models
  obsolete (Bhuiyan et al. 2025)[^bhuiyan2025]. Evaluating those defenses, and supporting
  migration to them, is named as open work. Swapping to a linear-time
  engine therefore rests on the construction argument, not on measured
  outcomes.
- **Backreferences fall outside the detectors.** The automaton models the
  current detectors are built on do not cover backreferences. A preprint
  reports 45 previously unknown quadratic-or-worse vulnerabilities in the
  Snort ruleset in exactly the regime where existing detectors report
  nothing (Liu et al. 2026)[^liu2026].
- **Developers do not reach for the parser.** Shown all three repair
  strategies for a super-linear regex, developers favored revising the
  regex over truncating the input or writing a custom parser
  (Davis et al. 2018)[^davis2018].

## Classification

- **Quality dimensions:** Security, Functionality, Reliability.
- **Area:** Semantic analysis over a model of the program: cross-language query and dataflow engines, and automaton analysis of regular expressions.
- **Guarantee:** Empirical.

## Referenced by

- [Quality dimensions](https://quality.stereobooster.com/quality-dimensions.md) · Quality dimensions
- [Security](https://quality.stereobooster.com/security.md) · Quality dimensions
- [Algorithmic complexity testing](https://quality.stereobooster.com/algorithmic-complexity.md) · Methods
- [Linters](https://quality.stereobooster.com/linters.md) · Methods
- [Static analysis](https://quality.stereobooster.com/static-analysis.md) · Methods
- [ESLint](https://quality.stereobooster.com/eslint.md) · Recipes

## References

[^davis2018]: Davis, James C., Christy A. Coghlan, Francisco Servant, and Dongyoon Lee. 2018. "[The Impact of Regular Expression Denial of Service (ReDoS) in Practice: An Empirical Study at the Ecosystem Scale](https://davisjam.github.io/files/publications/DavisCoghlanServantLee-EcosystemREDOS-ESECFSE18.pdf)." *Proceedings of the 2018 26th ACM Joint Meeting on European Software Engineering Conference and Symposium on the Foundations of Software Engineering (ESEC/FSE 2018)*, 246–56. <https://doi.org/10.1145/3236024.3236027>.
[^aho1990]: Aho, Alfred V. 1990. "[Algorithms for Finding Patterns in Strings](https://doi.org/10.1016/B978-0-444-88071-0.50010-2)." In *Handbook of Theoretical Computer Science, Volume a: Algorithms and Complexity*, edited by Jan van Leeuwen. Elsevier. <https://doi.org/10.1016/B978-0-444-88071-0.50010-2>.
[^ford2002]: Ford, Bryan. 2002. "[Packrat Parsing: Simple, Powerful, Lazy, Linear Time](https://bford.info/pub/lang/packrat-icfp02.pdf)." *Proceedings of the Seventh ACM SIGPLAN International Conference on Functional Programming (ICFP '02)*, 36–47. <https://doi.org/10.1145/581478.581483>.
[^ford2004]: Ford, Bryan. 2004. "[Parsing Expression Grammars: A Recognition-Based Syntactic Foundation](https://bford.info/pub/lang/peg.pdf)." *Proceedings of the 31st ACM SIGPLAN-SIGACT Symposium on Principles of Programming Languages (POPL '04)*, 111–22. <https://doi.org/10.1145/964001.964011>.
[^habib2018]: Habib, Andrew, and Michael Pradel. 2018. "[How Many of All Bugs Do We Find? A Study of Static Bug Detectors](https://software-lab.org/publications/ase2018_static_bug_detectors_study.pdf)." *Proceedings of the 33rd ACM/IEEE International Conference on Automated Software Engineering (ASE '18)*, 317–28. <https://doi.org/10.1145/3238147.3238213>.
[^lipp2022]: Lipp, Stephan, Sebastian Banescu, and Alexander Pretschner. 2022. "[An Empirical Study on the Effectiveness of Static C Code Analyzers for Vulnerability Detection](https://mediatum.ub.tum.de/doc/1659728/1659728.pdf)." *Proceedings of the 31st ACM SIGSOFT International Symposium on Software Testing and Analysis (ISSTA 2022)*, 544–55. <https://doi.org/10.1145/3533767.3534380>.
[^distefano2019]: Distefano, Dino, Manuel Fähndrich, Francesco Logozzo, and Peter W. O'Hearn. 2019. "[Scaling Static Analyses at Facebook](https://cseweb.ucsd.edu/~dstefan/cse227-spring20/papers/distefano:scaling.pdf)." *Communications of the ACM* 62 (8): 62–70. <https://doi.org/10.1145/3338112>.
[^bhuiyan2025]: Bhuiyan, Masudul Hasan Masud, Berk Çakar, Ethan H. Burmane, James C. Davis, and Cristian-Alexandru Staicu. 2025. "[SoK: A Literature and Engineering Review of Regular Expression Denial of Service (ReDoS)](https://arxiv.org/pdf/2406.11618)." *Proceedings of the 20th ACM Asia Conference on Computer and Communications Security (ASIA CCS '25)*, 1659–75. <https://doi.org/10.1145/3708821.3733912>.
[^liu2026]: Liu, Yichen, Berk Çakar, Aman Agrawal, Minseok Seo, James C. Davis, and Dongyoon Lee. 2026. *[Regular Expression Denial of Service Induced by Backreferences](https://arxiv.org/pdf/2602.21459)*. <https://doi.org/10.48550/arXiv.2602.21459>.

## Acronyms

- CCS — Calculus of Communicating Systems
- OSS — open-source software
- PEG — parsing expression grammar
