oracle/graal · error · UnsupportedRegexException

possessive quantifiers are not supported

Error message

possessive quantifiers are not supported

What it means

The same possessive-quantifier rejection as in the parser, raised from the JavaRegexValidator pass. TRegex validates the token stream before compilation; when a Quantifier token has isPossessive() set, the validator throws UnsupportedRegexException('possessive quantifiers are not supported') even in contexts where the parser's own check did not fire (e.g. dangling or validator-only paths).

Source

Thrown at regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/flavor/java/JavaRegexValidator.java:126

                case wordBoundary:
                case nonWordBoundary:
                case charClass:
                case classSet:
                case linebreak:
                case backReference:
                    curTermState = CurTermState.Other;
                    break;
                case quantifier:
                    Token.Quantifier quantifier = (Token.Quantifier) token;
                    // quantifiers of type *, + or ? cannot directly follow another quantifier
                    if (last instanceof Token.Quantifier && quantifier.isSingleChar()) {
                        throw syntaxErrorHere(JavaErrorMessages.danglingMetaCharacter(quantifier), ErrorCode.InvalidQuantifier);
                    }
                    if (curTermState == CurTermState.Null && quantifier.isSingleChar()) {
                        throw syntaxErrorHere(JavaErrorMessages.danglingMetaCharacter(quantifier), ErrorCode.InvalidQuantifier);
                    }
                    if (quantifier.isPossessive()) {
                        throw new UnsupportedRegexException("possessive quantifiers are not supported");
                    }
                    break;
                case alternation:
                case inlineFlags:
                    curTermState = CurTermState.Null;
                    break;
                case captureGroupBegin:
                case nonCaptureGroupBegin:
                    curTermState = CurTermState.Null;
                    syntaxStack.add(RegexStackElem.Group);
                    break;
                case lookAheadAssertionBegin:
                    curTermState = CurTermState.Null;
                    syntaxStack.add(RegexStackElem.LookAheadAssertion);
                    break;
                case lookBehindAssertionBegin:
                    curTermState = CurTermState.Null;
                    syntaxStack.add(RegexStackElem.LookBehindAssertion);

View on GitHub (pinned to a66e9ccd1d)

Solutions

  1. Remove the possessive '+' from every quantifier in the pattern ('a?+' -> 'a?', '(ab){1,3}+' -> '(ab){1,3}')
  2. Grep patterns for the possessive suffix regex ([*+?}]|\{[0-9]+(,[0-9]*)?\})\+ before compiling when patterns are externally supplied
  3. If cut semantics are required, compute them outside the regex or switch to java.util.regex for that pattern

Example fix

// before
String p = "x?+y";

// after
String p = "x?y";
Defensive patterns

Strategy: validation

Validate before calling

private static final java.util.regex.Pattern POSSESSIVE =
    java.util.regex.Pattern.compile("([*+?]|\\{[0-9]+(,[0-9]*)?\\})\\+");

boolean hasPossessiveQuantifier(String pattern) {
    return POSSESSIVE.matcher(pattern).find();
}

Try / catch

try {
    RegexObject re = compileJavaFlavor(pattern);
} catch (UnsupportedRegexException e) {
    if (e.getReason().contains("possessive")) {
        pattern = POSSESSIVE.matcher(pattern).replaceAll("$1");
        re = compileJavaFlavor(pattern);
    } else { throw e; }
}

Prevention

When it happens

Trigger: Any Java-flavor pattern containing *+, ++, ?+ or {n,m}+ that reaches the validation stage, e.g. validating "x?+" after parse; the validator's quantifier case calls quantifier.isPossessive() and throws.

Common situations: Same as the parser variant: JDK-optimized or ReDoS-hardened patterns with possessive quantifiers run on a TRegex-backed engine; users see either this validator message or the parser's depending on which pass encounters the token first.

Related errors


AI-assisted analysis of oracle/graal@a66e9ccd1d (2026-08-14). Data as JSON: /api/errors/21bd7e38c6158f37. Report an issue: GitHub.