Skip to content

Compare FoldCase in Regexp.equals/hashCode for LITERAL/CHAR_CLASS. - #212

Open
jemmix wants to merge 1 commit into
google:masterfrom
jemmix:fix-foldcase-in-regexp-equals
Open

jemmix wants to merge 1 commit into
google:masterfrom
jemmix:fix-foldcase-in-regexp-equals

Conversation

@jemmix

@jemmix jemmix commented Sep 17, 2026

Copy link
Copy Markdown

Fixes #211.

Regexp.equals() compared only the runes for LITERAL/CHAR_CLASS, so alternation factoring (Parser.factor round 1) merged a folded literal with its case-sensitive twin and the fold leaked into the merged arm: (?i:Z)x|Z matched lowercase "z" (the case-sensitive arm was effectively deleted). Go's regexp/syntax compares Flags&FoldCase here; the port dropped it.

This adds FoldCase to both equals() and hashCode() (factoring groups via hashCode first, so the hash must agree with equality).

Adds FoldCaseFactoringTest: the fold no longer leaks ((?i:Z)x|Z, (?i:[Z])x|[Z] reject "z"), and both arms still match ("Zx" via the folded arm, "Z" via the case-sensitive one).

Verified locally with ./gradlew check on JDK 8: 1831 tests, 0 failures, verifyGoogleJavaFormat + license green.

Disclosure (as in #211): found while fuzzing https://github.com/jemmix/tdfa-jvm against re2j; patch and tests composed agentically with GLM 5.3 assistance; verification run locally by me.

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.

Folded literal factored with its case-sensitive twin: (?i:Z)x|Z matches "z"

1 participant