Annotation Interface SafeRegex


Guards the regex operators within the annotated scope against Regular Expression Denial of Service (ReDoS). Match (==~) and find (=~) expressions are rewritten at compile time to deadline-guarded RegexGuard calls which throw RegexTimeoutException if evaluation, e.g. due to catastrophic backtracking on adversarial input, exceeds the configured timeout. Matching semantics are otherwise unchanged, including left-to-right evaluation of the operands, which the generated call preserves by taking them in the operator's order.
 @SafeRegex(millis = 200)
 class Handler {
     boolean check(String input) {
         input ==~ /(a+)+$/    // rewritten to RegexGuard.matchRegex(input, /(a+)+$/, 200)
     }
 }
 
For the find operator, the deadline covers the whole use of the returned matcher, i.e. it starts when the matcher is created and later matcher operations such as find() throw once it has passed.

When placed on a field or local variable declaration, only regex operators lexically within the initializer expression are guarded; later uses of the variable are unaffected. A guarded field initializer runs, as usual, in the constructor (or in the static initializer for a static field, where a timeout surfaces as an ExceptionInInitializerError whose cause is the RegexTimeoutException).

Limitations: only regex operators lexically visible within the annotated scope are rewritten. Regex evaluation via method calls such as String#matches, replaceAll or split, or occurring in code called from the annotated scope, is not guarded; use RegexGuard explicitly for those. This is an opt-in facility, never a blanket default.

Since:
6.0.0
See Also:
  • Optional Element Summary

    Optional Elements
    Modifier and Type
    Optional Element
    Description
    long
    Returns the timeout in milliseconds applied to each guarded regex evaluation within the annotated scope.
  • Element Details

    • millis

      long millis
      Returns the timeout in milliseconds applied to each guarded regex evaluation within the annotated scope. Must be positive.
      Returns:
      the timeout in milliseconds
      Default:
      1000L