Skip to content

Commit bedc221

Browse files
committed
Auto merge of rust-lang#370 - BurntSushi:ag-fix-358, r=BurntSushi
RegexSet: fix literal optimization bug When combining multiple regexes in a set where some are anchored and others aren't, it's possible to wind up in a situation where prefix scanning is used. This is bad, because it can lead to some of the anchored regexes matching where they shouldn't be allowed to match. As a result, we disable all literal optimizations for regex sets if *any* regex in the set is anchored. Fixes rust-lang#358
2 parents 8a1b2bb + be9653c commit bedc221

File tree

2 files changed

+12
-0
lines changed

2 files changed

+12
-0
lines changed

src/exec.rs

+11
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,9 @@ impl ExecBuilder {
210210
let mut prefixes = Some(Literals::empty());
211211
let mut suffixes = Some(Literals::empty());
212212
let mut bytes = false;
213+
let is_set = self.options.pats.len() > 1;
214+
// If we're compiling a regex set and that set has any anchored
215+
// expressions, then disable all literal optimizations.
213216
for pat in &self.options.pats {
214217
let parser =
215218
ExprBuilder::new()
@@ -227,6 +230,10 @@ impl ExecBuilder {
227230
// Partial anchors unfortunately make it hard to use prefixes,
228231
// so disable them.
229232
prefixes = None;
233+
} else if is_set && expr.is_anchored_start() {
234+
// Regex sets with anchors do not go well with literal
235+
// optimizations.
236+
prefixes = None;
230237
}
231238
prefixes = prefixes.and_then(|mut prefixes| {
232239
if !prefixes.union_prefixes(&expr) {
@@ -240,6 +247,10 @@ impl ExecBuilder {
240247
// Partial anchors unfortunately make it hard to use suffixes,
241248
// so disable them.
242249
suffixes = None;
250+
} else if is_set && expr.is_anchored_end() {
251+
// Regex sets with anchors do not go well with literal
252+
// optimizations.
253+
prefixes = None;
243254
}
244255
suffixes = suffixes.and_then(|mut suffixes| {
245256
if !suffixes.union_suffixes(&expr) {

tests/set.rs

+1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ matset!(set18, &["a", "β"], "β", 1);
2020
nomatset!(nset1, &["a", "a"], "b");
2121
nomatset!(nset2, &["^foo", "bar$"], "bar foo");
2222
nomatset!(nset3, { let xs: &[&str] = &[]; xs }, "a");
23+
nomatset!(nset4, &[r"^rooted$", r"\.log$"], "notrooted");
2324

2425
// See: https://github.com/rust-lang/regex/issues/187
2526
#[test]

0 commit comments

Comments
 (0)