mirror of
https://gitlab.com/apparmor/apparmor
synced 2025-08-28 21:07:56 +00:00
parser: replace dynamic_cast with is_type method
The dynamic_cast operator is slow as it needs to look at RTTI information and even does some string comparisons, especially in deep hierarchies like the one for Node. Profiling with callgrind showed that dynamic_cast can eat a huge portion of the running time, as it takes most of the time that is spent in the simplify_tree() function. For some complex profiles, the number of calls to dynamic_cast can be in the range of millions. This commit replaces the use of dynamic_cast in the Node hierarchy with a method called is_type(), which returns true if the pointer can be casted to the specified type. It works by looking at a Node object field that is an integer with bits set for each type up in the hierarchy. Therefore, dynamic_cast is replaced by a simple bits operation. This change can reduce the compilation times for some profiles more that 50%, especially in arm/arm64 arch. This opens the door to maybe avoid "-O no-expr-simplify" in the snapd daemon, as now that option would make the compilation slower in almost all cases. This is the example profile used in some of my tests, with this change the run-time is around 1/3 of what it was before on an x86 laptop: profile "test" (attach_disconnected,mediate_deleted) { dbus send bus={fcitx,session} path=/inputcontext_[0-9]* interface=org.fcitx.Fcitx.InputContext member="{Close,Destroy,Enable}IC" peer=(label=unconfined), dbus send bus={fcitx,session} path=/inputcontext_[0-9]* interface=org.fcitx.Fcitx.InputContext member=Reset peer=(label=unconfined), dbus receive bus=fcitx peer=(label=unconfined), dbus receive bus=session interface=org.fcitx.Fcitx.* peer=(label=unconfined), dbus send bus={fcitx,session} path=/inputcontext_[0-9]* interface=org.fcitx.Fcitx.InputContext member="Focus{In,Out}" peer=(label=unconfined), dbus send bus={fcitx,session} path=/inputcontext_[0-9]* interface=org.fcitx.Fcitx.InputContext member="{CommitPreedit,Set*}" peer=(label=unconfined), dbus send bus={fcitx,session} path=/inputcontext_[0-9]* interface=org.fcitx.Fcitx.InputContext member="{MouseEvent,ProcessKeyEvent}" peer=(label=unconfined), dbus send bus={fcitx,session} path=/inputcontext_[0-9]* interface=org.freedesktop.DBus.Properties member=GetAll peer=(label=unconfined), dbus (send) bus=session path=/org/a11y/bus interface=org.a11y.Bus member=GetAddress peer=(label=unconfined), dbus (send) bus=session path=/org/a11y/bus interface=org.freedesktop.DBus.Properties member=Get{,All} peer=(label=unconfined), dbus (receive, send) bus=accessibility path=/org/a11y/atspi/** peer=(label=unconfined), dbus (send) bus=system path=/org/freedesktop/Accounts interface=org.freedesktop.DBus.Introspectable member=Introspect peer=(label=unconfined), dbus (send) bus=system path=/org/freedesktop/Accounts interface=org.freedesktop.Accounts member=FindUserById peer=(label=unconfined), dbus (receive, send) bus=system path=/org/freedesktop/Accounts/User[0-9]* interface=org.freedesktop.DBus.Properties member={Get,PropertiesChanged} peer=(label=unconfined), dbus (send) bus=session interface=org.gtk.Actions member=Changed peer=(name=org.freedesktop.DBus, label=unconfined), dbus (receive) bus=session interface=org.gtk.Actions member={Activate,DescribeAll,SetState} peer=(label=unconfined), dbus (receive) bus=session interface=org.gtk.Menus member={Start,End} peer=(label=unconfined), dbus (send) bus=session interface=org.gtk.Menus member=Changed peer=(name=org.freedesktop.DBus, label=unconfined), dbus (send) bus=session path="/com/ubuntu/MenuRegistrar" interface="com.ubuntu.MenuRegistrar" member="{Register,Unregister}{App,Surface}Menu" peer=(label=unconfined), }
This commit is contained in:
parent
ee5303c8a0
commit
5aab543a3b
@ -97,11 +97,11 @@ bool aare_rules::add_rule_vec(int deny, uint32_t perms, uint32_t audit,
|
|||||||
*/
|
*/
|
||||||
exact_match = 1;
|
exact_match = 1;
|
||||||
for (depth_first_traversal i(tree); i && exact_match; i++) {
|
for (depth_first_traversal i(tree); i && exact_match; i++) {
|
||||||
if (dynamic_cast<StarNode *>(*i) ||
|
if ((*i)->is_type(NODE_TYPE_STAR) ||
|
||||||
dynamic_cast<PlusNode *>(*i) ||
|
(*i)->is_type(NODE_TYPE_PLUS) ||
|
||||||
dynamic_cast<AnyCharNode *>(*i) ||
|
(*i)->is_type(NODE_TYPE_ANYCHAR) ||
|
||||||
dynamic_cast<CharSetNode *>(*i) ||
|
(*i)->is_type(NODE_TYPE_CHARSET) ||
|
||||||
dynamic_cast<NotCharSetNode *>(*i))
|
(*i)->is_type(NODE_TYPE_NOTCHARSET))
|
||||||
exact_match = 0;
|
exact_match = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -210,7 +210,7 @@ int TwoChildNode::normalize_eps(int dir)
|
|||||||
// Test for E | (E | E) and E . (E . E) which will
|
// Test for E | (E | E) and E . (E . E) which will
|
||||||
// result in an infinite loop
|
// result in an infinite loop
|
||||||
Node *c = child[!dir];
|
Node *c = child[!dir];
|
||||||
if (dynamic_cast<TwoChildNode *>(c) &&
|
if (c->is_type(NODE_TYPE_TWOCHILD) &&
|
||||||
&epsnode == c->child[dir] &&
|
&epsnode == c->child[dir] &&
|
||||||
&epsnode == c->child[!dir]) {
|
&epsnode == c->child[!dir]) {
|
||||||
c->release();
|
c->release();
|
||||||
@ -229,7 +229,7 @@ void CatNode::normalize(int dir)
|
|||||||
for (;;) {
|
for (;;) {
|
||||||
if (normalize_eps(dir)) {
|
if (normalize_eps(dir)) {
|
||||||
continue;
|
continue;
|
||||||
} else if (dynamic_cast<CatNode *>(child[dir])) {
|
} else if (child[dir]->is_type(NODE_TYPE_CAT)) {
|
||||||
// (ab)c -> a(bc)
|
// (ab)c -> a(bc)
|
||||||
rotate_node(this, dir);
|
rotate_node(this, dir);
|
||||||
} else {
|
} else {
|
||||||
@ -248,11 +248,11 @@ void AltNode::normalize(int dir)
|
|||||||
for (;;) {
|
for (;;) {
|
||||||
if (normalize_eps(dir)) {
|
if (normalize_eps(dir)) {
|
||||||
continue;
|
continue;
|
||||||
} else if (dynamic_cast<AltNode *>(child[dir])) {
|
} else if (child[dir]->is_type(NODE_TYPE_ALT)) {
|
||||||
// (a | b) | c -> a | (b | c)
|
// (a | b) | c -> a | (b | c)
|
||||||
rotate_node(this, dir);
|
rotate_node(this, dir);
|
||||||
} else if (dynamic_cast<CharSetNode *>(child[dir]) &&
|
} else if (child[dir]->is_type(NODE_TYPE_CHARSET) &&
|
||||||
dynamic_cast<CharNode *>(child[!dir])) {
|
child[!dir]->is_type(NODE_TYPE_CHAR)) {
|
||||||
// [a] | b -> b | [a]
|
// [a] | b -> b | [a]
|
||||||
Node *c = child[dir];
|
Node *c = child[dir];
|
||||||
child[dir] = child[!dir];
|
child[dir] = child[!dir];
|
||||||
@ -344,7 +344,7 @@ static Node *alt_to_charsets(Node *t, int dir)
|
|||||||
|
|
||||||
static Node *basic_alt_factor(Node *t, int dir)
|
static Node *basic_alt_factor(Node *t, int dir)
|
||||||
{
|
{
|
||||||
if (!dynamic_cast<AltNode *>(t))
|
if (!t->is_type(NODE_TYPE_ALT))
|
||||||
return t;
|
return t;
|
||||||
|
|
||||||
if (t->child[dir]->eq(t->child[!dir])) {
|
if (t->child[dir]->eq(t->child[!dir])) {
|
||||||
@ -355,8 +355,8 @@ static Node *basic_alt_factor(Node *t, int dir)
|
|||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
// (ab) | (ac) -> a(b|c)
|
// (ab) | (ac) -> a(b|c)
|
||||||
if (dynamic_cast<CatNode *>(t->child[dir]) &&
|
if (t->child[dir]->is_type(NODE_TYPE_CAT) &&
|
||||||
dynamic_cast<CatNode *>(t->child[!dir]) &&
|
t->child[!dir]->is_type(NODE_TYPE_CAT) &&
|
||||||
t->child[dir]->child[dir]->eq(t->child[!dir]->child[dir])) {
|
t->child[dir]->child[dir]->eq(t->child[!dir]->child[dir])) {
|
||||||
// (ab) | (ac) -> a(b|c)
|
// (ab) | (ac) -> a(b|c)
|
||||||
Node *left = t->child[dir];
|
Node *left = t->child[dir];
|
||||||
@ -369,7 +369,7 @@ static Node *basic_alt_factor(Node *t, int dir)
|
|||||||
return left;
|
return left;
|
||||||
}
|
}
|
||||||
// a | (ab) -> a (E | b) -> a (b | E)
|
// a | (ab) -> a (E | b) -> a (b | E)
|
||||||
if (dynamic_cast<CatNode *>(t->child[!dir]) &&
|
if (t->child[!dir]->is_type(NODE_TYPE_CAT) &&
|
||||||
t->child[dir]->eq(t->child[!dir]->child[dir])) {
|
t->child[dir]->eq(t->child[!dir]->child[dir])) {
|
||||||
Node *c = t->child[!dir];
|
Node *c = t->child[!dir];
|
||||||
t->child[dir]->release();
|
t->child[dir]->release();
|
||||||
@ -379,7 +379,7 @@ static Node *basic_alt_factor(Node *t, int dir)
|
|||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
// ab | (a) -> a (b | E)
|
// ab | (a) -> a (b | E)
|
||||||
if (dynamic_cast<CatNode *>(t->child[dir]) &&
|
if (t->child[dir]->is_type(NODE_TYPE_CAT) &&
|
||||||
t->child[dir]->child[dir]->eq(t->child[!dir])) {
|
t->child[dir]->child[dir]->eq(t->child[!dir])) {
|
||||||
Node *c = t->child[dir];
|
Node *c = t->child[dir];
|
||||||
t->child[!dir]->release();
|
t->child[!dir]->release();
|
||||||
@ -394,7 +394,7 @@ static Node *basic_alt_factor(Node *t, int dir)
|
|||||||
|
|
||||||
static Node *basic_simplify(Node *t, int dir)
|
static Node *basic_simplify(Node *t, int dir)
|
||||||
{
|
{
|
||||||
if (dynamic_cast<CatNode *>(t) && &epsnode == t->child[!dir]) {
|
if (t->is_type(NODE_TYPE_CAT) && &epsnode == t->child[!dir]) {
|
||||||
// aE -> a
|
// aE -> a
|
||||||
Node *tmp = t->child[dir];
|
Node *tmp = t->child[dir];
|
||||||
t->child[dir] = NULL;
|
t->child[dir] = NULL;
|
||||||
@ -419,7 +419,7 @@ static Node *basic_simplify(Node *t, int dir)
|
|||||||
*/
|
*/
|
||||||
Node *simplify_tree_base(Node *t, int dir, bool &mod)
|
Node *simplify_tree_base(Node *t, int dir, bool &mod)
|
||||||
{
|
{
|
||||||
if (dynamic_cast<ImportantNode *>(t))
|
if (t->is_type(NODE_TYPE_IMPORTANT))
|
||||||
return t;
|
return t;
|
||||||
|
|
||||||
for (int i = 0; i < 2; i++) {
|
for (int i = 0; i < 2; i++) {
|
||||||
@ -442,15 +442,15 @@ Node *simplify_tree_base(Node *t, int dir, bool &mod)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* all tests after this must meet 2 alt node condition */
|
/* all tests after this must meet 2 alt node condition */
|
||||||
if (!dynamic_cast<AltNode *>(t) ||
|
if (!t->is_type(NODE_TYPE_ALT) ||
|
||||||
!dynamic_cast<AltNode *>(t->child[!dir]))
|
!t->child[!dir]->is_type(NODE_TYPE_ALT))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// a | (a | b) -> (a | b)
|
// a | (a | b) -> (a | b)
|
||||||
// a | (b | (c | a)) -> (b | (c | a))
|
// a | (b | (c | a)) -> (b | (c | a))
|
||||||
Node *p = t;
|
Node *p = t;
|
||||||
Node *i = t->child[!dir];
|
Node *i = t->child[!dir];
|
||||||
for (; dynamic_cast<AltNode *>(i); p = i, i = i->child[!dir]) {
|
for (; i->is_type(NODE_TYPE_ALT); p = i, i = i->child[!dir]) {
|
||||||
if (t->child[dir]->eq(i->child[dir])) {
|
if (t->child[dir]->eq(i->child[dir])) {
|
||||||
Node *tmp = t->child[!dir];
|
Node *tmp = t->child[!dir];
|
||||||
t->child[!dir] = NULL;
|
t->child[!dir] = NULL;
|
||||||
@ -475,19 +475,19 @@ Node *simplify_tree_base(Node *t, int dir, bool &mod)
|
|||||||
int count = 0;
|
int count = 0;
|
||||||
Node *subject = t->child[dir];
|
Node *subject = t->child[dir];
|
||||||
Node *a = subject;
|
Node *a = subject;
|
||||||
if (dynamic_cast<CatNode *>(subject))
|
if (subject->is_type(NODE_TYPE_CAT))
|
||||||
a = subject->child[dir];
|
a = subject->child[dir];
|
||||||
|
|
||||||
for (pp = p = t, i = t->child[!dir];
|
for (pp = p = t, i = t->child[!dir];
|
||||||
dynamic_cast<AltNode *>(i);) {
|
i->is_type(NODE_TYPE_ALT);) {
|
||||||
if ((dynamic_cast<CatNode *>(i->child[dir]) &&
|
if ((i->child[dir]->is_type(NODE_TYPE_CAT) &&
|
||||||
a->eq(i->child[dir]->child[dir])) ||
|
a->eq(i->child[dir]->child[dir])) ||
|
||||||
(a->eq(i->child[dir]))) {
|
(a->eq(i->child[dir]))) {
|
||||||
// extract matching alt node
|
// extract matching alt node
|
||||||
p->child[!dir] = i->child[!dir];
|
p->child[!dir] = i->child[!dir];
|
||||||
i->child[!dir] = subject;
|
i->child[!dir] = subject;
|
||||||
subject = basic_simplify(i, dir);
|
subject = basic_simplify(i, dir);
|
||||||
if (dynamic_cast<CatNode *>(subject))
|
if (subject->is_type(NODE_TYPE_CAT))
|
||||||
a = subject->child[dir];
|
a = subject->child[dir];
|
||||||
else
|
else
|
||||||
a = subject;
|
a = subject;
|
||||||
@ -502,7 +502,7 @@ Node *simplify_tree_base(Node *t, int dir, bool &mod)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// last altnode in chain check other dir as well
|
// last altnode in chain check other dir as well
|
||||||
if ((dynamic_cast<CatNode *>(i) &&
|
if ((i->is_type(NODE_TYPE_CAT) &&
|
||||||
a->eq(i->child[dir])) || (a->eq(i))) {
|
a->eq(i->child[dir])) || (a->eq(i))) {
|
||||||
count++;
|
count++;
|
||||||
if (t == p) {
|
if (t == p) {
|
||||||
@ -528,7 +528,7 @@ int debug_tree(Node *t)
|
|||||||
{
|
{
|
||||||
int nodes = 1;
|
int nodes = 1;
|
||||||
|
|
||||||
if (!dynamic_cast<ImportantNode *>(t)) {
|
if (!t->is_type(NODE_TYPE_IMPORTANT)) {
|
||||||
if (t->child[0])
|
if (t->child[0])
|
||||||
nodes += debug_tree(t->child[0]);
|
nodes += debug_tree(t->child[0]);
|
||||||
if (t->child[1])
|
if (t->child[1])
|
||||||
@ -539,30 +539,30 @@ int debug_tree(Node *t)
|
|||||||
|
|
||||||
static void count_tree_nodes(Node *t, struct node_counts *counts)
|
static void count_tree_nodes(Node *t, struct node_counts *counts)
|
||||||
{
|
{
|
||||||
if (dynamic_cast<AltNode *>(t)) {
|
if (t->is_type(NODE_TYPE_ALT)) {
|
||||||
counts->alt++;
|
counts->alt++;
|
||||||
count_tree_nodes(t->child[0], counts);
|
count_tree_nodes(t->child[0], counts);
|
||||||
count_tree_nodes(t->child[1], counts);
|
count_tree_nodes(t->child[1], counts);
|
||||||
} else if (dynamic_cast<CatNode *>(t)) {
|
} else if (t->is_type(NODE_TYPE_CAT)) {
|
||||||
counts->cat++;
|
counts->cat++;
|
||||||
count_tree_nodes(t->child[0], counts);
|
count_tree_nodes(t->child[0], counts);
|
||||||
count_tree_nodes(t->child[1], counts);
|
count_tree_nodes(t->child[1], counts);
|
||||||
} else if (dynamic_cast<PlusNode *>(t)) {
|
} else if (t->is_type(NODE_TYPE_PLUS)) {
|
||||||
counts->plus++;
|
counts->plus++;
|
||||||
count_tree_nodes(t->child[0], counts);
|
count_tree_nodes(t->child[0], counts);
|
||||||
} else if (dynamic_cast<StarNode *>(t)) {
|
} else if (t->is_type(NODE_TYPE_STAR)) {
|
||||||
counts->star++;
|
counts->star++;
|
||||||
count_tree_nodes(t->child[0], counts);
|
count_tree_nodes(t->child[0], counts);
|
||||||
} else if (dynamic_cast<OptionalNode *>(t)) {
|
} else if (t->is_type(NODE_TYPE_OPTIONAL)) {
|
||||||
counts->optional++;
|
counts->optional++;
|
||||||
count_tree_nodes(t->child[0], counts);
|
count_tree_nodes(t->child[0], counts);
|
||||||
} else if (dynamic_cast<CharNode *>(t)) {
|
} else if (t->is_type(NODE_TYPE_CHAR)) {
|
||||||
counts->charnode++;
|
counts->charnode++;
|
||||||
} else if (dynamic_cast<AnyCharNode *>(t)) {
|
} else if (t->is_type(NODE_TYPE_ANYCHAR)) {
|
||||||
counts->any++;
|
counts->any++;
|
||||||
} else if (dynamic_cast<CharSetNode *>(t)) {
|
} else if (t->is_type(NODE_TYPE_CHARSET)) {
|
||||||
counts->charset++;
|
counts->charset++;
|
||||||
} else if (dynamic_cast<NotCharSetNode *>(t)) {
|
} else if (t->is_type(NODE_TYPE_NOTCHARSET)) {
|
||||||
counts->notcharset++;
|
counts->notcharset++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -635,7 +635,8 @@ Node *simplify_tree(Node *t, dfaflags_t flags)
|
|||||||
void flip_tree(Node *node)
|
void flip_tree(Node *node)
|
||||||
{
|
{
|
||||||
for (depth_first_traversal i(node); i; i++) {
|
for (depth_first_traversal i(node); i; i++) {
|
||||||
if (CatNode *cat = dynamic_cast<CatNode *>(*i)) {
|
if ((*i)->is_type(NODE_TYPE_CAT)) {
|
||||||
|
CatNode *cat = static_cast<CatNode *>(*i);
|
||||||
swap(cat->child[0], cat->child[1]);
|
swap(cat->child[0], cat->child[1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -222,16 +222,43 @@ typedef struct Cases {
|
|||||||
|
|
||||||
ostream &operator<<(ostream &os, Node &node);
|
ostream &operator<<(ostream &os, Node &node);
|
||||||
|
|
||||||
|
#define NODE_TYPE_NODE 0
|
||||||
|
#define NODE_TYPE_INNER (1 << 0)
|
||||||
|
#define NODE_TYPE_ONECHILD (1 << 1)
|
||||||
|
#define NODE_TYPE_TWOCHILD (1 << 2)
|
||||||
|
#define NODE_TYPE_LEAF (1 << 3)
|
||||||
|
#define NODE_TYPE_EPS (1 << 4)
|
||||||
|
#define NODE_TYPE_IMPORTANT (1 << 5)
|
||||||
|
#define NODE_TYPE_C (1 << 6)
|
||||||
|
#define NODE_TYPE_CHAR (1 << 7)
|
||||||
|
#define NODE_TYPE_CHARSET (1 << 8)
|
||||||
|
#define NODE_TYPE_NOTCHARSET (1 << 9)
|
||||||
|
#define NODE_TYPE_ANYCHAR (1 << 10)
|
||||||
|
#define NODE_TYPE_STAR (1 << 11)
|
||||||
|
#define NODE_TYPE_OPTIONAL (1 << 12)
|
||||||
|
#define NODE_TYPE_PLUS (1 << 13)
|
||||||
|
#define NODE_TYPE_CAT (1 << 14)
|
||||||
|
#define NODE_TYPE_ALT (1 << 15)
|
||||||
|
#define NODE_TYPE_SHARED (1 << 16)
|
||||||
|
#define NODE_TYPE_ACCEPT (1 << 17)
|
||||||
|
#define NODE_TYPE_MATCHFLAG (1 << 18)
|
||||||
|
#define NODE_TYPE_EXACTMATCHFLAG (1 << 19)
|
||||||
|
#define NODE_TYPE_DENYMATCHFLAG (1 << 20)
|
||||||
|
|
||||||
/* An abstract node in the syntax tree. */
|
/* An abstract node in the syntax tree. */
|
||||||
class Node {
|
class Node {
|
||||||
public:
|
public:
|
||||||
Node(): nullable(false), label(0) { child[0] = child[1] = 0; }
|
Node(): nullable(false), type_flags(NODE_TYPE_NODE), label(0)
|
||||||
Node(Node *left): nullable(false), label(0)
|
{
|
||||||
|
child[0] = child[1] = 0;
|
||||||
|
}
|
||||||
|
Node(Node *left): nullable(false), type_flags(NODE_TYPE_NODE), label(0)
|
||||||
{
|
{
|
||||||
child[0] = left;
|
child[0] = left;
|
||||||
child[1] = 0;
|
child[1] = 0;
|
||||||
}
|
}
|
||||||
Node(Node *left, Node *right): nullable(false), label(0)
|
Node(Node *left, Node *right): nullable(false),
|
||||||
|
type_flags(NODE_TYPE_NODE), label(0)
|
||||||
{
|
{
|
||||||
child[0] = left;
|
child[0] = left;
|
||||||
child[1] = right;
|
child[1] = right;
|
||||||
@ -302,6 +329,13 @@ public:
|
|||||||
NodeSet firstpos, lastpos, followpos;
|
NodeSet firstpos, lastpos, followpos;
|
||||||
/* child 0 is left, child 1 is right */
|
/* child 0 is left, child 1 is right */
|
||||||
Node *child[2];
|
Node *child[2];
|
||||||
|
/*
|
||||||
|
* Bitmap that stores supported pointer casts for the Node, composed
|
||||||
|
* by the NODE_TYPE_* flags. This is used by is_type() as a substitute
|
||||||
|
* of costly dynamic_cast calls.
|
||||||
|
*/
|
||||||
|
unsigned type_flags;
|
||||||
|
bool is_type(unsigned type) { return type_flags & type; }
|
||||||
|
|
||||||
unsigned int label; /* unique number for debug etc */
|
unsigned int label; /* unique number for debug etc */
|
||||||
/**
|
/**
|
||||||
@ -315,25 +349,34 @@ public:
|
|||||||
|
|
||||||
class InnerNode: public Node {
|
class InnerNode: public Node {
|
||||||
public:
|
public:
|
||||||
InnerNode(): Node() { };
|
InnerNode(): Node() { type_flags |= NODE_TYPE_INNER; };
|
||||||
InnerNode(Node *left): Node(left) { };
|
InnerNode(Node *left): Node(left) { type_flags |= NODE_TYPE_INNER; };
|
||||||
InnerNode(Node *left, Node *right): Node(left, right) { };
|
InnerNode(Node *left, Node *right): Node(left, right)
|
||||||
|
{
|
||||||
|
type_flags |= NODE_TYPE_INNER;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
class OneChildNode: public InnerNode {
|
class OneChildNode: public InnerNode {
|
||||||
public:
|
public:
|
||||||
OneChildNode(Node *left): InnerNode(left) { };
|
OneChildNode(Node *left): InnerNode(left)
|
||||||
|
{
|
||||||
|
type_flags |= NODE_TYPE_ONECHILD;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
class TwoChildNode: public InnerNode {
|
class TwoChildNode: public InnerNode {
|
||||||
public:
|
public:
|
||||||
TwoChildNode(Node *left, Node *right): InnerNode(left, right) { };
|
TwoChildNode(Node *left, Node *right): InnerNode(left, right)
|
||||||
|
{
|
||||||
|
type_flags |= NODE_TYPE_TWOCHILD;
|
||||||
|
};
|
||||||
virtual int normalize_eps(int dir);
|
virtual int normalize_eps(int dir);
|
||||||
};
|
};
|
||||||
|
|
||||||
class LeafNode: public Node {
|
class LeafNode: public Node {
|
||||||
public:
|
public:
|
||||||
LeafNode(): Node() { };
|
LeafNode(): Node() { type_flags |= NODE_TYPE_LEAF; };
|
||||||
virtual void normalize(int dir __attribute__((unused))) { return; }
|
virtual void normalize(int dir __attribute__((unused))) { return; }
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -342,6 +385,7 @@ class EpsNode: public LeafNode {
|
|||||||
public:
|
public:
|
||||||
EpsNode(): LeafNode()
|
EpsNode(): LeafNode()
|
||||||
{
|
{
|
||||||
|
type_flags |= NODE_TYPE_EPS;
|
||||||
nullable = true;
|
nullable = true;
|
||||||
label = 0;
|
label = 0;
|
||||||
}
|
}
|
||||||
@ -356,7 +400,7 @@ public:
|
|||||||
void compute_lastpos() { }
|
void compute_lastpos() { }
|
||||||
int eq(Node *other)
|
int eq(Node *other)
|
||||||
{
|
{
|
||||||
if (dynamic_cast<EpsNode *>(other))
|
if (other->is_type(NODE_TYPE_EPS))
|
||||||
return 1;
|
return 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -373,7 +417,7 @@ public:
|
|||||||
*/
|
*/
|
||||||
class ImportantNode: public LeafNode {
|
class ImportantNode: public LeafNode {
|
||||||
public:
|
public:
|
||||||
ImportantNode(): LeafNode() { }
|
ImportantNode(): LeafNode() { type_flags |= NODE_TYPE_IMPORTANT; }
|
||||||
void compute_firstpos() { firstpos.insert(this); }
|
void compute_firstpos() { firstpos.insert(this); }
|
||||||
void compute_lastpos() { lastpos.insert(this); }
|
void compute_lastpos() { lastpos.insert(this); }
|
||||||
virtual void follow(Cases &cases) = 0;
|
virtual void follow(Cases &cases) = 0;
|
||||||
@ -386,7 +430,7 @@ public:
|
|||||||
*/
|
*/
|
||||||
class CNode: public ImportantNode {
|
class CNode: public ImportantNode {
|
||||||
public:
|
public:
|
||||||
CNode(): ImportantNode() { }
|
CNode(): ImportantNode() { type_flags |= NODE_TYPE_C; }
|
||||||
int is_accept(void) { return false; }
|
int is_accept(void) { return false; }
|
||||||
int is_postprocess(void) { return false; }
|
int is_postprocess(void) { return false; }
|
||||||
};
|
};
|
||||||
@ -394,7 +438,7 @@ public:
|
|||||||
/* Match one specific character (/c/). */
|
/* Match one specific character (/c/). */
|
||||||
class CharNode: public CNode {
|
class CharNode: public CNode {
|
||||||
public:
|
public:
|
||||||
CharNode(transchar c): c(c) { }
|
CharNode(transchar c): c(c) { type_flags |= NODE_TYPE_CHAR; }
|
||||||
void follow(Cases &cases)
|
void follow(Cases &cases)
|
||||||
{
|
{
|
||||||
NodeSet **x = &cases.cases[c];
|
NodeSet **x = &cases.cases[c];
|
||||||
@ -408,8 +452,8 @@ public:
|
|||||||
}
|
}
|
||||||
int eq(Node *other)
|
int eq(Node *other)
|
||||||
{
|
{
|
||||||
CharNode *o = dynamic_cast<CharNode *>(other);
|
if (other->is_type(NODE_TYPE_CHAR)) {
|
||||||
if (o) {
|
CharNode *o = static_cast<CharNode *>(other);
|
||||||
return c == o->c;
|
return c == o->c;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@ -439,7 +483,10 @@ public:
|
|||||||
/* Match a set of characters (/[abc]/). */
|
/* Match a set of characters (/[abc]/). */
|
||||||
class CharSetNode: public CNode {
|
class CharSetNode: public CNode {
|
||||||
public:
|
public:
|
||||||
CharSetNode(Chars &chars): chars(chars) { }
|
CharSetNode(Chars &chars): chars(chars)
|
||||||
|
{
|
||||||
|
type_flags |= NODE_TYPE_CHARSET;
|
||||||
|
}
|
||||||
void follow(Cases &cases)
|
void follow(Cases &cases)
|
||||||
{
|
{
|
||||||
for (Chars::iterator i = chars.begin(); i != chars.end(); i++) {
|
for (Chars::iterator i = chars.begin(); i != chars.end(); i++) {
|
||||||
@ -455,8 +502,11 @@ public:
|
|||||||
}
|
}
|
||||||
int eq(Node *other)
|
int eq(Node *other)
|
||||||
{
|
{
|
||||||
CharSetNode *o = dynamic_cast<CharSetNode *>(other);
|
if (!other->is_type(NODE_TYPE_CHARSET))
|
||||||
if (!o || chars.size() != o->chars.size())
|
return 0;
|
||||||
|
|
||||||
|
CharSetNode *o = static_cast<CharSetNode *>(other);
|
||||||
|
if (chars.size() != o->chars.size())
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
for (Chars::iterator i = chars.begin(), j = o->chars.begin();
|
for (Chars::iterator i = chars.begin(), j = o->chars.begin();
|
||||||
@ -498,7 +548,10 @@ public:
|
|||||||
/* Match all except one character (/[^abc]/). */
|
/* Match all except one character (/[^abc]/). */
|
||||||
class NotCharSetNode: public CNode {
|
class NotCharSetNode: public CNode {
|
||||||
public:
|
public:
|
||||||
NotCharSetNode(Chars &chars): chars(chars) { }
|
NotCharSetNode(Chars &chars): chars(chars)
|
||||||
|
{
|
||||||
|
type_flags |= NODE_TYPE_NOTCHARSET;
|
||||||
|
}
|
||||||
void follow(Cases &cases)
|
void follow(Cases &cases)
|
||||||
{
|
{
|
||||||
if (!cases.otherwise)
|
if (!cases.otherwise)
|
||||||
@ -522,8 +575,11 @@ public:
|
|||||||
}
|
}
|
||||||
int eq(Node *other)
|
int eq(Node *other)
|
||||||
{
|
{
|
||||||
NotCharSetNode *o = dynamic_cast<NotCharSetNode *>(other);
|
if (!other->is_type(NODE_TYPE_NOTCHARSET))
|
||||||
if (!o || chars.size() != o->chars.size())
|
return 0;
|
||||||
|
|
||||||
|
NotCharSetNode *o = static_cast<NotCharSetNode *>(other);
|
||||||
|
if (chars.size() != o->chars.size())
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
for (Chars::iterator i = chars.begin(), j = o->chars.begin();
|
for (Chars::iterator i = chars.begin(), j = o->chars.begin();
|
||||||
@ -565,7 +621,7 @@ public:
|
|||||||
/* Match any character (/./). */
|
/* Match any character (/./). */
|
||||||
class AnyCharNode: public CNode {
|
class AnyCharNode: public CNode {
|
||||||
public:
|
public:
|
||||||
AnyCharNode() { }
|
AnyCharNode() { type_flags |= NODE_TYPE_ANYCHAR; }
|
||||||
void follow(Cases &cases)
|
void follow(Cases &cases)
|
||||||
{
|
{
|
||||||
if (!cases.otherwise)
|
if (!cases.otherwise)
|
||||||
@ -579,7 +635,7 @@ public:
|
|||||||
}
|
}
|
||||||
int eq(Node *other)
|
int eq(Node *other)
|
||||||
{
|
{
|
||||||
if (dynamic_cast<AnyCharNode *>(other))
|
if (other->is_type(NODE_TYPE_ANYCHAR))
|
||||||
return 1;
|
return 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -589,7 +645,11 @@ public:
|
|||||||
/* Match a node zero or more times. (This is a unary operator.) */
|
/* Match a node zero or more times. (This is a unary operator.) */
|
||||||
class StarNode: public OneChildNode {
|
class StarNode: public OneChildNode {
|
||||||
public:
|
public:
|
||||||
StarNode(Node *left): OneChildNode(left) { nullable = true; }
|
StarNode(Node *left): OneChildNode(left)
|
||||||
|
{
|
||||||
|
type_flags |= NODE_TYPE_STAR;
|
||||||
|
nullable = true;
|
||||||
|
}
|
||||||
void compute_firstpos() { firstpos = child[0]->firstpos; }
|
void compute_firstpos() { firstpos = child[0]->firstpos; }
|
||||||
void compute_lastpos() { lastpos = child[0]->lastpos; }
|
void compute_lastpos() { lastpos = child[0]->lastpos; }
|
||||||
void compute_followpos()
|
void compute_followpos()
|
||||||
@ -601,7 +661,7 @@ public:
|
|||||||
}
|
}
|
||||||
int eq(Node *other)
|
int eq(Node *other)
|
||||||
{
|
{
|
||||||
if (dynamic_cast<StarNode *>(other))
|
if (other->is_type(NODE_TYPE_STAR))
|
||||||
return child[0]->eq(other->child[0]);
|
return child[0]->eq(other->child[0]);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -618,12 +678,16 @@ public:
|
|||||||
/* Match a node zero or one times. */
|
/* Match a node zero or one times. */
|
||||||
class OptionalNode: public OneChildNode {
|
class OptionalNode: public OneChildNode {
|
||||||
public:
|
public:
|
||||||
OptionalNode(Node *left): OneChildNode(left) { nullable = true; }
|
OptionalNode(Node *left): OneChildNode(left)
|
||||||
|
{
|
||||||
|
type_flags |= NODE_TYPE_OPTIONAL;
|
||||||
|
nullable = true;
|
||||||
|
}
|
||||||
void compute_firstpos() { firstpos = child[0]->firstpos; }
|
void compute_firstpos() { firstpos = child[0]->firstpos; }
|
||||||
void compute_lastpos() { lastpos = child[0]->lastpos; }
|
void compute_lastpos() { lastpos = child[0]->lastpos; }
|
||||||
int eq(Node *other)
|
int eq(Node *other)
|
||||||
{
|
{
|
||||||
if (dynamic_cast<OptionalNode *>(other))
|
if (other->is_type(NODE_TYPE_OPTIONAL))
|
||||||
return child[0]->eq(other->child[0]);
|
return child[0]->eq(other->child[0]);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -638,7 +702,9 @@ public:
|
|||||||
/* Match a node one or more times. (This is a unary operator.) */
|
/* Match a node one or more times. (This is a unary operator.) */
|
||||||
class PlusNode: public OneChildNode {
|
class PlusNode: public OneChildNode {
|
||||||
public:
|
public:
|
||||||
PlusNode(Node *left): OneChildNode(left) {
|
PlusNode(Node *left): OneChildNode(left)
|
||||||
|
{
|
||||||
|
type_flags |= NODE_TYPE_PLUS;
|
||||||
}
|
}
|
||||||
void compute_nullable() { nullable = child[0]->nullable; }
|
void compute_nullable() { nullable = child[0]->nullable; }
|
||||||
void compute_firstpos() { firstpos = child[0]->firstpos; }
|
void compute_firstpos() { firstpos = child[0]->firstpos; }
|
||||||
@ -651,7 +717,7 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
int eq(Node *other) {
|
int eq(Node *other) {
|
||||||
if (dynamic_cast<PlusNode *>(other))
|
if (other->is_type(NODE_TYPE_PLUS))
|
||||||
return child[0]->eq(other->child[0]);
|
return child[0]->eq(other->child[0]);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -667,7 +733,10 @@ public:
|
|||||||
/* Match a pair of consecutive nodes. */
|
/* Match a pair of consecutive nodes. */
|
||||||
class CatNode: public TwoChildNode {
|
class CatNode: public TwoChildNode {
|
||||||
public:
|
public:
|
||||||
CatNode(Node *left, Node *right): TwoChildNode(left, right) { }
|
CatNode(Node *left, Node *right): TwoChildNode(left, right)
|
||||||
|
{
|
||||||
|
type_flags |= NODE_TYPE_CAT;
|
||||||
|
}
|
||||||
void compute_nullable()
|
void compute_nullable()
|
||||||
{
|
{
|
||||||
nullable = child[0]->nullable && child[1]->nullable;
|
nullable = child[0]->nullable && child[1]->nullable;
|
||||||
@ -695,7 +764,7 @@ public:
|
|||||||
}
|
}
|
||||||
int eq(Node *other)
|
int eq(Node *other)
|
||||||
{
|
{
|
||||||
if (dynamic_cast<CatNode *>(other)) {
|
if (other->is_type(NODE_TYPE_CAT)) {
|
||||||
if (!child[0]->eq(other->child[0]))
|
if (!child[0]->eq(other->child[0]))
|
||||||
return 0;
|
return 0;
|
||||||
return child[1]->eq(other->child[1]);
|
return child[1]->eq(other->child[1]);
|
||||||
@ -730,7 +799,10 @@ public:
|
|||||||
/* Match one of two alternative nodes. */
|
/* Match one of two alternative nodes. */
|
||||||
class AltNode: public TwoChildNode {
|
class AltNode: public TwoChildNode {
|
||||||
public:
|
public:
|
||||||
AltNode(Node *left, Node *right): TwoChildNode(left, right) { }
|
AltNode(Node *left, Node *right): TwoChildNode(left, right)
|
||||||
|
{
|
||||||
|
type_flags |= NODE_TYPE_ALT;
|
||||||
|
}
|
||||||
void compute_nullable()
|
void compute_nullable()
|
||||||
{
|
{
|
||||||
nullable = child[0]->nullable || child[1]->nullable;
|
nullable = child[0]->nullable || child[1]->nullable;
|
||||||
@ -745,7 +817,7 @@ public:
|
|||||||
}
|
}
|
||||||
int eq(Node *other)
|
int eq(Node *other)
|
||||||
{
|
{
|
||||||
if (dynamic_cast<AltNode *>(other)) {
|
if (other->is_type(NODE_TYPE_ALT)) {
|
||||||
if (!child[0]->eq(other->child[0]))
|
if (!child[0]->eq(other->child[0]))
|
||||||
return 0;
|
return 0;
|
||||||
return child[1]->eq(other->child[1]);
|
return child[1]->eq(other->child[1]);
|
||||||
@ -780,7 +852,10 @@ public:
|
|||||||
|
|
||||||
class SharedNode: public ImportantNode {
|
class SharedNode: public ImportantNode {
|
||||||
public:
|
public:
|
||||||
SharedNode() { }
|
SharedNode()
|
||||||
|
{
|
||||||
|
type_flags |= NODE_TYPE_SHARED;
|
||||||
|
}
|
||||||
void release(void)
|
void release(void)
|
||||||
{
|
{
|
||||||
/* don't delete SharedNodes via release as they are shared, and
|
/* don't delete SharedNodes via release as they are shared, and
|
||||||
@ -803,14 +878,17 @@ public:
|
|||||||
*/
|
*/
|
||||||
class AcceptNode: public SharedNode {
|
class AcceptNode: public SharedNode {
|
||||||
public:
|
public:
|
||||||
AcceptNode() { }
|
AcceptNode() { type_flags |= NODE_TYPE_ACCEPT; }
|
||||||
int is_accept(void) { return true; }
|
int is_accept(void) { return true; }
|
||||||
int is_postprocess(void) { return false; }
|
int is_postprocess(void) { return false; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class MatchFlag: public AcceptNode {
|
class MatchFlag: public AcceptNode {
|
||||||
public:
|
public:
|
||||||
MatchFlag(uint32_t flag, uint32_t audit): flag(flag), audit(audit) { }
|
MatchFlag(uint32_t flag, uint32_t audit): flag(flag), audit(audit)
|
||||||
|
{
|
||||||
|
type_flags |= NODE_TYPE_MATCHFLAG;
|
||||||
|
}
|
||||||
ostream &dump(ostream &os) { return os << "< 0x" << hex << flag << '>'; }
|
ostream &dump(ostream &os) { return os << "< 0x" << hex << flag << '>'; }
|
||||||
|
|
||||||
uint32_t flag;
|
uint32_t flag;
|
||||||
@ -819,12 +897,18 @@ public:
|
|||||||
|
|
||||||
class ExactMatchFlag: public MatchFlag {
|
class ExactMatchFlag: public MatchFlag {
|
||||||
public:
|
public:
|
||||||
ExactMatchFlag(uint32_t flag, uint32_t audit): MatchFlag(flag, audit) {}
|
ExactMatchFlag(uint32_t flag, uint32_t audit): MatchFlag(flag, audit)
|
||||||
|
{
|
||||||
|
type_flags |= NODE_TYPE_EXACTMATCHFLAG;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class DenyMatchFlag: public MatchFlag {
|
class DenyMatchFlag: public MatchFlag {
|
||||||
public:
|
public:
|
||||||
DenyMatchFlag(uint32_t flag, uint32_t quiet): MatchFlag(flag, quiet) {}
|
DenyMatchFlag(uint32_t flag, uint32_t quiet): MatchFlag(flag, quiet)
|
||||||
|
{
|
||||||
|
type_flags |= NODE_TYPE_DENYMATCHFLAG;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Traverse the syntax tree depth-first in an iterator-like manner. */
|
/* Traverse the syntax tree depth-first in an iterator-like manner. */
|
||||||
@ -833,7 +917,7 @@ class depth_first_traversal {
|
|||||||
void push_left(Node *node) {
|
void push_left(Node *node) {
|
||||||
pos.push(node);
|
pos.push(node);
|
||||||
|
|
||||||
while (dynamic_cast<InnerNode *>(node)) {
|
while (node->is_type(NODE_TYPE_INNER)) {
|
||||||
pos.push(node->child[0]);
|
pos.push(node->child[0]);
|
||||||
node = node->child[0];
|
node = node->child[0];
|
||||||
}
|
}
|
||||||
|
@ -1352,17 +1352,18 @@ int accept_perms(NodeSet *state, perms_t &perms, bool filedfa)
|
|||||||
return error;
|
return error;
|
||||||
|
|
||||||
for (NodeSet::iterator i = state->begin(); i != state->end(); i++) {
|
for (NodeSet::iterator i = state->begin(); i != state->end(); i++) {
|
||||||
MatchFlag *match;
|
if (!(*i)->is_type(NODE_TYPE_MATCHFLAG))
|
||||||
if (!(match = dynamic_cast<MatchFlag *>(*i)))
|
|
||||||
continue;
|
continue;
|
||||||
if (dynamic_cast<ExactMatchFlag *>(match)) {
|
|
||||||
|
MatchFlag *match = static_cast<MatchFlag *>(*i);
|
||||||
|
if (match->is_type(NODE_TYPE_EXACTMATCHFLAG)) {
|
||||||
/* exact match only ever happens with x */
|
/* exact match only ever happens with x */
|
||||||
if (filedfa && !is_merged_x_consistent(exact_match_allow,
|
if (filedfa && !is_merged_x_consistent(exact_match_allow,
|
||||||
match->flag))
|
match->flag))
|
||||||
error = 1;;
|
error = 1;;
|
||||||
exact_match_allow |= match->flag;
|
exact_match_allow |= match->flag;
|
||||||
exact_audit |= match->audit;
|
exact_audit |= match->audit;
|
||||||
} else if (dynamic_cast<DenyMatchFlag *>(match)) {
|
} else if (match->is_type(NODE_TYPE_DENYMATCHFLAG)) {
|
||||||
perms.deny |= match->flag;
|
perms.deny |= match->flag;
|
||||||
perms.quiet |= match->audit;
|
perms.quiet |= match->audit;
|
||||||
} else {
|
} else {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user