From 3a1b7bb54ce15953fa6e7f7d5c6b6029f23eef2e Mon Sep 17 00:00:00 2001 From: John Johansen Date: Fri, 9 Mar 2012 04:22:42 -0800 Subject: [PATCH] Fix infinite loop bug in normalization. There are some rare occassions, when lots of alternations are used that tree simplification can result in an expression of (E | (E | E)) or (E . (E . E)) where E is the epsnode both of these expressions will lead to an inifinite loop in normalize_tree as the epsnode test if ((&epsnode == t->child[dir]) && (&epsnode != t->child[!dir]) && dynamic_cast(t)) { and the tree node rotation test } else if ((dynamic_cast(t) && dynamic_cast(t->child[dir])) || (dynamic_cast(t) && dynamic_cast(t->child[dir]))) { end up undoing each others work, ie. eps flip rotate (E | (E | E)) --------> ((E | E) | E) -------> (E | (E | E)) Signed-off-by: John Johansen Acked-By: Steve Beattie --- parser/libapparmor_re/expr-tree.cc | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) 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) &&