Skip to content

Commit

Permalink
syntax: fix overflow for big counted repetitions
Browse files Browse the repository at this point in the history
This fixes a bug where the calculation for the min/max length of a regex
could overflow if the counted repetitions in the pattern are big enough.
The panic only happens when debug assertions are enabled, which means
there is no panic by default in release mode.

One may wonder whether other bad things happen in release mode though,
since in that case, the arithmetic will wrap around instead. Since this
is in new code and since the regex crate doesn't yet utilize the min/max
attributes of an Hir, the wrap around in this case is completely
innocuous.

Fixes #995
  • Loading branch information
BurntSushi committed May 22, 2023
1 parent 65ec58c commit f9aec41
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 4 deletions.
16 changes: 12 additions & 4 deletions regex-syntax/src/hir/mod.rs
Expand Up @@ -2481,16 +2481,24 @@ impl Properties {
props.literal = props.literal && p.is_literal();
props.alternation_literal =
props.alternation_literal && p.is_alternation_literal();
if let Some(ref mut minimum_len) = props.minimum_len {
if let Some(minimum_len) = props.minimum_len {
match p.minimum_len() {
None => props.minimum_len = None,
Some(len) => *minimum_len += len,
Some(len) => {
// We use saturating arithmetic here because the
// minimum is just a lower bound. We can't go any
// higher than what our number types permit.
props.minimum_len =
Some(minimum_len.saturating_add(len));
}
}
}
if let Some(ref mut maximum_len) = props.maximum_len {
if let Some(maximum_len) = props.maximum_len {
match p.maximum_len() {
None => props.maximum_len = None,
Some(len) => *maximum_len += len,
Some(len) => {
props.maximum_len = maximum_len.checked_add(len)
}
}
}
}
Expand Down
8 changes: 8 additions & 0 deletions tests/regression.rs
Expand Up @@ -240,3 +240,11 @@ fn regression_unicode_perl_not_enabled() {
let re = regex_new!(pat);
assert!(re.is_ok());
}

// See: https://github.com/rust-lang/regex/issues/995
#[test]
fn regression_big_regex_overflow() {
let pat = r" {2147483516}{2147483416}{5}";
let re = regex_new!(pat);
assert!(re.is_err());
}

0 comments on commit f9aec41

Please sign in to comment.