mirror of
https://gitlab.com/apparmor/apparmor
synced 2025-08-22 01:57:43 +00:00
parser: improve unreachable state removal
Currently states are added to the reachable set when they are popped from the workqueue. This however can result in states being added to the work queue multiple times and reprocessed. Eg. If state 2 has the transitions, and 9 is not in the reachable set a -> 9 b -> 9 c -> 9 d -> 9 e -> 3 then 9 will get pushed onto the work 4 times. Even worse other states on the workqueue may also add state 9 to the workqueue because it has not been added to the reachable set. Instead add states to the reachable set when they are added to the workqueue. The first encounter with a state will result in it being reachable and all other encounters will see that it already in the set and not add it to the workqueue. Signed-off-by: John Johansen <john.johansen@canonical.com>
This commit is contained in:
parent
40e9b2a961
commit
4fb3dbc7b3
@ -546,6 +546,14 @@ void DFA::dump_uniq_perms(const char *s)
|
||||
//TODO: add prompt
|
||||
}
|
||||
|
||||
// make sure work_queue and reachable insertion are always done together
|
||||
static void push_reachable(set<State *> &reachable, list<State *> &work_queue,
|
||||
State *state)
|
||||
{
|
||||
work_queue.push_back(state);
|
||||
reachable.insert(state);
|
||||
}
|
||||
|
||||
/* Remove dead or unreachable states */
|
||||
void DFA::remove_unreachable(optflags const &opts)
|
||||
{
|
||||
@ -553,19 +561,18 @@ void DFA::remove_unreachable(optflags const &opts)
|
||||
|
||||
/* find the set of reachable states */
|
||||
reachable.insert(nonmatching);
|
||||
work_queue.push_back(start);
|
||||
push_reachable(reachable, work_queue, start);
|
||||
while (!work_queue.empty()) {
|
||||
State *from = work_queue.front();
|
||||
work_queue.pop_front();
|
||||
reachable.insert(from);
|
||||
|
||||
if (from->otherwise != nonmatching &&
|
||||
reachable.find(from->otherwise) == reachable.end())
|
||||
work_queue.push_back(from->otherwise);
|
||||
push_reachable(reachable, work_queue, from->otherwise);
|
||||
|
||||
for (StateTrans::iterator j = from->trans.begin(); j != from->trans.end(); j++) {
|
||||
if (reachable.find(j->second) == reachable.end())
|
||||
work_queue.push_back(j->second);
|
||||
push_reachable(reachable, work_queue, j->second);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user