2
0
mirror of https://gitlab.com/apparmor/apparmor synced 2025-08-22 01:57:43 +00:00

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<TwoChildNode *>(t)) {

and the tree node rotation test
    	} else if ((dynamic_cast<AltNode *>(t) &&
	           dynamic_cast<AltNode *>(t->child[dir])) ||
		   			   (dynamic_cast<CatNode *>(t) &&
					   			    dynamic_cast<CatNode *>(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 <john.johansen@canonical.com>
Acked-By: Steve Beattie <sbeattie@ubuntu.com>
This commit is contained in:
John Johansen 2012-03-09 04:22:42 -08:00
parent 04ef92ca94
commit 3a1b7bb54c

View File

@ -187,14 +187,22 @@ void normalize_tree(Node *t, int dir)
return;
for (;;) {
if ((&epsnode == t->child[dir]) &&
(&epsnode != t->child[!dir]) &&
dynamic_cast<TwoChildNode *>(t)) {
if (dynamic_cast<TwoChildNode *>(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<TwoChildNode *>(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<AltNode *>(t) &&