oracle/graal · error · UnsupportedRegexException

Literal parsing is not supported

Error message

Literal parsing is not supported

What it means

JavaRegexLexer rejects Pattern.LITERAL at construction with UnsupportedRegexException: literal (non-meta) parsing mode is not implemented by the TRegex Java-flavor frontend, even though java.util.regex supports treating the whole pattern as a literal string.

Source

Thrown at regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/flavor/java/JavaRegexLexer.java:155

        }
    }

    private static final TBitSet WHITESPACE = TBitSet.valueOf('\t', '\n', '\f', '\r', ' ');
    private static final TBitSet PREDEFINED_CHAR_CLASSES = TBitSet.valueOf('D', 'H', 'S', 'V', 'W', 'd', 'h', 's', 'v', 'w');
    private static final TBitSet LATIN1_CHARS_THAT_CASE_FOLD_TO_NON_LATIN1_CHARS = TBitSet.valueOf(0x49, 0x4b, 0x53, 0x69, 0x6b, 0x73, 0xb5, 0xc5, 0xe5, 0xff);

    final JavaUnicodeProperties unicode;
    private final Deque<JavaFlags> flagsStack = new ArrayDeque<>();
    private JavaFlags currentFlags;
    private final CodePointSetAccumulator curCharClass = new CodePointSetAccumulator();

    public JavaRegexLexer(RegexSource source, JavaFlags flags, CompilationBuffer compilationBuffer) {
        super(source, compilationBuffer);
        if (flags.isCanonEq()) {
            throw new UnsupportedRegexException("Canonical equivalence is not supported");
        }
        if (flags.isLiteral()) {
            throw new UnsupportedRegexException("Literal parsing is not supported");
        }
        this.unicode = JavaUnicodeProperties.create(source.getOptions());
        this.currentFlags = flags;
    }

    @Override
    protected boolean isPredefCharClass(char c) {
        return PREDEFINED_CHAR_CLASSES.get(c);
    }

    JavaFlags getLocalFlags() {
        return currentFlags;
    }

    public void pushLocalFlags() {
        flagsStack.push(currentFlags);
    }

View on GitHub (pinned to a66e9ccd1d)

Solutions

  1. Quote the pattern manually instead of using the flag: Pattern.compile(Pattern.quote(userInput)) without LITERAL.
  2. For simple substring search, skip regex entirely and use String.contains/String.indexOf or TruffleString operations.
  3. Update libraries that unconditionally pass LITERAL, or run them on a context where the host engine handles the compile.

Example fix

// before
Pattern p = Pattern.compile(userInput, Pattern.LITERAL); // throws on TRegex

// after
Pattern p = Pattern.compile(Pattern.quote(userInput)); // equivalent literal semantics
Defensive patterns

Strategy: fallback

Validate before calling

if ((flags & Pattern.LITERAL) != 0) {
    pattern = Pattern.quote(pattern);
    flags &= ~Pattern.LITERAL;
}

Try / catch

try {
    return Pattern.compile(pattern, flags);
} catch (com.oracle.truffle.regex.UnsupportedRegexException e) {
    if ((flags & Pattern.LITERAL) != 0) {
        return Pattern.compile(Pattern.quote(pattern), flags & ~Pattern.LITERAL);
    }
    throw e;
}

Prevention

When it happens

Trigger: Pattern.compile(userInput, Pattern.LITERAL) executed on Espresso/TRegex, or any library that uses LITERAL to safely match arbitrary user-provided strings containing regex metacharacters.

Common situations: Search/replace features that take raw user text as a pattern; security-conscious code that deliberately avoids pattern injection by using LITERAL; log-grepping tools running on GraalVM.

Related errors


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