diff --git a/parser/libapparmor_re/aare_rules.cc b/parser/libapparmor_re/aare_rules.cc index 4bf38f71d..02aa80fa0 100644 --- a/parser/libapparmor_re/aare_rules.cc +++ b/parser/libapparmor_re/aare_rules.cc @@ -63,7 +63,7 @@ void aare_rules::add_to_rules(Node *tree, Node *perms) static Node *cat_with_null_seperator(Node *l, Node *r) { - return new CatNode(new CatNode(l, new CharSetNode(0)), r); + return new CatNode(new CatNode(l, new CharNode(0)), r); } bool aare_rules::add_rule_vec(int deny, uint32_t perms, uint32_t audit, diff --git a/parser/libapparmor_re/expr-tree.cc b/parser/libapparmor_re/expr-tree.cc index c7e4b6e54..a80f9037f 100644 --- a/parser/libapparmor_re/expr-tree.cc +++ b/parser/libapparmor_re/expr-tree.cc @@ -232,6 +232,12 @@ void AltNode::normalize(int dir) } else if (dynamic_cast(child[dir])) { // (a | b) | c -> a | (b | c) rotate_node(this, dir); + } else if (dynamic_cast(child[dir]) && + dynamic_cast(child[!dir])) { + // [a] | b -> b | [a] + Node *c = child[dir]; + child[dir] = child[!dir]; + child[!dir] = c; } else { break; } @@ -246,77 +252,76 @@ void AltNode::normalize(int dir) //charset conversion is disabled for now, //it hinders tree optimization in some cases, so it need to be either //done post optimization, or have extra factoring rules added +#if 0 static Node *merge_charset(Node *a, Node *b) { - Chars *from = &dynamic_cast(b)->chars; - Chars *to = &dynamic_cast(a)->chars; - for (Chars::iterator i = from->begin(); i != from->end(); i++) - to->insert(*i); - b->release(); - return a; + if (dynamic_cast(a) && dynamic_cast(b)) { + Chars chars; + chars.insert(dynamic_cast(a)->c); + chars.insert(dynamic_cast(b)->c); + CharSetNode *n = new CharSetNode(chars); + return n; + } else if (dynamic_cast(a) && + dynamic_cast(b)) { + Chars *chars = &dynamic_cast(b)->chars; + chars->insert(dynamic_cast(a)->c); + return b; + } else if (dynamic_cast(a) && + dynamic_cast(b)) { + Chars *from = &dynamic_cast(a)->chars; + Chars *to = &dynamic_cast(b)->chars; + for (Chars::iterator i = from->begin(); i != from->end(); i++) + to->insert(*i); + return b; + } + //return ???; } -/* given a constructed alt vector do duplicate elimination and merging */ -eliminate_dups_and_merge(vector vec) { - std::sort(vec->begin(), vec->end(), ???); - - i = vec->begin(); - if (vec->begin()->is_charset()) { - for (j = i+1; *j->is_charset() && j != vec->end(); - j++) { - merge_charset(*i, *j); - *j = NULL; - merge_count++; +static Node *alt_to_charsets(Node *t, int dir) +{ +/* + Node *first = NULL; + Node *p = t; + Node *i = t; + for (;dynamic_cast(i);) { + if (dynamic_cast(i->child[dir]) || + dynamic_cast(i->child[dir])) { + if (!first) { + first = i; + p = i; + i = i->child[!dir]; + } else { + first->child[dir] = merge_charset(first->child[dir], + i->child[dir]); + p->child[!dir] = i->child[!dir]; + Node *tmp = i; + i = tmp->child[!dir]; + tmp->child[!dir] = NULL; + tmp->release(); + } + } else { + p = i; + i = i->child[!dir]; } - if (j != vec->end()) - i = j; } - - /* merged charsets, now eliminate other dups */ - for (j = i + 1; ??; ???) { - + // last altnode of chain check other dir as well + if (first && (dynamic_cast(i) || + dynamic_cast(i))) { + } +*/ + +/* + if (dynamic_cast(t->child[dir]) || + dynamic_cast(t->child[dir])) + char_test = true; + (char_test && + (dynamic_cast(i->child[dir]) || + dynamic_cast(i->child[dir])))) { +*/ + return t; } - -flatten_altnode(Node *t) { - - /* flatten tree */ - elimintated_alt_nodes++; - - eliminate_dups_and_merge(); -} - -flatten_catnode(Node *t) { - - /* flatten tree */ - eliminated_cat_nodes++; - - /* only elimination to be done is accept nodes */ -} - -factor() { - - factor everything from right, then left - - factor longest/most - look at both left and right, which is most? - to determine which dir to factor first - - ab | abc | abcd | abcde - - a (b | bc | bcd | bcde) - - a ( b (E | c | cd | cde)) - - a ( b (E | c (E | d | de)) - - a ( b (E | c (E | d (E | e)))) - - so once flattened, work top to bottom - - may actually want to flatten charsets into single chars in altnode - to make it easier to factor them - -} +#endif static Node *basic_alt_factor(Node *t, int dir) { @@ -330,13 +335,6 @@ static Node *basic_alt_factor(Node *t, int dir) t->release(); return tmp; } - if (dynamic_cast(t->child[dir]) && - dynamic_cast(t->child[!dir])) { - Node *res = merge_charset(t->child[dir], t->child[!dir]); - t->child[dir] = t->child[!dir] = NULL; - t->release(); - return res; - } // (ab) | (ac) -> a(b|c) if (dynamic_cast(t->child[dir]) && dynamic_cast(t->child[!dir]) && @@ -536,6 +534,8 @@ static void count_tree_nodes(Node *t, struct node_counts *counts) } else if (dynamic_cast(t)) { counts->star++; count_tree_nodes(t->child[0], counts); + } else if (dynamic_cast(t)) { + counts->charnode++; } else if (dynamic_cast(t)) { counts->any++; } else if (dynamic_cast(t)) { @@ -554,11 +554,11 @@ Node *simplify_tree(Node *t, dfaflags_t flags) bool update; if (flags & DFA_DUMP_TREE_STATS) { - struct node_counts counts = { 0, 0, 0, 0, 0, 0, 0 }; + struct node_counts counts = { 0, 0, 0, 0, 0, 0, 0, 0 }; count_tree_nodes(t, &counts); fprintf(stderr, - "expr tree: [] %d, [^] %d, | %d, + %d, * %d, . %d, cat %d\n", - counts.charset, counts.notcharset, + "expr tree: c %d, [] %d, [^] %d, | %d, + %d, * %d, . %d, cat %d\n", + counts.charnode, counts.charset, counts.notcharset, counts.alt, counts.plus, counts.star, counts.any, counts.cat); } @@ -590,11 +590,11 @@ Node *simplify_tree(Node *t, dfaflags_t flags) } } while (update); if (flags & DFA_DUMP_TREE_STATS) { - struct node_counts counts = { 0, 0, 0, 0, 0, 0, 0 }; + struct node_counts counts = { 0, 0, 0, 0, 0, 0, 0, 0 }; count_tree_nodes(t, &counts); fprintf(stderr, - "simplified expr tree: [] %d, [^] %d, | %d, + %d, * %d, . %d, cat %d\n", - counts.charset, counts.notcharset, + "simplified expr tree: c %d, [] %d, [^] %d, | %d, + %d, * %d, . %d, cat %d\n", + counts.charnode, counts.charset, counts.notcharset, counts.alt, counts.plus, counts.star, counts.any, counts.cat); } diff --git a/parser/libapparmor_re/expr-tree.h b/parser/libapparmor_re/expr-tree.h index 80f29817d..afd426f51 100644 --- a/parser/libapparmor_re/expr-tree.h +++ b/parser/libapparmor_re/expr-tree.h @@ -229,11 +229,41 @@ public: int is_postprocess(void) { return false; } }; +/* Match one specific character (/c/). */ +class CharNode: public CNode { +public: + CharNode(uchar c): c(c) { } + void follow(Cases &cases) + { + NodeSet **x = &cases.cases[c]; + if (!*x) { + if (cases.otherwise) + *x = new NodeSet(*cases.otherwise); + else + *x = new NodeSet; + } + (*x)->insert(followpos.begin(), followpos.end()); + } + int eq(Node *other) + { + CharNode *o = dynamic_cast(other); + if (o) { + return c == o->c; + } + return 0; + } + ostream &dump(ostream &os) + { + return os << c; + } + + uchar c; +}; + /* Match a set of characters (/[abc]/). */ class CharSetNode: public CNode { public: CharSetNode(Chars &chars): chars(chars) { } - CharSetNode(uchar c): chars() { chars.insert(c); } void follow(Cases &cases) { for (Chars::iterator i = chars.begin(); i != chars.end(); i++) { @@ -561,6 +591,7 @@ public: }; struct node_counts { + int charnode; int charset; int notcharset; int alt; diff --git a/parser/libapparmor_re/parse.y b/parser/libapparmor_re/parse.y index 2a944c525..3ec07e12c 100644 --- a/parser/libapparmor_re/parse.y +++ b/parser/libapparmor_re/parse.y @@ -102,7 +102,7 @@ qterm : term ; term : '.' { $$ = new AnyCharNode; } - | regex_char { $$ = new CharSetNode($1); } + | regex_char { $$ = new CharNode($1); } | '[' charset ']' { $$ = new CharSetNode(*$2); delete $2; } | '[' '^' charset ']'