Ruby
Describes how recheck checks a regular expression of the ruby dialect.
Engine
recheck follows the syntax and the semantics of Ruby 4.0's Regexp, which is Onigmo.
Settings
encodingis the encoding of the regexp,UTF-8(default) orASCII-8BIT(as thenflag makes).
- CLI
- JavaScript
- Scala
$ recheck --dialect=ruby '/^(a|a)*$/'
$ recheck --dialect=ruby --ruby-encoding=ASCII-8BIT '/^(a|a)*$/'
import { check } from "recheck";
await check("^(a|a)*$", "", { dialect: "ruby" });
await check("^(a|a)*$", "", {
dialect: { name: "ruby", encoding: "ASCII-8BIT" },
});
import codes.quine.labs.recheck.ReDoS
import codes.quine.labs.recheck.common.Parameters
import codes.quine.labs.resyntax.dialect.Dialect
ReDoS.check("^(a|a)*$", "", Parameters(dialect = Dialect.Ruby()))
ReDoS.check("^(a|a)*$", "", Parameters(dialect = Dialect.Ruby(Dialect.Ruby.Encoding.ASCII8Bit)))
Flags and Units
The matching unit is scalar-value in UTF-8 (the default encoding), and byte in ASCII-8BIT (or with the n flag) (see Matching Units).
recheck supports the following options of a regexp literal (e.g. /.../i) and inline options, written as their letters.
| Flag | Regexp option | Inline | Notes |
|---|---|---|---|
i | Regexp::IGNORECASE | (?i) | |
m | Regexp::MULTILINE | (?m) | . matches a line break, as s does in the other dialects (^ and $ always match at line boundaries). |
x | Regexp::EXTENDED | (?x) | |
n | Regexp::NOENCODING | An ASCII-8BIT pattern (the literal /n), as encoding: "ASCII-8BIT" makes. | |
a | (?a) | The ASCII character set. | |
d | (?d) | The default character set. | |
u | (?u) | The Unicode character set, which is not the literal /u (Regexp::FIXEDENCODING). | |
o | The literal /o, no effect on matching. |
Syntax Limitations
The following constructs are not supported, and they are reported as unsupported.
- Subroutine calls (e.g.
\g<name>and\g<1>). - Back-references with a nest level (e.g.
\k<n+1>). - Absence operators (e.g.
(?~abc)). - Under
i, more than six places in a run of literals that match a folding to several characters, such asßorss, which matchesß(e.g.ssssssssgivesToo many multi-character case foldings in a literal (limit 6) at 0).
The encodings EUC-JP (/e) and Windows-31J (/s) are not supported, and their flags are reported as invalid.
Approximations
- Ruby has memoization (since Ruby 3.2) that
recheckdoes not model, so an attack thatrecheckreports may not work on Ruby, and the runtime-attack verification checks whether it does. \Gmatches only at the start of the input, sincerecheckmodels a search from there, not one from a later position (e.g. the second match ofString#scan).- Under
i,recheckdoes not reproduce Onigmo's bugs in matching a character folded to several characters (e.g.ßandss). For example,(?<=ß)and(ß)\1do not match"ß"and"ßss"in Ruby, but they do inrecheck. Also,[s]sandßsmatch"ß"and"sß"in Ruby, but not inrecheck. - Under
i,recheckadds the folding of each character of a case-folded class, so[sẞ]triessstwice, where Ruby tries it once. - A pattern of only ASCII characters has no fixed encoding: Ruby matches a string of only ASCII characters by the pattern compiled in
US-ASCII, where no character is folded to several characters, and Ruby keeps the pattern compiled again inUTF-8after matching another string. So/[[:alpha:]]/imatchesssonly after matching a non-ASCII string, and/(?<=a[[:lower:]])y/iraisesRegexpErroron a non-ASCII string.rechecktakes such a pattern inUTF-8(e.g. it reports(?<=a[[:lower:]])ywithias invalid). - An iteration matching the empty string is not handled as Ruby does: Onigmo repeats copies of the node for a bounded repetition depending on the size of its compiled code, and it checks the captures in an empty iteration.
- Onigmo does not restore the end of a group on backtracking inside the group, so a back-reference in the group can see the end of a failed attempt, and
recheckdoes not reproduce it. For example,^(a|ab\1)*$matches"aba"in Ruby 4.0, but not inrecheck.
Runtime-Attack Verification
- Command:
ruby -. - Matching:
Regexp#match?(noRegexp.timeout). - Engine limits: none.
- Engine errors:
RegexpError,NoMemoryError,SystemStackError. - Environment variable:
RECHECK_RUBY.