yo_common/re.rs
1//! A POSIX extended regular expression matcher over bytes.
2//!
3//! Redis has one command that takes a regular expression, `ARGREP ... RE`, and
4//! it gets it from TRE, which it vendors under `deps/tre`. What it asks TRE for
5//! is narrow: `REG_EXTENDED | REG_NOSUB | REG_USEBYTES`, optionally `REG_ICASE`,
6//! and then a yes or no per element. No capture groups are read, no match
7//! offsets are read, and a pattern with a backreference in it is refused before
8//! it is ever run. So the thing that has to be built is a boolean matcher for
9//! extended regular expressions over bytes, which is a much smaller object than
10//! a general purpose regex crate.
11//!
12//! That is the whole reason this is here rather than a dependency. The
13//! workspace has four third party crates in it and two of them are only for
14//! tests, and adding a regex engine and its three transitive crates to the
15//! engine that the C ABI and every language binding link against is a large
16//! thing to pay for one command. Writing the narrow version is a few hundred
17//! lines and it comes out with a property the general one cannot promise: the
18//! simulation is a Thompson construction walked with a set of live states, so
19//! matching is linear in the subject and cannot be made to blow up by a pattern.
20//! `ARGREP` runs its predicates over every element a range touches, from a
21//! pattern a client sent, so that is worth having rather than being clever.
22//!
23//! The syntax is TRE's, read off `deps/tre/lib/tre-parse.c` rather than off
24//! POSIX, because the point is to agree with the server people are migrating
25//! from. TRE has a table of macros that run before anything else, so `\n` is a
26//! newline, `\d` is `[[:digit:]]` and `\w` is `[[:alnum:]_]`, and after that a
27//! switch with `\b`, `\B`, `\<`, `\>` and `\xNN`. The one that surprises people
28//! is that a backslash inside a bracket expression is a literal backslash and
29//! not an escape, so `[\d]` is a backslash or a d.
30//!
31//! Bytes rather than characters, the same as `glob`, and for the same reason: an
32//! array element is arbitrary bytes and deciding what a character is would mean
33//! deciding what encoding it is in.
34//!
35//! Every rule in here was either read off a line of TRE or measured against it.
36//! The measuring was done by building TRE from `deps/tre` into a small program
37//! that answers the same question this does, and then generating patterns from
38//! the pieces TRE's parser has cases for and comparing the two answers. That is
39//! how the macro table was found, along with the way a repeated assertion stays
40//! mandatory, the split between the two errors a bad bound gives, and the
41//! handful of places where TRE and Redis's own fast path disagree with each
42//! other. Roughly a quarter of a million comparisons agree.
43
44use core::fmt;
45
46/// The largest `{n,m}` repetition, which is TRE's `RE_DUP_MAX`.
47pub const DUP_MAX: u32 = 255;
48
49/// The largest program a pattern may compile to.
50///
51/// A bound repetition is expanded by copying, so `(a{255}){255}` is sixty five
52/// thousand instructions and nesting one more level is sixteen million. The cap
53/// is what stops a short pattern from turning into a long compile, and it is
54/// generous enough that nothing anyone writes by hand reaches it.
55const PROG_MAX: usize = 100_000;
56
57/// The deepest a pattern may nest groups.
58///
59/// The parser is recursive, so this is the difference between refusing a
60/// pattern and overflowing the stack on the shard thread.
61const DEPTH_MAX: u32 = 64;
62
63/// Why a pattern would not compile.
64///
65/// The names and the messages are TRE's, from `deps/tre/lib/regerror.c`,
66/// because Redis puts the message straight into its error reply and a client
67/// that matches on the text should not be able to tell the two servers apart.
68#[derive(Clone, Copy, Debug, PartialEq, Eq)]
69pub enum Error {
70 /// `REG_BADPAT`, a pattern that is not one.
71 BadPattern,
72 /// `REG_ECOLLATE`, a `[.` or `[=` bracket item.
73 Collate,
74 /// `REG_ECTYPE`, a `[:name:]` that is not a class.
75 CharClass,
76 /// `REG_EESCAPE`, a backslash at the very end.
77 TrailingBackslash,
78 /// `REG_ESUBREG`, a backreference to a group the pattern does not have.
79 BackRef,
80 /// A backreference to a group that does exist.
81 ///
82 /// Not one of TRE's codes. TRE compiles this and Redis refuses it a step
83 /// later with a sentence of its own, so the message here is that sentence
84 /// and a caller reporting it should not put "invalid regular expression"
85 /// in front of it the way it would for the rest of these.
86 Unsupported,
87 /// `REG_EBRACK`, a bracket expression with no `]`.
88 MissingBracket,
89 /// `REG_EPAREN`, a group with no `)`.
90 MissingParen,
91 /// `REG_EBRACE`, a `\x{` or a `{` with no `}`.
92 MissingBrace,
93 /// `REG_BADBR`, a `{}` whose contents are not a bound.
94 BadBrace,
95 /// `REG_ERANGE`, a bracket range that runs backwards.
96 BadRange,
97 /// `REG_ESPACE`, a pattern that compiles to more than this engine will hold.
98 Space,
99 /// `REG_BADRPT`, a repetition operator with nothing in front of it.
100 BadRepeat,
101 /// `REG_BADMAX`, a `{n,m}` past [`DUP_MAX`].
102 BadMax,
103}
104
105impl Error {
106 /// TRE's message for this code, which is what the client sees.
107 #[must_use]
108 pub const fn as_str(self) -> &'static str {
109 match self {
110 Error::BadPattern => "Invalid regexp",
111 Error::Collate => "Unknown collating element",
112 Error::CharClass => "Unknown character class name",
113 Error::TrailingBackslash => "Trailing backslash",
114 Error::BackRef => "Invalid back reference",
115 Error::Unsupported => "regular expression backreferences are not supported",
116 Error::MissingBracket => "Missing ']'",
117 Error::MissingParen => "Missing ')'",
118 Error::MissingBrace => "Missing '}'",
119 Error::BadBrace => "Invalid contents of {}",
120 Error::BadRange => "Invalid character range",
121 Error::Space => "Out of memory",
122 Error::BadRepeat => "Invalid use of repetition operators",
123 Error::BadMax => "Maximum repetition in {} larger than 255",
124 }
125 }
126}
127
128impl fmt::Display for Error {
129 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
130 f.write_str(self.as_str())
131 }
132}
133
134/// A set of bytes, as one bit each.
135///
136/// Every consuming step in the program is one of these, so a literal, a `.`, a
137/// bracket expression and a `[:alpha:]` are all the same instruction and the
138/// matcher has one case rather than four.
139#[derive(Clone, Copy, PartialEq, Eq, Debug)]
140struct Class([u64; 4]);
141
142impl Class {
143 const fn empty() -> Class {
144 Class([0; 4])
145 }
146
147 const fn all() -> Class {
148 Class([u64::MAX; 4])
149 }
150
151 fn set(&mut self, b: u8) {
152 self.0[(b >> 6) as usize] |= 1 << (b & 63);
153 }
154
155 fn clear(&mut self, b: u8) {
156 self.0[(b >> 6) as usize] &= !(1 << (b & 63));
157 }
158
159 fn set_range(&mut self, lo: u8, hi: u8) {
160 for b in lo..=hi {
161 self.set(b);
162 }
163 }
164
165 const fn has(self, b: u8) -> bool {
166 self.0[(b >> 6) as usize] >> (b & 63) & 1 == 1
167 }
168
169 fn negate(&mut self) {
170 for w in &mut self.0 {
171 *w = !*w;
172 }
173 }
174
175 /// Add the other case of every letter already in the set.
176 ///
177 /// Done once when the class is built rather than per byte at match time,
178 /// and done to the positive set before a `[^...]` is negated, so `[^a]`
179 /// under NOCASE refuses `A` as well.
180 fn fold_case(&mut self) {
181 for b in b'a'..=b'z' {
182 if self.has(b) {
183 self.set(b - 32);
184 }
185 }
186 for b in b'A'..=b'Z' {
187 if self.has(b) {
188 self.set(b + 32);
189 }
190 }
191 }
192}
193
194/// A zero width test, which the closure evaluates rather than the step.
195#[derive(Clone, Copy, PartialEq, Eq, Debug)]
196enum Assert {
197 /// `^`, the start of the subject. Not the start of a line: Redis does not
198 /// pass `REG_NEWLINE`, so a newline in the subject is an ordinary byte.
199 Start,
200 /// `$`, the end of the subject.
201 End,
202 /// `\b` when true, `\B` when false.
203 ///
204 /// TRE calls both of these true at the start of the subject and at a byte
205 /// it reads as the end, without looking at either side, so `\b` holds and
206 /// `\B` fails there whatever the neighbours are.
207 Word(bool),
208 /// `\<`, the first byte of a word.
209 StartOfWord,
210 /// `\>`, one past the last byte of a word.
211 EndOfWord,
212}
213
214/// One byte as a class, whatever NOCASE says.
215///
216/// TRE only folds a byte it read straight out of the pattern, because the fold
217/// lives in the branch of the parser that handles a plain byte. A byte that an
218/// escape produced never passes through there, so `\x41` under NOCASE is `A`
219/// and not `A` or `a`.
220fn raw(b: u8) -> Class {
221 let mut c = Class::empty();
222 c.set(b);
223 c
224}
225
226const fn is_word(b: u8) -> bool {
227 b.is_ascii_alphanumeric() || b == b'_'
228}
229
230impl Assert {
231 fn holds(self, hay: &[u8], at: usize) -> bool {
232 let before = at > 0 && is_word(hay[at - 1]);
233 let after = at < hay.len() && is_word(hay[at]);
234 match self {
235 Assert::Start => at == 0,
236 Assert::End => at == hay.len(),
237 // TRE decides these by reading the byte ahead and comparing it
238 // against nul, so the end of the subject and a nul byte inside it
239 // look the same, and the start is not looked at either way.
240 Assert::Word(want) => {
241 let edge = at == 0 || at == hay.len() || hay[at] == 0;
242 (edge || before != after) == want
243 }
244 Assert::StartOfWord => !before && after,
245 Assert::EndOfWord => before && !after,
246 }
247 }
248}
249
250/// One step of the compiled program.
251#[derive(Clone, Copy, Debug)]
252enum Inst {
253 /// Consume one byte in `classes[i]` and carry on at the next instruction.
254 Class(u32),
255 /// Be in both places at once.
256 Split(u32, u32),
257 /// Carry on somewhere else.
258 Jump(u32),
259 /// Carry on at the next instruction if the test holds.
260 Assert(Assert),
261 /// The pattern matched.
262 Match,
263}
264
265/// What the parser builds before anything is laid out.
266///
267/// A tree rather than instructions with holes to patch, because `{n,m}` is
268/// compiled by emitting the same subtree several times and a tree is the thing
269/// that can be walked twice.
270enum Ast {
271 Empty,
272 Class(Class),
273 Assert(Assert),
274 Concat(Vec<Ast>),
275 Alt(Vec<Ast>),
276 Repeat(Box<Ast>, u32, Option<u32>),
277}
278
279/// A compiled pattern.
280///
281/// Compiling allocates and matching does not, which is the split `ARGREP` wants:
282/// a pattern is compiled once when the command is parsed and then run against
283/// every element the range touches.
284#[derive(Debug)]
285pub struct Regex {
286 prog: Vec<Inst>,
287 classes: Vec<Class>,
288}
289
290impl Regex {
291 /// Compile `pattern` as an extended regular expression over bytes.
292 ///
293 /// `nocase` is `REG_ICASE`, and it is applied while the byte classes are
294 /// built rather than while matching, so it costs nothing per element.
295 ///
296 /// # Errors
297 ///
298 /// Any of [`Error`], carrying TRE's own message for the same mistake.
299 pub fn new(pattern: &[u8], nocase: bool) -> Result<Regex, Error> {
300 let mut p = Parser {
301 pat: pattern,
302 at: 0,
303 nocase,
304 newline: false,
305 depth: 0,
306 groups: 0,
307 backref: None,
308 };
309 let ast = p.alternation()?;
310 if p.at != pattern.len() {
311 // Nothing reaches this. A `)` with no `(` is a literal and every
312 // other exit from `alternation` is the end of the pattern, so this
313 // is a guard against a future change rather than a live path.
314 return Err(Error::BadPattern);
315 }
316 // Both backreference answers wait for the whole parse, because TRE
317 // decides them in regcomp after tre_parse has returned, so a mistake
318 // anywhere else in the pattern is reported instead of these.
319 if let Some(n) = p.backref {
320 if n > p.groups {
321 return Err(Error::BackRef);
322 }
323 return Err(Error::Unsupported);
324 }
325 let mut c = Compiler {
326 prog: Vec::new(),
327 classes: Vec::new(),
328 };
329 c.node(&ast)?;
330 c.push(Inst::Match)?;
331 Ok(Regex {
332 prog: c.prog,
333 classes: c.classes,
334 })
335 }
336
337 /// How many instructions the pattern compiled to, for the matcher's scratch.
338 #[must_use]
339 fn len(&self) -> usize {
340 self.prog.len()
341 }
342}
343
344/// The scratch a match needs, kept across calls.
345///
346/// `ARGREP` runs a predicate per visited element, so the three vectors are
347/// allocated once for the command rather than once per element. A `Matcher` can
348/// be used with any [`Regex`]; it grows to the largest one it has seen.
349#[derive(Default, Debug)]
350pub struct Matcher {
351 /// The states live at this position, and the ones live at the next.
352 now: Vec<u32>,
353 next: Vec<u32>,
354 /// The stamp each state was last added under, so that adding a state
355 /// twice in one step is a comparison rather than a search.
356 seen: Vec<u64>,
357 /// The stack the epsilon closure walks with, so it is not the call stack.
358 work: Vec<u32>,
359 stamp: u64,
360}
361
362impl Matcher {
363 /// A matcher with nothing allocated yet.
364 #[must_use]
365 pub fn new() -> Matcher {
366 Matcher::default()
367 }
368
369 /// Grows the scratch to what `re` will need, so that matching never does.
370 ///
371 /// A state is added at most once per step, so none of the four vectors can
372 /// go past the program size. Doing the growth here means the caller can put
373 /// every allocation `ARGREP` makes in the part of the command that reads the
374 /// arguments, and the walk over the elements allocates nothing at all.
375 pub fn reserve(&mut self, re: &Regex) {
376 let n = re.len();
377 if self.seen.len() < n {
378 self.seen.resize(n, 0);
379 }
380 for v in [&mut self.now, &mut self.next, &mut self.work] {
381 v.reserve_exact(n.saturating_sub(v.capacity()));
382 }
383 }
384
385 /// Whether `re` matches anywhere in `hay`.
386 ///
387 /// Unanchored, which is what `regexec` without an anchor does and what
388 /// `ARGREP RE` means: the pattern has to match some run of bytes, not the
389 /// whole element.
390 ///
391 /// The walk is a Thompson simulation. Every state that could be live at a
392 /// position is live at once, so a byte is looked at exactly once and the
393 /// cost is the subject length times the program size in the worst case,
394 /// with no backtracking and therefore no pattern that makes it exponential.
395 pub fn is_match(&mut self, re: &Regex, hay: &[u8]) -> bool {
396 let n = re.len();
397 if self.seen.len() < n {
398 self.seen.resize(n, 0);
399 }
400 self.now.clear();
401 self.next.clear();
402 self.stamp += 1;
403 let mut stamp = self.stamp;
404
405 for at in 0..=hay.len() {
406 // Start a fresh attempt at every position, which is what makes the
407 // search unanchored without a `.*` in front of the program.
408 if add(
409 &mut self.now,
410 &mut self.seen,
411 &mut self.work,
412 stamp,
413 re,
414 hay,
415 at,
416 0,
417 ) {
418 return true;
419 }
420 if at == hay.len() {
421 break;
422 }
423 let byte = hay[at];
424 self.stamp += 1;
425 stamp = self.stamp;
426 self.next.clear();
427 for i in 0..self.now.len() {
428 let pc = self.now[i];
429 if let Inst::Class(c) = re.prog[pc as usize]
430 && re.classes[c as usize].has(byte)
431 && add(
432 &mut self.next,
433 &mut self.seen,
434 &mut self.work,
435 stamp,
436 re,
437 hay,
438 at + 1,
439 pc + 1,
440 )
441 {
442 return true;
443 }
444 }
445 core::mem::swap(&mut self.now, &mut self.next);
446 }
447 false
448 }
449}
450
451/// Add `pc` and everything reachable from it without consuming a byte.
452///
453/// Returns whether one of them was `Match`, which is the only answer `is_match`
454/// needs, so the walk stops the moment it is true rather than finishing the
455/// subject.
456#[allow(clippy::too_many_arguments)]
457fn add(
458 list: &mut Vec<u32>,
459 seen: &mut [u64],
460 work: &mut Vec<u32>,
461 stamp: u64,
462 re: &Regex,
463 hay: &[u8],
464 at: usize,
465 pc: u32,
466) -> bool {
467 work.clear();
468 work.push(pc);
469 while let Some(pc) = work.pop() {
470 let i = pc as usize;
471 if seen[i] == stamp {
472 continue;
473 }
474 seen[i] = stamp;
475 match re.prog[i] {
476 Inst::Class(_) => list.push(pc),
477 Inst::Split(a, b) => {
478 work.push(b);
479 work.push(a);
480 }
481 Inst::Jump(a) => work.push(a),
482 Inst::Assert(a) => {
483 if a.holds(hay, at) {
484 work.push(pc + 1);
485 }
486 }
487 Inst::Match => return true,
488 }
489 }
490 false
491}
492
493// ---------------------------------------------------------------------------
494// Parsing
495// ---------------------------------------------------------------------------
496
497struct Parser<'a> {
498 pat: &'a [u8],
499 at: usize,
500 nocase: bool,
501 /// Whether `.` skips a newline, which only `(?n)` can turn on because
502 /// Redis never passes `REG_NEWLINE` itself.
503 newline: bool,
504 depth: u32,
505 /// How many groups the pattern has opened so far.
506 groups: u32,
507 /// The highest backreference seen, if any.
508 ///
509 /// Whether one is valid is not known until the whole pattern has been read,
510 /// because a reference may point forwards: `\1(a)` is a reference to a
511 /// group that has not been written down yet and TRE takes it.
512 backref: Option<u32>,
513}
514
515impl Parser<'_> {
516 fn peek(&self) -> Option<u8> {
517 self.pat.get(self.at).copied()
518 }
519
520 fn eat(&mut self, b: u8) -> bool {
521 if self.peek() == Some(b) {
522 self.at += 1;
523 return true;
524 }
525 false
526 }
527
528 /// `branch ('|' branch)*`
529 fn alternation(&mut self) -> Result<Ast, Error> {
530 let mut arms = vec![self.branch()?];
531 while self.eat(b'|') {
532 arms.push(self.branch()?);
533 }
534 if arms.len() == 1 {
535 return Ok(arms.pop().expect("one arm"));
536 }
537 Ok(Ast::Alt(arms))
538 }
539
540 /// A run of repeated atoms, up to a `|` or a closing `)` or the end.
541 ///
542 /// An empty branch is allowed, so `a|` matches `a` or nothing and `()` is a
543 /// group that matches nothing, both of which TRE accepts.
544 fn branch(&mut self) -> Result<Ast, Error> {
545 let mut parts: Vec<Ast> = Vec::new();
546 loop {
547 match self.peek() {
548 None | Some(b'|') => break,
549 // A `)` only ends the branch when a `(` is waiting for it.
550 // Outside a group it is an ordinary byte, which is why `a)b`
551 // matches the three bytes it looks like rather than failing.
552 Some(b')') if self.depth > 0 => break,
553 _ => {}
554 }
555 // A repetition operator with nothing in front of it repeats an atom
556 // that matches the empty string, which is what TRE's parser hands
557 // back when it is asked for an atom and finds an operator. So `*a`
558 // is `a`, and `{2}a` is `a` rather than `aa`.
559 let atom = match self.peek() {
560 Some(b'*' | b'+' | b'?' | b'{') => Ast::Empty,
561 _ => self.atom()?,
562 };
563 parts.push(self.repeats(atom)?);
564 }
565 match parts.len() {
566 0 => Ok(Ast::Empty),
567 1 => Ok(parts.pop().expect("one part")),
568 _ => Ok(Ast::Concat(parts)),
569 }
570 }
571
572 /// Every repetition operator that follows an atom, applied outwards.
573 ///
574 /// A second operator straight after the first is reserved in TRE and
575 /// refused, so `a**` and `a{2}+` are both errors, with one exception: a `?`
576 /// asks for the shortest match rather than the longest. That changes where
577 /// a match ends and not whether there is one, so for a yes or no answer it
578 /// is read and dropped.
579 fn repeats(&mut self, mut node: Ast) -> Result<Ast, Error> {
580 loop {
581 let (min, max) = match self.peek() {
582 Some(b'*') => {
583 self.at += 1;
584 (0, None)
585 }
586 Some(b'+') => {
587 self.at += 1;
588 (1, None)
589 }
590 Some(b'?') => {
591 self.at += 1;
592 (0, Some(1))
593 }
594 Some(b'{') => {
595 self.at += 1;
596 self.bound()?
597 }
598 _ => return Ok(node),
599 };
600 match self.peek() {
601 Some(b'?') => self.at += 1,
602 Some(b'*' | b'+') => return Err(Error::BadRepeat),
603 _ => {}
604 }
605 node = Ast::Repeat(Box::new(node), min, max);
606 }
607 }
608
609 /// The inside of a bound, with the `{` already eaten.
610 ///
611 /// A count is optional on both sides of the comma, so `{,3}` is `{0,3}` and
612 /// `{2,}` has no ceiling, and a missing count on both sides with no comma
613 /// at all is the empty `{}`, which is an error. The three ways this can go
614 /// wrong are told apart by where the parse stopped: off the end of the
615 /// pattern is a missing brace, stopped without having read anything is an
616 /// empty bound, and stopped on something that is not a brace is a bound
617 /// with rubbish in it.
618 fn bound(&mut self) -> Result<(u32, Option<u32>), Error> {
619 let start = self.at;
620 let mut min: i64 = self.number().map_or(-1, i64::from);
621 let mut max = min;
622 if self.eat(b',') {
623 if min < 0 {
624 min = 0;
625 }
626 max = self.number().map_or(-1, i64::from);
627 }
628 // Both of these are decided before the brace is looked for, so `{3,2`
629 // is a backwards bound rather than a missing brace.
630 if max >= 0 && min > max {
631 return Err(Error::BadBrace);
632 }
633 if min > i64::from(DUP_MAX) || max > i64::from(DUP_MAX) {
634 return Err(Error::BadMax);
635 }
636 // TRE walks past spaces and further commas on its way to the brace, so
637 // `{2, }` and `{2,,}` are the same bound as `{2,}`.
638 while matches!(self.peek(), Some(b' ' | b',')) {
639 self.at += 1;
640 }
641 if self.at >= self.pat.len() {
642 return Err(Error::MissingBrace);
643 }
644 if self.at == start {
645 return Err(Error::BadBrace);
646 }
647 if !self.eat(b'}') {
648 return Err(Error::BadBrace);
649 }
650 if min < 0 {
651 // No count on either side and no comma, which after the parameters
652 // TRE allows here would be `{~2}` and friends. Those repeat once.
653 min = 1;
654 max = 1;
655 }
656 Ok((min as u32, if max < 0 { None } else { Some(max as u32) }))
657 }
658
659 fn number(&mut self) -> Option<u32> {
660 let start = self.at;
661 let mut n: u32 = 0;
662 while let Some(b) = self.peek() {
663 if !b.is_ascii_digit() {
664 break;
665 }
666 // A bound past DUP_MAX is refused anyway, so saturating here keeps
667 // a long run of digits from wrapping into a small number.
668 n = n.saturating_mul(10).saturating_add(u32::from(b - b'0'));
669 self.at += 1;
670 }
671 if self.at == start { None } else { Some(n) }
672 }
673
674 fn atom(&mut self) -> Result<Ast, Error> {
675 let b = self.peek().ok_or(Error::BadPattern)?;
676 match b {
677 b'(' => {
678 self.at += 1;
679 if self.eat(b'?') {
680 return self.extension();
681 }
682 self.groups += 1;
683 self.group()
684 }
685 b'.' => {
686 self.at += 1;
687 let mut c = Class::all();
688 if self.newline {
689 c.clear(b'\n');
690 }
691 Ok(Ast::Class(c))
692 }
693 b'^' => {
694 self.at += 1;
695 Ok(Ast::Assert(Assert::Start))
696 }
697 b'$' => {
698 self.at += 1;
699 Ok(Ast::Assert(Assert::End))
700 }
701 b'[' => {
702 self.at += 1;
703 self.bracket()
704 }
705 b'\\' => {
706 self.at += 1;
707 self.escape()
708 }
709 // Everything else is the byte, including a `)` with no `(` and a
710 // `]` with no `[`.
711 _ => {
712 self.at += 1;
713 Ok(Ast::Class(self.literal(b)))
714 }
715 }
716 }
717
718 /// Everything up to the `)` that closes a group whose `(` is already eaten.
719 fn group(&mut self) -> Result<Ast, Error> {
720 self.depth += 1;
721 if self.depth > DEPTH_MAX {
722 return Err(Error::Space);
723 }
724 let inner = self.alternation()?;
725 self.depth -= 1;
726 if !self.eat(b')') {
727 return Err(Error::MissingParen);
728 }
729 Ok(inner)
730 }
731
732 /// TRE's `(?...)` extensions, with the `(?` already eaten.
733 ///
734 /// The letters turn compile flags on, and a `-` turns the rest of them off
735 /// again. A `:` then opens a group that does not capture, while a `)` or a
736 /// `#` comment ends the extension and leaves the flags on for the rest of
737 /// whatever encloses it. That last part is worth reading twice: TRE parses
738 /// the remainder as a whole expression under the new flags, so `a(?i)b|c`
739 /// is `a` followed by `b|c` rather than `ab` or `c`. Anything else is
740 /// "Invalid regexp", which is why `(?x)` is refused.
741 fn extension(&mut self) -> Result<Ast, Error> {
742 let (nocase, newline) = (self.nocase, self.newline);
743 let mut on = true;
744 let opens = loop {
745 match self.peek().ok_or(Error::BadPattern)? {
746 b'i' => self.nocase = on,
747 b'n' => self.newline = on,
748 // Right associativity and ungreedy decide which match is
749 // reported rather than whether there is one, and Redis asks
750 // only whether there is one, so these are read and dropped.
751 b'r' | b'U' => {}
752 b'-' => on = false,
753 b':' => {
754 self.at += 1;
755 break true;
756 }
757 b'#' => {
758 // A comment is every byte up to the first `)`.
759 while self.peek().is_some_and(|b| b != b')') {
760 self.at += 1;
761 }
762 if !self.eat(b')') {
763 return Err(Error::BadPattern);
764 }
765 break false;
766 }
767 b')' => {
768 self.at += 1;
769 break false;
770 }
771 _ => return Err(Error::BadPattern),
772 }
773 self.at += 1;
774 };
775 let inner = if opens {
776 self.group()?
777 } else {
778 self.alternation()?
779 };
780 self.nocase = nocase;
781 self.newline = newline;
782 Ok(inner)
783 }
784
785 /// One byte as a class, case folded if `nocase`.
786 fn literal(&self, b: u8) -> Class {
787 let mut c = raw(b);
788 if self.nocase {
789 c.fold_case();
790 }
791 c
792 }
793
794 /// What follows a backslash outside a bracket expression.
795 ///
796 /// TRE looks at this in two rounds and the order is what decides several
797 /// of the answers. First it checks a table of macros, which are letters
798 /// that stand for a short pattern and get parsed as if the client had
799 /// written that pattern out. Only if the letter is not a macro does it
800 /// reach the switch that has the word boundaries, `\x` and backreferences
801 /// in it. That is why `\d` is the digit class rather than backreference
802 /// number thirteen, and it is why `\n` is a newline rather than the letter.
803 fn escape(&mut self) -> Result<Ast, Error> {
804 let b = self.peek().ok_or(Error::TrailingBackslash)?;
805 if let Some(node) = self.macro_for(b) {
806 self.at += 1;
807 return Ok(node);
808 }
809 self.at += 1;
810 match b {
811 b'b' => Ok(Ast::Assert(Assert::Word(true))),
812 b'B' => Ok(Ast::Assert(Assert::Word(false))),
813 b'<' => Ok(Ast::Assert(Assert::StartOfWord)),
814 b'>' => Ok(Ast::Assert(Assert::EndOfWord)),
815 b'x' => self.hex(),
816 // A digit is a backreference, which needs the engine to remember
817 // what a group matched and a set of live states cannot. Note it and
818 // carry on: whether it is refused, and with which of two sentences,
819 // is decided once the pattern has been read to the end.
820 b'0'..=b'9' => {
821 let n = u32::from(b - b'0');
822 self.backref = Some(self.backref.map_or(n, |m| m.max(n)));
823 Ok(Ast::Empty)
824 }
825 // Anything else is the byte itself, so `\.` is a dot and `\\` is a
826 // backslash. Not folded: see `raw`.
827 _ => Ok(Ast::Class(raw(b))),
828 }
829 }
830
831 /// TRE's macro table, from `tre_macros` in `deps/tre/lib/tre-parse.c`.
832 ///
833 /// Six of them are a control byte by another name and six are a character
834 /// class. TRE writes them out as source and parses that, so `\w` is
835 /// `[[:alnum:]_]` down to how a negation and NOCASE interact; building the
836 /// same byte set directly gets to the same place without a second parse.
837 fn macro_for(&self, b: u8) -> Option<Ast> {
838 let byte = |v: u8| Some(Ast::Class(raw(v)));
839 let class = |keep: fn(u8) -> bool, negate: bool| {
840 let mut c = Class::empty();
841 for x in 0..=255u8 {
842 if keep(x) {
843 c.set(x);
844 }
845 }
846 if negate {
847 c.negate();
848 }
849 Some(Ast::Class(c))
850 };
851 // A space in TRE's `[[:space:]]` is the C locale's, which includes the
852 // vertical tab, so this is the same set the named class builds.
853 let space = |x: u8| x.is_ascii_whitespace() || x == 0x0b;
854 let word = |x: u8| x.is_ascii_alphanumeric() || x == b'_';
855 match b {
856 b't' => byte(b'\t'),
857 b'n' => byte(b'\n'),
858 b'r' => byte(b'\r'),
859 b'f' => byte(0x0c),
860 b'a' => byte(0x07),
861 b'e' => byte(0x1b),
862 b'w' => class(word, false),
863 b'W' => class(word, true),
864 b's' => class(space, false),
865 b'S' => class(space, true),
866 b'd' => class(|x| x.is_ascii_digit(), false),
867 b'D' => class(|x| x.is_ascii_digit(), true),
868 _ => None,
869 }
870 }
871
872 /// `\xNN` or `\x{NNNN}`, with the `x` already eaten.
873 ///
874 /// The braced form is a whole code point in TRE and this engine is bytes,
875 /// so anything past 255 is a class with nothing in it, which is what a byte
876 /// build of TRE ends up matching against: nothing. A bare `\x` at the end
877 /// of the pattern is a NUL, which is TRE's `tre_ast_new_literal(mem, 0, 0)`
878 /// rather than an error.
879 fn hex(&mut self) -> Result<Ast, Error> {
880 let one = |v: u32| {
881 let mut c = Class::empty();
882 if v <= 255 {
883 c.set(v as u8);
884 }
885 c
886 };
887 if !self.eat(b'{') {
888 let mut v: u32 = 0;
889 for _ in 0..2 {
890 match self.peek().and_then(|b| (b as char).to_digit(16)) {
891 Some(d) => {
892 v = v * 16 + d;
893 self.at += 1;
894 }
895 None => break,
896 }
897 }
898 return Ok(Ast::Class(one(v)));
899 }
900 // TRE reads at most eight hex digits and anything that is not one, and
901 // is not the closing brace, ends the pattern rather than the number.
902 let mut v: u32 = 0;
903 let mut digits = 0;
904 loop {
905 match self.peek() {
906 Some(b'}') => {
907 self.at += 1;
908 return Ok(Ast::Class(one(v)));
909 }
910 Some(b) => match (b as char).to_digit(16) {
911 Some(d) if digits < 8 => {
912 v = v * 16 + d;
913 digits += 1;
914 self.at += 1;
915 }
916 // Past eight digits TRE stops storing but keeps reading,
917 // so the value is the first eight and the rest is skipped.
918 Some(_) => self.at += 1,
919 None => return Err(Error::MissingBrace),
920 },
921 None => return Err(Error::MissingBrace),
922 }
923 }
924 }
925
926 /// A bracket expression, with the `[` already eaten.
927 ///
928 /// The rules are all about position rather than about escaping: a `]` first
929 /// is a literal, a `^` first negates, a `-` first or last is a literal, and
930 /// a backslash is a backslash rather than an escape. That last one is what
931 /// catches people, and it is what TRE does.
932 ///
933 /// The order the three item shapes are tried in matters, because a range is
934 /// looked for before anything else. That is why `[]-a]` is the range from
935 /// `]` to `a` and not an empty expression, and why `[a-[:x:]]` is a range
936 /// whose ends are the wrong way round rather than a class.
937 fn bracket(&mut self) -> Result<Ast, Error> {
938 let mut class = Class::empty();
939 let negate = self.eat(b'^');
940 let first = self.at;
941 loop {
942 let b = self.peek().ok_or(Error::MissingBracket)?;
943 if b == b']' && self.at > first {
944 self.at += 1;
945 break;
946 }
947 // A range needs a `-` and something after it that is not the `]`
948 // closing the expression, so `[a-]` is an a and a dash.
949 let dash = self.pat.get(self.at + 1) == Some(&b'-');
950 let hi = self.pat.get(self.at + 2).copied();
951 if dash && hi.is_some_and(|h| h != b']') {
952 let hi = hi.expect("checked");
953 if b > hi {
954 return Err(Error::BadRange);
955 }
956 class.set_range(b, hi);
957 self.at += 3;
958 continue;
959 }
960 if b == b'[' {
961 match self.pat.get(self.at + 1) {
962 Some(b'.') | Some(b'=') => return Err(Error::Collate),
963 Some(b':') => {
964 self.named_class(&mut class)?;
965 continue;
966 }
967 _ => {}
968 }
969 }
970 // A dash that is not the first item and could have opened a range
971 // has already had its left end taken by the range before it, and
972 // TRE's own comment for this is that two ranges are not allowed to
973 // share an endpoint. So `[a-c-e]` is refused while `[a-c-]` is not.
974 if b == b'-'
975 && self.at != first
976 && self.pat.get(self.at + 1).is_some_and(|&n| n != b']')
977 {
978 return Err(Error::BadRange);
979 }
980 class.set(b);
981 self.at += 1;
982 }
983 if self.nocase {
984 class.fold_case();
985 }
986 if negate {
987 class.negate();
988 }
989 Ok(Ast::Class(class))
990 }
991
992 /// `[:name:]` inside a bracket expression, with the `[` at the cursor.
993 fn named_class(&mut self, class: &mut Class) -> Result<(), Error> {
994 let start = self.at + 2;
995 let mut end = start;
996 while end < self.pat.len() && self.pat[end] != b':' {
997 end += 1;
998 }
999 if end + 1 >= self.pat.len() || self.pat[end + 1] != b']' {
1000 return Err(Error::CharClass);
1001 }
1002 let name = &self.pat[start..end];
1003 let keep: fn(u8) -> bool = match name {
1004 b"alnum" => |b| b.is_ascii_alphanumeric(),
1005 b"alpha" => |b| b.is_ascii_alphabetic(),
1006 // No `blank`. TRE has eleven classes and that is not one of them,
1007 // so `[[:blank:]]` is an unknown class name rather than a space and
1008 // a tab.
1009 b"cntrl" => |b| b.is_ascii_control(),
1010 b"digit" => |b| b.is_ascii_digit(),
1011 b"graph" => |b| b.is_ascii_graphic(),
1012 b"lower" => |b| b.is_ascii_lowercase(),
1013 b"print" => |b| b.is_ascii_graphic() || b == b' ',
1014 b"punct" => |b| b.is_ascii_punctuation(),
1015 b"space" => |b| b.is_ascii_whitespace() || b == 0x0b,
1016 b"upper" => |b| b.is_ascii_uppercase(),
1017 b"xdigit" => |b| b.is_ascii_hexdigit(),
1018 _ => return Err(Error::CharClass),
1019 };
1020 for b in 0..=255u8 {
1021 if keep(b) {
1022 class.set(b);
1023 }
1024 }
1025 self.at = end + 2;
1026 Ok(())
1027 }
1028}
1029
1030// ---------------------------------------------------------------------------
1031// Compiling
1032// ---------------------------------------------------------------------------
1033
1034struct Compiler {
1035 prog: Vec<Inst>,
1036 classes: Vec<Class>,
1037}
1038
1039/// Whether the node has a path through it that consumes no bytes.
1040fn matches_empty(ast: &Ast) -> bool {
1041 match ast {
1042 Ast::Empty | Ast::Assert(_) => true,
1043 Ast::Class(_) => false,
1044 Ast::Concat(parts) => parts.iter().all(matches_empty),
1045 Ast::Alt(arms) => arms.iter().any(matches_empty),
1046 Ast::Repeat(inner, min, _) => *min == 0 || matches_empty(inner),
1047 }
1048}
1049
1050impl Compiler {
1051 fn push(&mut self, i: Inst) -> Result<u32, Error> {
1052 if self.prog.len() >= PROG_MAX {
1053 return Err(Error::Space);
1054 }
1055 self.prog.push(i);
1056 Ok(self.prog.len() as u32 - 1)
1057 }
1058
1059 fn here(&self) -> u32 {
1060 self.prog.len() as u32
1061 }
1062
1063 fn class(&mut self, c: Class) -> Result<(), Error> {
1064 // The same class twice is one entry, which matters for `{n,m}` because
1065 // the expansion emits the same subtree over and over.
1066 let idx = match self.classes.iter().position(|&e| e == c) {
1067 Some(i) => i as u32,
1068 None => {
1069 self.classes.push(c);
1070 self.classes.len() as u32 - 1
1071 }
1072 };
1073 self.push(Inst::Class(idx))?;
1074 Ok(())
1075 }
1076
1077 fn node(&mut self, ast: &Ast) -> Result<(), Error> {
1078 match ast {
1079 Ast::Empty => Ok(()),
1080 Ast::Class(c) => self.class(*c),
1081 Ast::Assert(a) => {
1082 self.push(Inst::Assert(*a))?;
1083 Ok(())
1084 }
1085 Ast::Concat(parts) => {
1086 for p in parts {
1087 self.node(p)?;
1088 }
1089 Ok(())
1090 }
1091 Ast::Alt(arms) => self.alt(arms),
1092 Ast::Repeat(inner, min, max) => self.repeat(inner, *min, *max),
1093 }
1094 }
1095
1096 /// `a|b|c` as a chain of splits, each arm jumping to the same place after.
1097 fn alt(&mut self, arms: &[Ast]) -> Result<(), Error> {
1098 let mut ends = Vec::with_capacity(arms.len());
1099 for (i, arm) in arms.iter().enumerate() {
1100 if i + 1 == arms.len() {
1101 self.node(arm)?;
1102 break;
1103 }
1104 let split = self.push(Inst::Split(0, 0))?;
1105 let first = self.here();
1106 self.node(arm)?;
1107 ends.push(self.push(Inst::Jump(0))?);
1108 let second = self.here();
1109 self.prog[split as usize] = Inst::Split(first, second);
1110 }
1111 let after = self.here();
1112 for j in ends {
1113 self.prog[j as usize] = Inst::Jump(after);
1114 }
1115 Ok(())
1116 }
1117
1118 /// A repetition, by emitting the subtree as many times as it can run.
1119 ///
1120 /// `a{2,4}` becomes `aa a? a?`, which is the same language: concatenation is
1121 /// contiguous, so a skipped optional cannot be made up by a later one.
1122 /// `a{2,}` becomes `aa a*`. This is why `PROG_MAX` exists.
1123 fn repeat(&mut self, inner: &Ast, min: u32, max: Option<u32>) -> Result<(), Error> {
1124 // A body that can match the empty string always runs at least once in
1125 // TRE, because its assertions sit on the transitions the skip would go
1126 // through. For a body with no assertions that changes nothing, since
1127 // the extra pass can match nothing. For one with them it is the whole
1128 // difference: `^*a` does not match "*a" and `x\b?y` does not match
1129 // "xy". The one exception is `{0}`, which TRE turns into an explicit
1130 // empty node that throws the operand away, and which lands in the
1131 // `Some(0)` arm below having emitted nothing at all.
1132 let min = if min == 0 && max != Some(0) && matches_empty(inner) {
1133 1
1134 } else {
1135 min
1136 };
1137 for _ in 0..min {
1138 self.node(inner)?;
1139 }
1140 match max {
1141 None => {
1142 // `x*`: split forwards or into the body, and loop back.
1143 let split = self.push(Inst::Split(0, 0))?;
1144 let body = self.here();
1145 self.node(inner)?;
1146 self.push(Inst::Jump(split))?;
1147 let after = self.here();
1148 self.prog[split as usize] = Inst::Split(body, after);
1149 Ok(())
1150 }
1151 Some(max) => {
1152 let mut splits = Vec::new();
1153 for _ in min..max {
1154 let split = self.push(Inst::Split(0, 0))?;
1155 let body = self.here();
1156 self.prog[split as usize] = Inst::Split(body, 0);
1157 splits.push(split);
1158 self.node(inner)?;
1159 }
1160 // Every optional copy skips to the same place, which is the end
1161 // of the last one.
1162 let after = self.here();
1163 for s in splits {
1164 let Inst::Split(body, _) = self.prog[s as usize] else {
1165 unreachable!("only splits were recorded")
1166 };
1167 self.prog[s as usize] = Inst::Split(body, after);
1168 }
1169 Ok(())
1170 }
1171 }
1172 }
1173}
1174
1175#[cfg(test)]
1176mod tests {
1177 use super::*;
1178
1179 fn hits(pattern: &str, subject: &str) -> bool {
1180 let re = Regex::new(pattern.as_bytes(), false).expect("compiles");
1181 Matcher::new().is_match(&re, subject.as_bytes())
1182 }
1183
1184 fn hits_nocase(pattern: &str, subject: &str) -> bool {
1185 let re = Regex::new(pattern.as_bytes(), true).expect("compiles");
1186 Matcher::new().is_match(&re, subject.as_bytes())
1187 }
1188
1189 fn refuses(pattern: &str) -> Error {
1190 Regex::new(pattern.as_bytes(), false).expect_err("refused")
1191 }
1192
1193 #[test]
1194 fn a_literal_matches_anywhere_in_the_subject() {
1195 assert!(hits("abc", "abc"));
1196 assert!(hits("abc", "xxabcxx"));
1197 assert!(!hits("abc", "ab"));
1198 assert!(hits("", ""));
1199 assert!(hits("", "anything"));
1200 }
1201
1202 #[test]
1203 fn the_anchors_are_the_ends_of_the_subject_and_not_of_a_line() {
1204 assert!(hits("^abc", "abcdef"));
1205 assert!(!hits("^abc", "xabcdef"));
1206 assert!(hits("abc$", "xxabc"));
1207 assert!(!hits("abc$", "abcx"));
1208 assert!(hits("^abc$", "abc"));
1209 assert!(!hits("^abc$", "abc\n"));
1210 // No REG_NEWLINE, so a newline is an ordinary byte and `^` does not
1211 // start again after it.
1212 assert!(!hits("^b", "a\nb"));
1213 assert!(hits(".", "\n"));
1214 }
1215
1216 #[test]
1217 fn the_three_unbounded_repetitions_do_what_they_say() {
1218 assert!(hits("^ab*c$", "ac"));
1219 assert!(hits("^ab*c$", "abbbbc"));
1220 assert!(!hits("^ab+c$", "ac"));
1221 assert!(hits("^ab+c$", "abc"));
1222 assert!(hits("^ab?c$", "ac"));
1223 assert!(hits("^ab?c$", "abc"));
1224 assert!(!hits("^ab?c$", "abbc"));
1225 // A repetition that can match nothing, which is the shape that loops
1226 // forever in an engine that does not mark states as already added.
1227 assert!(hits("^(a*)*$", ""));
1228 assert!(hits("^(a*)*$", "aaa"));
1229 }
1230
1231 #[test]
1232 fn a_bound_counts_and_refuses_what_it_cannot_count() {
1233 assert!(hits("^a{3}$", "aaa"));
1234 assert!(!hits("^a{3}$", "aa"));
1235 assert!(!hits("^a{3}$", "aaaa"));
1236 assert!(hits("^a{2,}$", "aaaaa"));
1237 assert!(!hits("^a{2,}$", "a"));
1238 assert!(hits("^a{2,4}$", "aa"));
1239 assert!(hits("^a{2,4}$", "aaaa"));
1240 assert!(!hits("^a{2,4}$", "aaaaa"));
1241 assert!(hits("^a{0,2}$", ""));
1242 assert_eq!(refuses("a{3,2}"), Error::BadBrace);
1243 assert_eq!(refuses("a{256}"), Error::BadMax);
1244 assert_eq!(refuses("a{2"), Error::MissingBrace);
1245 assert_eq!(refuses("a{x}"), Error::BadBrace);
1246 // In atom position a brace is just a brace.
1247 assert!(hits("^[{]a$", "{a"));
1248 }
1249
1250 #[test]
1251 fn alternation_tries_every_arm_and_an_empty_arm_is_an_arm() {
1252 assert!(hits("^(cat|dog|bird)$", "dog"));
1253 assert!(!hits("^(cat|dog|bird)$", "cow"));
1254 assert!(hits("^(ab|a)b$", "ab"));
1255 assert!(hits("^(a|)$", ""));
1256 assert!(hits("^()$", ""));
1257 assert!(hits("^a(b|c)*d$", "abcbcd"));
1258 }
1259
1260 #[test]
1261 fn a_bracket_expression_follows_position_rather_than_escaping() {
1262 assert!(hits("^[abc]$", "b"));
1263 assert!(!hits("^[abc]$", "d"));
1264 assert!(hits("^[^abc]$", "d"));
1265 assert!(!hits("^[^abc]$", "a"));
1266 assert!(hits("^[a-z]+$", "hello"));
1267 assert!(!hits("^[a-z]+$", "Hello"));
1268 // A `]` first is a literal, a `-` first or last is a literal.
1269 assert!(hits("^[]a]$", "]"));
1270 assert!(hits("^[-a]$", "-"));
1271 assert!(hits("^[a-]$", "-"));
1272 assert!(hits("^[^]]$", "x"));
1273 // A backslash inside brackets is a backslash, which is the one that
1274 // catches people coming from a Perl style engine.
1275 assert!(hits("^[\\]$", "\\"));
1276 assert_eq!(refuses("[abc"), Error::MissingBracket);
1277 assert_eq!(refuses("[z-a]"), Error::BadRange);
1278 assert_eq!(refuses("[[.a.]]"), Error::Collate);
1279 assert_eq!(refuses("[[=a=]]"), Error::Collate);
1280 }
1281
1282 #[test]
1283 fn the_named_classes_are_the_posix_ones() {
1284 assert!(hits("^[[:digit:]]+$", "12345"));
1285 assert!(!hits("^[[:digit:]]+$", "12a45"));
1286 assert!(hits("^[[:alpha:][:digit:]]+$", "ab12"));
1287 assert!(hits("^[[:space:]]$", "\t"));
1288 assert!(hits("^[^[:alpha:]]$", "1"));
1289 assert!(hits("^[[:xdigit:]]+$", "deadBEEF01"));
1290 assert_eq!(refuses("[[:nosuch:]]"), Error::CharClass);
1291 }
1292
1293 #[test]
1294 fn the_escapes_are_tres_and_a_macro_beats_the_switch() {
1295 assert!(hits("^a\\.c$", "a.c"));
1296 assert!(!hits("^a\\.c$", "abc"));
1297 assert!(hits("^a\\*$", "a*"));
1298 assert!(hits("^\\x41$", "A"));
1299 assert!(hits("^\\x{41}$", "A"));
1300 // Past a byte there is no byte to match, so the class is empty.
1301 assert!(!hits("\\x{100}", "\u{100}"));
1302 assert!(!hits("\\x{100}", "\0"));
1303 // The six control macros.
1304 assert!(hits("^\\n$", "\n"));
1305 assert!(!hits("^\\n$", "n"));
1306 assert!(hits("^\\t\\r\\f\\a\\e$", "\t\r\x0c\x07\x1b"));
1307 // The six class macros, which the table reaches before the switch does,
1308 // so `\d` is a digit rather than backreference thirteen.
1309 assert!(hits("^\\d+$", "42"));
1310 assert!(!hits("^\\d+$", "4a"));
1311 assert!(hits("^\\D$", "a"));
1312 assert!(hits("^\\w+$", "a_1"));
1313 assert!(!hits("^\\w+$", "a-1"));
1314 assert!(hits("^\\W$", "-"));
1315 assert!(hits("^\\s+$", " \t\n"));
1316 assert!(hits("^\\S$", "x"));
1317 // And a macro is one atom, so a repetition applies to the whole class.
1318 assert!(hits("^\\d{3}$", "123"));
1319 assert_eq!(refuses("a\\"), Error::TrailingBackslash);
1320 }
1321
1322 #[test]
1323 fn a_backreference_is_refused_with_one_of_two_sentences() {
1324 // Pointing at a group that is not there is TRE's own error. Pointing at
1325 // one that is there compiles in TRE and is refused a step later, and
1326 // that step is the one whose sentence this carries.
1327 assert_eq!(refuses("(a)\\1"), Error::Unsupported);
1328 assert_eq!(refuses("(a)(b)\\2"), Error::Unsupported);
1329 assert_eq!(refuses("\\0"), Error::Unsupported);
1330 assert_eq!(refuses("\\1"), Error::BackRef);
1331 assert_eq!(refuses("(a)\\2"), Error::BackRef);
1332 // A reference may point forwards, so this one is valid and therefore
1333 // gets the second sentence rather than the first.
1334 assert_eq!(refuses("\\1(a)"), Error::Unsupported);
1335 // Both answers wait for the whole parse, so a mistake anywhere else in
1336 // the pattern is reported instead.
1337 assert_eq!(refuses("((a)\\9"), Error::MissingParen);
1338 assert_eq!(refuses("\\1a{256}"), Error::BadMax);
1339 assert_eq!(
1340 Error::Unsupported.as_str(),
1341 "regular expression backreferences are not supported"
1342 );
1343 }
1344
1345 #[test]
1346 fn a_backslash_in_a_bracket_expression_is_not_an_escape() {
1347 // The macros are expanded in atom position only, so inside brackets a
1348 // backslash is a backslash and `\d` is the two bytes it looks like.
1349 assert!(hits("^[\\d]+$", "\\d"));
1350 assert!(!hits("^[\\d]+$", "42"));
1351 assert!(hits("^[\\n]+$", "\\n"));
1352 assert!(!hits("^[\\n]$", "\n"));
1353 }
1354
1355 #[test]
1356 fn the_word_boundaries_look_at_both_sides() {
1357 assert!(hits("\\bcat\\b", "the cat sat"));
1358 assert!(!hits("\\bcat\\b", "concatenate"));
1359 assert!(hits("\\Bcat\\B", "concatenate"));
1360 assert!(!hits("\\Bcat\\B", "the cat sat"));
1361 assert!(hits("\\<cat", "a cat"));
1362 assert!(!hits("\\<cat", "concat"));
1363 assert!(hits("cat\\>", "concat"));
1364 assert!(!hits("cat\\>", "cats"));
1365 // The two ends of the subject are a boundary to TRE whatever sits next
1366 // to them, so `\b` holds there and `\B` fails there even between two
1367 // bytes that are not word bytes at all.
1368 assert!(hits("\\b-", "-a"));
1369 assert!(!hits("\\B-", "-a"));
1370 assert!(hits("-\\b", "a-"));
1371 assert!(!hits("-\\B", "a-"));
1372 assert!(!hits("-\\b-", "---"));
1373 assert!(hits("-\\B-", "---"));
1374 // A nul byte reads as the end for the same reason, because TRE decides
1375 // by comparing the byte ahead against nul rather than by counting.
1376 assert!(hits("\0\\b\0", "\0\0\0"));
1377 assert!(!hits("\0\\B\0", "\0\0\0"));
1378 // `\<` and `\>` are the ordinary ones and do look at both sides.
1379 assert!(hits("\\>", "a"));
1380 assert!(!hits("\\>", "-"));
1381 assert!(hits("\\<", "a"));
1382 }
1383
1384 #[test]
1385 fn nocase_folds_the_class_and_not_the_subject() {
1386 assert!(hits_nocase("^abc$", "ABC"));
1387 assert!(hits_nocase("^[a-c]+$", "ABC"));
1388 assert!(hits_nocase("^[A-C]+$", "abc"));
1389 // The fold happens before the negation, so a negated class refuses
1390 // both cases rather than refusing one and taking the other.
1391 assert!(!hits_nocase("^[^a]$", "A"));
1392 assert!(hits_nocase("^[^a]$", "b"));
1393 assert!(!hits_nocase("^abc$", "abd"));
1394 // A byte an escape produced is not folded, because the fold sits in
1395 // the branch of TRE's parser that reads a plain byte and an escape
1396 // never goes through it. This is the one place the register calls out,
1397 // because Redis's literal fast path does fold it.
1398 assert!(!hits_nocase("\\x41.", "ab"));
1399 assert!(hits_nocase("\\x41.", "Ab"));
1400 assert!(!hits_nocase("\\x{41}.", "ab"));
1401 }
1402
1403 #[test]
1404 fn the_inline_flags_are_read_and_scoped_the_way_tre_scopes_them() {
1405 assert!(hits("(?i)abc", "ABC"));
1406 assert!(hits("(?i)ABC", "abc"));
1407 assert!(hits("(?i:a)b", "Ab"));
1408 assert!(!hits("(?i:a)b", "AB"));
1409 assert!(hits_nocase("(?-i)A", "A"));
1410 assert!(!hits_nocase("(?-i)A", "a"));
1411 // The rest of the enclosing expression is parsed under the new flags
1412 // as a whole, so this is `a` followed by `b|c` rather than `ab` or `c`.
1413 assert!(hits("a(?i)b|c", "ac"));
1414 assert!(!hits("a(?i)b|c", "c"));
1415 // `(?n)` is the only flag with a second effect, and only on the dot,
1416 // because the matcher reads the outer flags when it decides an anchor.
1417 assert!(!hits("(?n).", "\n"));
1418 assert!(hits("(?n).", "a"));
1419 assert!(!hits("(?n)^b", "a\nb"));
1420 // A comment is dropped and the letters that only pick between matches
1421 // are read and ignored.
1422 assert!(hits("(?#a comment)abc", "abc"));
1423 assert!(hits("(?U)a", "a"));
1424 assert!(hits("(?r)a", "a"));
1425 // Anything else is refused, including a truncated one.
1426 assert_eq!(refuses("(?x)a"), Error::BadPattern);
1427 assert_eq!(refuses("(?"), Error::BadPattern);
1428 assert_eq!(refuses("(?ia)"), Error::BadPattern);
1429 assert_eq!(refuses("(?#unterminated"), Error::BadPattern);
1430 }
1431
1432 #[test]
1433 fn an_operator_with_nothing_in_front_of_it_repeats_nothing() {
1434 assert_eq!(refuses("(abc"), Error::MissingParen);
1435 // A `)` with no `(` is a byte, so this is a pattern about three bytes
1436 // rather than a mistake.
1437 assert!(hits("^a)b$", "a)b"));
1438 assert!(!hits("^a)b$", "ab"));
1439 assert!(hits("^(a)b$", "ab"));
1440 // A leading operator repeats an atom that matches the empty string.
1441 assert!(hits("^*a$", "a"));
1442 assert!(!hits("^*a$", "*a"));
1443 assert!(hits("^+a$", "a"));
1444 assert!(hits("^?a$", "a"));
1445 assert!(hits("^{2}a$", "a"));
1446 assert!(!hits("^{2}a$", "aa"));
1447 assert!(hits("^{,3}a$", "a"));
1448 // A `{` in that position is still a bound and still has to parse.
1449 assert_eq!(refuses("^{$"), Error::BadBrace);
1450 assert_eq!(refuses("{256}"), Error::BadMax);
1451 assert_eq!(refuses("{3,2}"), Error::BadBrace);
1452 }
1453
1454 #[test]
1455 fn a_repetition_of_something_that_matches_nothing_still_runs_once() {
1456 // The body of these repetitions can only match the empty string, so a
1457 // pass through it costs nothing, and TRE takes that pass rather than
1458 // the skip. Every assertion in the body therefore stays mandatory.
1459 assert!(!hits("x\\b?y", "xy"));
1460 assert!(!hits("x\\b{0,3}y", "xy"));
1461 assert!(!hits("x(\\b)*y", "xy"));
1462 assert!(!hits("x\\b?y", "x-y"));
1463 assert!(!hits("(^|a)*b", "cb"));
1464 assert!(hits("(^|a)*b", "ab"));
1465 assert!(!hits("(\\b*)*x", "yx"));
1466 assert!(hits("(\\b*)*x", "y x"));
1467 // A body that can match the empty string without asserting anything is
1468 // unaffected, because the extra pass matches nothing.
1469 assert!(hits("(a|)*b", "b"));
1470 assert!(hits("(a*|^)*b", "cb"));
1471 assert!(hits("(|^)*b", "cb"));
1472 assert!(hits("(a?)*b", "cb"));
1473 // A body that cannot match the empty string keeps its skip.
1474 assert!(hits("(a\\b)*c", "c"));
1475 // `{0}` is the exception: TRE throws the operand away entirely, so the
1476 // anchor is gone rather than mandatory.
1477 assert!(hits("^{0}a$", "*a"));
1478 assert!(hits("^{0}a", "*a"));
1479 }
1480
1481 #[test]
1482 fn a_second_repetition_operator_is_reserved_and_refused() {
1483 assert_eq!(refuses("a**"), Error::BadRepeat);
1484 assert_eq!(refuses("a*+"), Error::BadRepeat);
1485 assert_eq!(refuses("a+*"), Error::BadRepeat);
1486 assert_eq!(refuses("a?*"), Error::BadRepeat);
1487 assert_eq!(refuses("a?+"), Error::BadRepeat);
1488 assert_eq!(refuses("a{2}*"), Error::BadRepeat);
1489 assert_eq!(refuses("a{2}+"), Error::BadRepeat);
1490 // A `?` is the exception. It asks for the shortest match rather than
1491 // the longest, which changes nothing about whether there is one.
1492 assert!(hits("^a*?$", ""));
1493 assert!(hits("^a??$", ""));
1494 assert!(hits("^a{2}?$", "aa"));
1495 // A bound after anything is a repetition of a repetition, not a second
1496 // operator, so it counts rather than being refused.
1497 assert!(hits("^a{2}{3}$", "aaaaaa"));
1498 assert!(!hits("^a{2}{3}$", "aa"));
1499 assert!(hits("^a*{2}$", "aa"));
1500 assert!(hits("^a{1,2}{1,2}$", "aaaa"));
1501 }
1502
1503 #[test]
1504 fn nothing_a_pattern_can_do_makes_the_walk_more_than_linear() {
1505 // The shape that is exponential in a backtracking engine. If this ever
1506 // stops returning promptly, the simulation has grown a backtrack.
1507 let re = Regex::new(b"^(a+)+b$", false).expect("compiles");
1508 let mut m = Matcher::new();
1509 let subject = vec![b'a'; 4096];
1510 assert!(!m.is_match(&re, &subject));
1511 assert!(m.is_match(&re, b"aaaab"));
1512 }
1513
1514 #[test]
1515 fn a_pattern_that_would_compile_to_too_much_is_refused_rather_than_built() {
1516 // Each level multiplies, so three of them is sixteen million steps.
1517 assert_eq!(refuses("((a{255}){255}){255}"), Error::Space);
1518 // Deep nesting is refused before it reaches the parser's own stack.
1519 let deep = "(".repeat(200) + "a" + &")".repeat(200);
1520 assert_eq!(refuses(&deep), Error::Space);
1521 // And the thing just under the cap still compiles.
1522 assert!(Regex::new(b"(a{200}){200}", false).is_ok());
1523 }
1524
1525 #[test]
1526 fn one_matcher_serves_every_pattern_it_is_given() {
1527 // This is the shape ARGREP uses: several compiled patterns, one lot of
1528 // scratch, many subjects. The scratch grows to the largest program and
1529 // a smaller one afterwards must not read the leftovers as live states.
1530 let big = Regex::new(b"^(abc|def){2,8}$", false).expect("compiles");
1531 let small = Regex::new(b"^x$", false).expect("compiles");
1532 let mut m = Matcher::new();
1533 for _ in 0..4 {
1534 assert!(m.is_match(&big, b"abcdefabc"));
1535 assert!(m.is_match(&small, b"x"));
1536 assert!(!m.is_match(&small, b"y"));
1537 assert!(!m.is_match(&big, b"abcdefa"));
1538 }
1539 }
1540
1541 #[test]
1542 fn the_error_messages_are_the_ones_tre_would_have_printed() {
1543 assert_eq!(Error::MissingBracket.as_str(), "Missing ']'");
1544 assert_eq!(Error::MissingParen.as_str(), "Missing ')'");
1545 assert_eq!(Error::MissingBrace.as_str(), "Missing '}'");
1546 assert_eq!(Error::BadBrace.as_str(), "Invalid contents of {}");
1547 assert_eq!(Error::BadRange.as_str(), "Invalid character range");
1548 assert_eq!(Error::CharClass.as_str(), "Unknown character class name");
1549 assert_eq!(Error::Collate.as_str(), "Unknown collating element");
1550 assert_eq!(Error::TrailingBackslash.as_str(), "Trailing backslash");
1551 assert_eq!(
1552 Error::BadRepeat.as_str(),
1553 "Invalid use of repetition operators"
1554 );
1555 assert_eq!(
1556 Error::BadMax.as_str(),
1557 "Maximum repetition in {} larger than 255"
1558 );
1559 assert_eq!(Error::Space.as_str(), "Out of memory");
1560 assert_eq!(Error::BadPattern.as_str(), "Invalid regexp");
1561 assert_eq!(Error::BackRef.as_str(), "Invalid back reference");
1562 }
1563
1564 #[test]
1565 fn a_subject_is_bytes_and_not_text() {
1566 let re = Regex::new(b"^.{3}$", false).expect("compiles");
1567 let mut m = Matcher::new();
1568 // Three bytes of anything, including a NUL and the top of the range,
1569 // and a three byte character is three bytes rather than one.
1570 assert!(m.is_match(&re, &[0x00, 0xff, 0x80]));
1571 assert!(m.is_match(&re, "☃".as_bytes()));
1572 assert!(!m.is_match(&re, "ab".as_bytes()));
1573 let hi = Regex::new(&[b'^', 0xff, b'$'], false).expect("compiles");
1574 assert!(m.is_match(&hi, &[0xff]));
1575 assert!(!m.is_match(&hi, &[0xfe]));
1576 }
1577}