Perl
Describes how recheck checks a regular expression of the perl dialect.
Engine
recheck follows the syntax and the semantics of Perl 5.44's regular expressions.
Settings
utf8tells whether the program hasuse utf8and its strings are decoded text, which has the UTF-8 flag.true(default) is a program withuse utf8whose strings are decoded text.falseis a program withoutuse utf8whose strings are bytes without the flag. A program reading text that is not decoded (e.g. Latin-1 bytes) isutf8: false.sourcetells how the pattern is given.literal(default) is a regular expression literal written in Perl source (e.g.qr/.../), where Perl applies\U,\L,\u,\l,\F,\Qand\Eto the text before the regex engine reads it.stringis a pattern from a string at runtime (e.g.qr/$p/), which the regex engine reads unchanged.
- CLI
- JavaScript
- Scala
$ recheck --dialect=perl '/^(a|a)*$/'
$ recheck --dialect=perl --no-perl-utf8 --perl-source=string '/^(a|a)*$/'
import { check } from "recheck";
await check("^(a|a)*$", "", { dialect: "perl" });
await check("^(a|a)*$", "", {
dialect: { name: "perl", utf8: false, source: "string" },
});
import codes.quine.labs.recheck.ReDoS
import codes.quine.labs.recheck.common.Parameters
import codes.quine.labs.resyntax.dialect.Dialect
import codes.quine.labs.resyntax.dialect.PerlSource
ReDoS.check("^(a|a)*$", "", Parameters(dialect = Dialect.Perl()))
ReDoS.check("^(a|a)*$", "", Parameters(dialect = Dialect.Perl(utf8 = false, source = PerlSource.String)))
Flags and Units
The matching unit is code-point with utf8: true (the default), and byte with utf8: false (see Matching Units).
recheck supports all the modifiers of m//, qr// and s///.
| Flag | Modifier | Inline | Notes |
|---|---|---|---|
a | /a | (?a) | The ASCII rules. |
aa | /aa | (?aa) | The ASCII rules, and no case-insensitive match between an ASCII and a non-ASCII character. |
d | /d | (?d) | The default rules. |
l | /l | (?l) | The rules of the C locale. |
u | /u | (?u) | The Unicode rules. |
i | /i | (?i) | |
m | /m | (?m) | |
n | /n | (?n) | |
s | /s | (?s) | |
x, xx | /x, /xx | (?x), (?xx) | |
p | /p | (?p) | No effect on matching. |
o | /o | No effect on matching. | |
g, c | /g, /c | No effect on matching, since recheck models a search from the start. | |
e, r | /e, /r | The modifiers of s///, no effect on matching. |
Syntax Limitations
The following constructs are not supported.
- Recursion and subroutine calls (e.g.
(?R),(?1)and(?&name)), including(?(DEFINE)...)in a pattern with calls, are reported asunsupported. - Embedded code (e.g.
(?{ ... })and(??{ ... })), user-defined properties (e.g.\p{IsFoo}) and property wildcards (e.g.\p{gc=/^L/}) are reported asunsupported. \N{name}(e.g.\N{EM DASH}) and word boundaries of a kind (e.g.\b{wb}and\b{gcb}) are reported asunsupported.- Under
i, more than six places in a run of literals that match a folding to several characters, such asßorss, which matchesß, are reported asunsupported(e.g.ssssssssgivesToo many multi-character case foldings in a literal (limit 6) at 0). - Extended bracketed character classes (
(?[ ... ])) are not supported yet, and they are reported asinvalid.
Approximations
- Perl has caches of the super-linear matching that
recheckdoes not model, so an attack thatrecheckreports may not work on Perl, 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 ofm//g).- Under
i, Perl matches a character against its folding to several characters (e.g.ßagainstss). Whether several nodes together match such a character depends on how Perl joins the nodes into a string on compiling, andrecheckdoes not reproduce it. A non-capturing group and a class of one character or of a character and its case variants join (e.g.(?:s)s,s[s]and[sS]smatchß). A quantifier and a capturing group do not join (e.g.s{2},[s]{2},s?sand(s)sdo not matchß). - Under
i, Perl also matches a run of literals against a string with the same folding whose characters split it differently, andrecheckdoes not reproduce it. For example,ßsmatches"sß", since both fold tosss, andffimatches"ffi"andffimatches"ffi", since all of them fold toffi. - Perl backs off one character at a time from
\Runder a simple quantifier, which can split\r\n(e.g.^\R?\n$matches"\r\n"in Perl, but not in PCRE or Ruby), andrecheckdoes not reproduce it. - Perl skips the attempts that cannot match by its start-of-match optimizations, and
recheckdoes not model them. - Perl compiles alternatives starting with literals into a trie, and
(*THEN)in the trie skips the other alternatives in it (e.g.aa(*THEN)b|amatches the secondaof"aac").recheckdoes not reproduce it, and(*THEN)takes the next alternative as in PCRE (matching the firsta). - Under
i, Perl lowers the minimum length of a look-behind by the literals that may match a shorter folded character, which comes from joining the literals on compiling (e.g.(?<=ss)xmatches"ßx").rechecksteps back by the lengths of the literals, so it does not reproduce such a match. - Perl compiles a repetition of a fixed-length node with no captures inside (e.g.
(a)?) into a counting node, which unsets the capture of the node when the repetition matches nothing (e.g.^(?:(a)?b){2}\1$does not match"abba").recheckdoes not reproduce it, and such a repetition keeps the capture of an earlier iteration as the other repetitions do. lfollows the C locale, where0x80–0xFFfollow the ASCII rules even withutf8, whatever locale the environment has. Underi, no character folds acrossU+00FFandU+0100there (e.g.kdoes not match the Kelvin signU+212A, andßmatches neitherẞnorss).
Runtime-Attack Verification
- Command:
perl -. - Matching:
=~. - Engine limits: none.
- Engine errors: none.
- Environment variable:
RECHECK_PERL.
With the literal source, the runtime-attack verification is skipped for a pattern that would interpolate a variable or run code as a literal (e.g. $name, @{...} or (?{ ... })), so runtimeAttack is null, and generate-runtime-attack-script fails.