Conversation
simpleFold's table-miss fallback follows toLower/toUpper, assuming the mappings form closed two-element orbits with the rune. That holds only for symmetric pairs: runes whose asymmetric case mappings postdate the generated tables' Unicode version (e.g. U+1C80..U+1C88, Cyrillic historic letters, added in Unicode 9.0 vs tables at 6.0) step into the partner's own orbit and never cycle back, hanging Pattern.compile and the match-time fold walks (minFoldRune, appendFoldedRange, equalsIgnoreCase). The fallback now follows a mapping only when the partner maps back (a verified symmetric pair), so such runes are fold-inert and every walk terminates structurally -- no hop cap, control-flow only, zero data changes. Symmetric pairs, including post-6.0 ones reached via the runtime's mappings, fold exactly as before. Adds CaseFoldTerminationTest: every U+1C80..U+1C88 compiles under (?i) (used to hang), the letters are consistently fold-inert in literal and class form in both directions, and symmetric pairs (z/Z, Cyrillic two-element pairs, the three-element K/k/Kelvin-sign orbit) keep folding. Regenerating the tables from current Unicode is the fuller fix (the universe then matches the runtime again); this change makes every walk terminate regardless of table/runtime skew, so it also guards whatever skew the next regeneration misses.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #168.
As diagnosed in #168 (see @rsc's comment):
simpleFold's table-miss fallback followstoLower/toUpperassuming they form closed two-element orbits with the rune. That holds only for symmetric pairs — for runes whose asymmetric case mappings postdate the generated tables (U+1C80..U+1C88, Unicode 9.0 vs tables at 6.0) the walk steps into the partner's own orbit and never cycles back, hangingPattern.compileand the match-time fold walks (minFoldRune,appendFoldedRange,equalsIgnoreCase).This implements the symmetry check suggested there: the fallback follows a mapping only when the partner maps back (
toLower(r)is followed ifftoUpper(toLower(r)) == r, and vice versa), so such runes are fold-inert and every walk terminates structurally. Control-flow only, zero data changes; symmetric pairs — including post-6.0 ones reached via the runtime's mappings — fold exactly as before.Regenerating the tables from current Unicode (or the runtime-derived orbit computation also discussed in #168) is the fuller fix and would restore folding for these runes; this change is deliberately minimal and also guards whatever skew a future regeneration misses, since termination no longer depends on the tables agreeing with the runtime.
Adds
CaseFoldTerminationTest: every U+1C80..U+1C88 compiles under(?i)(all used to hang), the letters are consistently fold-inert in literal and class form in both directions (e.g.(?i)Ꚁno longer matchesВ/в), and symmetric pairs keep folding — plain two-element pairs via the fallback plus the three-element K/k/Kelvin-sign orbit from the table.Verified locally with
./gradlew checkon JDK 8: 1829 tests, 0 failures,verifyGoogleJavaFormat+licensegreen.Disclosure: found while fuzzing https://github.com/jemmix/tdfa-jvm against re2j (patch 0003 there); analysis and patch composed agentically with GLM 5.3 assistance; verification run locally by me.