diff --git a/parser/libapparmor_re/expr-tree.cc b/parser/libapparmor_re/expr-tree.cc index cf6f2d608..a8938ef7f 100644 --- a/parser/libapparmor_re/expr-tree.cc +++ b/parser/libapparmor_re/expr-tree.cc @@ -187,14 +187,22 @@ void normalize_tree(Node *t, int dir) return; for (;;) { - if ((&epsnode == t->child[dir]) && - (&epsnode != t->child[!dir]) && - dynamic_cast(t)) { + if (dynamic_cast(t) && + (&epsnode == t->child[dir]) && + (&epsnode != t->child[!dir])) { // (E | a) -> (a | E) // Ea -> aE - Node *c = t->child[dir]; - t->child[dir] = t->child[!dir]; - t->child[!dir] = c; + // Test for E | (E | E) and E . (E . E) which will + // result in an infinite loop + Node *c = t->child[!dir]; + if (dynamic_cast(c) && + &epsnode == c->child[dir] && + &epsnode == c->child[!dir]) { + c->release(); + c = &epsnode; + } + t->child[dir] = c; + t->child[!dir] = &epsnode; // Don't break here as 'a' may be a tree that // can be pulled up. } else if ((dynamic_cast(t) &&