2
0
mirror of https://gitlab.com/apparmor/apparmor synced 2025-08-22 18:17:09 +00:00

Embedded the temporary computed nodes as part of the state

Embedding the nodes are part of the state gives fast back reference from
the state to the nodes that created it.  This is useful for the state to
nodes mapping dump as it lets us output the states in order.  It will also
let us avoid certain nodemap lookup in the future.

Overlay the nodes field (used only in dfa construction) with the partition
field which is only used during dfa minimization to avoid making the state
any larger.

Signed-off-by: John Johansen <john.johansen@canonical.com>
This commit is contained in:
John Johansen 2010-11-11 16:08:02 -08:00
parent 5b68e0f7c4
commit 15567a55dc

View File

@ -1395,17 +1395,28 @@ typedef struct Cases {
typedef list<State *> Partition; typedef list<State *> Partition;
/* /*
* State - DFA individual state information * State - DFA individual state information
* label: a unique label to identify the state used for pretty printing
* the non-matching state is setup to have label == 0 and
* the start state is setup to have label == 1
* audit: the audit permission mask for the state * audit: the audit permission mask for the state
* accept: the accept permissions for the state * accept: the accept permissions for the state
* cases: set of transitions from this state * cases: set of transitions from this state
* parition: Is a temporary work variable used during dfa minimization.
* it can be replaced with a map, but that is slower and uses more
* memory.
* nodes: Is a temporary work variable used during dfa creation. It can
* be replaced by using the nodemap, but that is slower
*/ */
class State { class State {
public: public:
State() : label (0), audit(0), accept(0), cases() { } State() : label (0), audit(0), accept(0), cases(), nodes(NULL) { }
int label; int label;
Partition *partition;
uint32_t audit, accept; uint32_t audit, accept;
Cases cases; Cases cases;
union {
Partition *partition;
NodeSet *nodes;
};
}; };
ostream& operator<<(ostream& os, const State& state) ostream& operator<<(ostream& os, const State& state)
@ -1421,6 +1432,7 @@ typedef map<pair<unsigned long, NodeSet *>, State *, deref_less_than > NodeMap;
/* Transitions in the DFA. */ /* Transitions in the DFA. */
class DFA { class DFA {
void dump_node_to_dfa(void);
public: public:
DFA(Node *root, dfaflags_t flags); DFA(Node *root, dfaflags_t flags);
virtual ~DFA(); virtual ~DFA();
@ -1454,6 +1466,7 @@ do { \
*/ \ */ \
TARGET = new State(); \ TARGET = new State(); \
(TARGET)->label = nodemap.size(); \ (TARGET)->label = nodemap.size(); \
(TARGET)->nodes = (NODES); \
states.push_back(TARGET); \ states.push_back(TARGET); \
nodemap.insert(make_pair(index, TARGET)); \ nodemap.insert(make_pair(index, TARGET)); \
work_queue.push_back(NODES); \ work_queue.push_back(NODES); \
@ -1468,14 +1481,16 @@ do { \
} \ } \
} while (0) } while (0)
static void dump_node_to_dfa(NodeMap &nodemap) /* WARNING: This routine can only be called from within DFA creation as
* the nodes value is only valid during dfa construction.
*/
void DFA::dump_node_to_dfa(void)
{ {
cerr << "Mapping of States to expr nodes\n" cerr << "Mapping of States to expr nodes\n"
" State <= Nodes\n" " State <= Nodes\n"
"-------------------\n"; "-------------------\n";
for (NodeMap::iterator i = nodemap.begin(); i != nodemap.end(); i++) for (Partition::iterator i = states.begin(); i != states.end(); i++)
cerr << " " << i->second->label << " <= " << *i->first.second << "\n"; cerr << " " << (*i)->label << " <= " << *(*i)->nodes << "\n";
} }
/** /**
@ -1505,6 +1520,7 @@ DFA::DFA(Node *root, dfaflags_t flags) : root(root)
nonmatching = new State; nonmatching = new State;
states.push_back(nonmatching); states.push_back(nonmatching);
NodeSet *emptynode = new NodeSet; NodeSet *emptynode = new NodeSet;
nonmatching->nodes = emptynode;
nodemap.insert(make_pair(make_pair(hash_NodeSet(emptynode), emptynode), nonmatching)); nodemap.insert(make_pair(make_pair(hash_NodeSet(emptynode), emptynode), nonmatching));
/* there is no nodemapping for the nonmatching state */ /* there is no nodemapping for the nonmatching state */
@ -1515,6 +1531,7 @@ DFA::DFA(Node *root, dfaflags_t flags) : root(root)
start->label = 1; start->label = 1;
states.push_back(start); states.push_back(start);
NodeSet *first = new NodeSet(root->firstpos); NodeSet *first = new NodeSet(root->firstpos);
start->nodes = first;
nodemap.insert(make_pair(make_pair(hash_NodeSet(first), first), start)); nodemap.insert(make_pair(make_pair(hash_NodeSet(first), first), start));
/* the work_queue contains the proto-states (set of nodes that is /* the work_queue contains the proto-states (set of nodes that is
@ -1594,7 +1611,7 @@ DFA::DFA(Node *root, dfaflags_t flags) : root(root)
} }
if (flags & DFA_DUMP_NODE_TO_DFA) if (flags & DFA_DUMP_NODE_TO_DFA)
dump_node_to_dfa(nodemap); dump_node_to_dfa();
for (NodeMap::iterator i = nodemap.begin(); i != nodemap.end(); i++) for (NodeMap::iterator i = nodemap.begin(); i != nodemap.end(); i++)
delete i->first.second; delete i->first.second;