From ca3ca77fc9e497ff5048a9f1ee0d1acc8e050f51 Mon Sep 17 00:00:00 2001 From: Jim Meyering Date: Tue, 29 Nov 2016 10:45:46 -0800 Subject: [PATCH] dfa: avoid new infinite loop This would infloop: echo cx | LC_ALL=C grep -E 'c\b[x ]' * lib/dfa.c (dfastate): When constructing a new state table, we could initially declare that we had found a match, and later find that constraints eliminate that possibility, yet continue to use the now stale "matched" indicator. That would lead to an infinite loop. The solution is to update "matched" when necessary. Introduced by commit v0.1-983-g403adf1. --- ChangeLog | 11 +++++++++++ lib/dfa.c | 6 ++++++ 2 files changed, 17 insertions(+) diff --git a/ChangeLog b/ChangeLog index fd062ae..3b18083 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2016-11-29 Jim Meyering + + dfa: avoid new infinite loop + This would infloop: echo cx | LC_ALL=C grep -E 'c\b[x ]' + * lib/dfa.c (dfastate): When constructing a new state table, we could + initially declare that we had found a match, and later find that + constraints eliminate that possibility, yet continue to use the + now stale "matched" indicator. That would lead to an infinite loop. + The solution is to update "matched" when necessary. + Introduced by commit v0.1-983-g403adf1. + 2016-11-27 Norihiro Tanaka dfa: avoid match middle in multibyte character diff --git a/lib/dfa.c b/lib/dfa.c index 673ef95..0412b2c 100644 --- a/lib/dfa.c +++ b/lib/dfa.c @@ -2609,6 +2609,12 @@ dfastate (state_num s, struct dfa *d, unsigned char uc, state_num trans[]) continue; if (j == CHARCLASS_WORDS) continue; + + /* If we have reset the bit that made us declare "matched", reset + that indicator, too. This is required to avoid an infinite loop + with this command: echo cx | LC_ALL=C grep -E 'c\b[x ]' */ + if (!tstbit (uc, matches)) + matched = false; } #ifdef DEBUG -- 2.9.3