Skip to content

Strict tests for groovy, fix 11 real bugs (2 ReDoS) - #712

Merged
squid-protocol merged 1 commit into
mainfrom
fix/584-groovy-strict-parsing
Jul 28, 2026
Merged

squid-protocol merged 1 commit into
mainfrom
fix/584-groovy-strict-parsing

Conversation

@squid-protocol

Copy link
Copy Markdown
Owner

Closes #584. Part of epic #518.

Summary

Found and fixed 11 real bugs: dead_code missing /* */, state_mutation miscounting == as =, func_start/args never matching lowercase/void return types or multi-param generics, nested-delimiter truncation in args/decorators/generics, dependency_injection's Gradle DSL entry points never matching (trailing \b after {), closures/comprehensions missing Groovy's dominant paren-less trailing-closure idiom, synchronized blocks hallucinated as methods, a missing _dependency_capture, and 2 confirmed ReDoS findings (closures, spec_exposure).

Cross-language finding, not fixed here: the spec_exposure ReDoS pattern is copy-pasted across 28 languages, including already-closed yacc. Confirmed via direct timing (~4x/doubling, consistent across samples). Filing a dedicated sweep issue separately.

Test plan

  • 67 new tests — full strict suite 1274 passed
  • Full suite — 2197 passed
  • ruff_audit.py / mypy_audit.py / dead_key_audit.py --ci — no new findings
  • Golden crucible: zero diff, confirmed legitimate (find-verified zero real groovy files anywhere in the corpus)

Co-authored-by: Claude Sonnet 5 noreply@anthropic.com

Closes #584. Part of epic #518.

Found and fixed 11 real bugs in groovy's structural signatures:

- dead_code: only fired on `//`, never `/* */` (Rule 12 gap).
- state_mutation: bare trailing `=` matched the first `=` of `==`,
  miscounting equality checks as assignments.
- func_start/args: return-type stepper required an uppercase first char,
  so lowercase primitive/void return types (`void foo()`, `int add()`)
  never matched at all; also excluded `,`, breaking multi-param generic
  return types (`Map<String, Integer> foo()`).
- args/decorators/generics: flat negated-class delimiters truncated on
  one-level nesting (`Math.max(3,4)` default value, `@Grab(...,
  version=resolve())`, `Map<String,List<Id>>`) -- bounded one-level-nesting
  forms per Rule 11.
- dependency_injection: `plugins {`/`dependencies {` ended on `{` inside a
  shared trailing \b, which can never fire on a non-word char -- Gradle's
  two most common DSL entry points never matched.
- closures/comprehensions: required `->`/`(` respectively, so Groovy's
  dominant paren-less trailing-closure idiom (`list.each { it }`) never
  matched either signature.
- func_start/args: `synchronized(lock) { ... }` was hallucinated as a
  method declaration/parameter block; `args` had no control-flow exclusion
  at all, also hallucinating `if`/`while`/`switch`/`for`/`catch` blocks as
  parameter lists.
- _dependency_capture was entirely absent for groovy (unlike every other
  JVM-family language) -- Groovy imports never fed the dependency graph.
  Added it.
- ReDoS: closures' `[\w\s,]+` overlapping a trailing `\s*` caused a
  confirmed hang (>5s) at n=2000 on an unclosed `{` -- collapsed into one
  bounded, non-overlapping class.
- ReDoS: spec_exposure's `\d+`/`[^\]]*` overlap showed confirmed ~4x-per-
  doubling quadratic scaling -- bounded to `{0,300}`.

Adds 67 new tests (43 parametrized _GROOVY_SIMPLE_CASES + 24 dedicated
regression/ambiguity/ReDoS tests).

Cross-language finding, NOT fixed here (filed separately): the
spec_exposure quadratic-blowup pattern fixed above is copy-pasted
identically across 28 languages in language_standards.py, including
several already-closed epic languages (yacc among them) -- confirmed via
direct ReDoS timing on 3 samples (~4x per doubling, consistent). Needs its
own dedicated sweep.

Golden crucible: zero diff, confirmed legitimate -- the crucible corpus
contains zero real .groovy/.gvy/.gy/.gsh/.gradle/Jenkinsfile files
anywhere (the data/groovy/ directory group holds only .java sources from
Spock/Gradle's own implementation).

Co-authored-by: Joe Esquibel <squid-protocol@users.noreply.github.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

🐦‍⬛ Muninn Security Scan

✅ No security issues found.

🐦‍⬛ Powered by Muninn · Skald Lab

@squid-protocol
squid-protocol merged commit ee06308 into main Jul 28, 2026
27 checks passed
@squid-protocol
squid-protocol deleted the fix/584-groovy-strict-parsing branch July 28, 2026 20:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Strict parsing tests: groovy structural signatures

1 participant