2
0
mirror of https://gitlab.com/apparmor/apparmor synced 2025-09-03 15:55:46 +00:00

Add reference counting on class Node so that we will be able to reuse AcceptNodes

This commit is contained in:
Andreas Gruenbacher
2007-03-30 14:13:56 +00:00
parent 1bdc66f696
commit aeb6205ce8

View File

@@ -68,15 +68,17 @@
class Node { class Node {
public: public:
Node() : Node() :
nullable(false), left(0), right(0) { } nullable(false), left(0), right(0), refcount(1) { }
Node(Node *left) : Node(Node *left) :
nullable(false), left(left), right(0) { } nullable(false), left(left), right(0), refcount(1) { }
Node(Node *left, Node *right) : Node(Node *left, Node *right) :
nullable(false), left(left), right(right) { } nullable(false), left(left), right(right), refcount(1) { }
virtual ~Node() virtual ~Node()
{ {
delete left; if (left)
delete right; left->release();
if (right)
right->release();
} }
/** /**
@@ -93,6 +95,17 @@
bool nullable; bool nullable;
State firstpos, lastpos, followpos; State firstpos, lastpos, followpos;
Node *left, *right; Node *left, *right;
/**
* We need reference counting for AcceptNodes: sharing AcceptNodes
* avoids introducing duplicate States with identical accept values.
*/
unsigned int refcount;
void dup(void) { refcount++; }
void release(void) {
if (--refcount == 0)
delete this;
}
}; };
/* Match nothing (//). */ /* Match nothing (//). */
@@ -419,7 +432,7 @@
* Note: destroy all nodes upon failure, but *not* the start symbol once * Note: destroy all nodes upon failure, but *not* the start symbol once
* parsing succeeds! * parsing succeeds!
*/ */
%destructor { delete $$; } expr terms0 terms qterm term %destructor { $$->release(); } expr terms0 terms qterm term
%% %%
@@ -1482,76 +1495,7 @@ void dump_regexp(ostream& os, Node *tree)
os << endl; os << endl;
} }
/**
* "Librarize"
*/
#include <errno.h>
#include <sstream> #include <sstream>
#if 0
#include <sys/cdefs.h>
__BEGIN_DECLS
#endif
/**
* "value\0regexp\0value\0regexp\0\0"
*/
extern "C" char *
regexp_flex_table(const char *name, const char *regexps,
int equivalence_classes, int reverse, size_t *size)
{
Node *root = new EpsNode();
char *buffer;
while (*regexps) {
char *endptr;
uint32_t accept;
int is_rerule;
Node *tree;
accept = strtoul(regexps, &endptr, 0);
if (*endptr != '\0' || accept == 0 || accept >= (1UL << 31)) {
delete root;
errno = EINVAL;
return NULL;
}
regexps = endptr + 1;
is_rerule = NOT_RE_RULE;
if (regexp_parse(&tree, endptr, &is_rerule)) {
delete root;
errno = EINVAL;
return NULL;
}
if (reverse)
flip_tree(tree);
tree = new CatNode(tree, new AcceptNode(accept, is_rerule));
root = new AltNode(root, tree);
regexps = strchr(regexps, 0);
}
DFA dfa(root);
map<uchar, uchar> eq;
if (equivalence_classes) {
eq = dfa.equivalence_classes();
dfa.apply_equivalence_classes(eq);
}
TransitionTable transition_table(dfa, eq);
ostringstream stream;
transition_table.flex_table(stream, name);
delete root;
streambuf *buf = stream.rdbuf();
*size = buf->in_avail();
buffer = (char *)malloc(*size);
if (!buffer)
return NULL;
buf->sgetn(buffer, *size);
return buffer;
}
#include <ext/stdio_filebuf.h> #include <ext/stdio_filebuf.h>
#include "apparmor_re.h" #include "apparmor_re.h"
@@ -1560,9 +1504,7 @@ struct aare_ruleset {
Node *root; Node *root;
}; };
extern "C" { extern "C" aare_ruleset_t *aare_new_ruleset(int reverse)
aare_ruleset_t *aare_new_ruleset(int reverse)
{ {
aare_ruleset_t *container = (aare_ruleset_t *) malloc(sizeof(aare_ruleset_t)); aare_ruleset_t *container = (aare_ruleset_t *) malloc(sizeof(aare_ruleset_t));
if (!container) if (!container)
@@ -1574,16 +1516,15 @@ aare_ruleset_t *aare_new_ruleset(int reverse)
return container; return container;
} }
void aare_delete_ruleset(aare_ruleset_t *rules) extern "C" void aare_delete_ruleset(aare_ruleset_t *rules)
{ {
if (rules) { if (rules) {
delete(rules->root); rules->root->release();
free(rules); free(rules);
} }
} }
int aare_add_rule(aare_ruleset_t *rules, char *rule, extern "C" int aare_add_rule(aare_ruleset_t *rules, char *rule, uint32_t perms)
uint32_t perms)
{ {
Node *tree; Node *tree;
int is_rerule = NOT_RE_RULE; int is_rerule = NOT_RE_RULE;
@@ -1605,7 +1546,8 @@ int aare_add_rule(aare_ruleset_t *rules, char *rule,
* returns: buffer contain dfa tables, @size set to the size of the tables * returns: buffer contain dfa tables, @size set to the size of the tables
* else NULL on failure * else NULL on failure
*/ */
void *aare_create_dfa(aare_ruleset_t *rules, int equiv_classes, size_t *size) extern "C" void *aare_create_dfa(aare_ruleset_t *rules, int equiv_classes,
size_t *size)
{ {
char *buffer = NULL; char *buffer = NULL;
@@ -1637,5 +1579,3 @@ void *aare_create_dfa(aare_ruleset_t *rules, int equiv_classes, size_t *size)
buf->sgetn(buffer, *size); buf->sgetn(buffer, *size);
return buffer; return buffer;
} }
} /* extern C */