diff options
author | dgp <dgp@users.sourceforge.net> | 2007-11-15 22:01:03 (GMT) |
---|---|---|
committer | dgp <dgp@users.sourceforge.net> | 2007-11-15 22:01:03 (GMT) |
commit | cdb09f0ded89acc8b7a6b269f50fc8cd15da9739 (patch) | |
tree | d9b1b39a8a0517ecc9bbd810273e0cb13e7ca980 /generic/regc_nfa.c | |
parent | a4ad9e9083662f62f8f3df8f9901a114be5cbf24 (diff) | |
download | tcl-cdb09f0ded89acc8b7a6b269f50fc8cd15da9739.zip tcl-cdb09f0ded89acc8b7a6b269f50fc8cd15da9739.tar.gz tcl-cdb09f0ded89acc8b7a6b269f50fc8cd15da9739.tar.bz2 |
* generic/regc_nfa.c: Fixed infinite loop in the regexp compiler
* generic/regcomp.c: [Bug 1810038]. Corrected looping logic in
* tests/regexp.test: fixempties() to avoid wasting time walking a
list of dead states [Bug 1832612]. Convert optst() from expensive
no-op to a cheap no-op. Improve newline usage in debug output.
Diffstat (limited to 'generic/regc_nfa.c')
-rw-r--r-- | generic/regc_nfa.c | 46 |
1 files changed, 45 insertions, 1 deletions
diff --git a/generic/regc_nfa.c b/generic/regc_nfa.c index 9881cd4..dd26e64 100644 --- a/generic/regc_nfa.c +++ b/generic/regc_nfa.c @@ -803,6 +803,26 @@ struct arc *con; return 1; } + /* + * DGP 2007-11-15: Cloning a state with a circular constraint on its + * list of outs can lead to trouble [Bug 1810038], so get rid of them + * first. + */ + + for (a = from->outs; a != NULL; a = nexta) { + nexta = a->outchain; + switch (a->type) { + case '^': + case '$': + case BEHIND: + case AHEAD: + if (from == a->to) { + freearc(nfa, a); + } + break; + } + } + /* first, clone from state if necessary to avoid other outarcs */ if (from->nouts > 1) { s = newstate(nfa); @@ -921,6 +941,29 @@ struct arc *con; return 1; } + /* + * DGP 2007-11-15: Here we duplicate the same protections as appear + * in pull() above to avoid troubles with cloning a state with a + * circular constraint on its list of ins. It is not clear whether + * this is necessary, or is protecting against a "can't happen". + * Any test case that actually leads to a freearc() call here would + * be a welcome addition to the test suite. + */ + + for (a = to->ins; a != NULL; a = nexta) { + nexta = a->inchain; + switch (a->type) { + case '^': + case '$': + case BEHIND: + case AHEAD: + if (a->from == to) { + freearc(nfa, a); + } + break; + } + } + /* first, clone to state if necessary to avoid other inarcs */ if (to->nins > 1) { s = newstate(nfa); @@ -1041,7 +1084,8 @@ FILE *f; /* for debug output; NULL none */ /* find and eliminate empties until there are no more */ do { progress = 0; - for (s = nfa->states; s != NULL && !NISERR(); s = nexts) { + for (s = nfa->states; s != NULL && !NISERR() + && s->no != FREESTATE; s = nexts) { nexts = s->next; for (a = s->outs; a != NULL && !NISERR(); a = nexta) { nexta = a->outchain; |