Le Mon, 1 Apr 2013 13:40:46 -0400, Eric Paris <eparis@xxxxxxxxxxxxxx> a écrit : > I feel like we talked about it... Regex ordering is a bit tricky. I > think I hacked up a patch which added an additional tie breaker step > with the total number of 'non-regex' type characters being used. It's > been long lost though... > > Do you still have that hack around? Maybe we can see what others > think? I definitely have a bad memory... I grepped my IRC logs and found this patch[0] from you at the date of the 28th of Sept 2012. Cheers Laurent Bigonville [0] http://fpaste.org/p48W/
diff --git a/libsemanage/src/semanage_store.c b/libsemanage/src/semanage_store.c index cd7ce68..5ee3b9f 100644 --- a/libsemanage/src/semanage_store.c +++ b/libsemanage/src/semanage_store.c @@ -128,6 +128,7 @@ typedef struct semanage_file_context_node { char *context; int path_len; int effective_len; + int nonmeta_len; int type_len; int context_len; int meta; /* position of first meta char in path, -1 if none */ @@ -2000,6 +2001,12 @@ static int semanage_fc_compare(semanage_file_context_node_t * a, if (b->meta < a->meta) return 1; + /* total number of non meta chars? */ + if (a->nonmeta_len < b->nonmeta_len) + return -1; + if (b->nonmeta_len < a->nonmeta_len) + return 1; + /* Check to see if either a or b have a shorter string * length than the other. */ if (a->effective_len < b->effective_len) @@ -2110,6 +2117,24 @@ static void semanage_fc_merge_sort(semanage_file_context_bucket_t * master) } } +static int is_meta_char(char c) +{ + switch (c) { + case '.': + case '^': + case '$': + case '?': + case '*': + case '+': + case '|': + case '[': + case '(': + case '{': + return 1; + } + return 0; +} + /* Compute the location of the first regular expression * meta character in the path of the given node, if it exists. * On return: @@ -2127,25 +2152,15 @@ static void semanage_fc_find_meta(semanage_file_context_node_t * fc_node) * spec_hasMetaChars in matchpathcon.c from * libselinux-1.22. */ while (fc_node->path[c] != '\0') { - switch (fc_node->path[c]) { - case '.': - case '^': - case '$': - case '?': - case '*': - case '+': - case '|': - case '[': - case '(': - case '{': + if (is_meta_char(fc_node->path[c])) { fc_node->meta = c - escape_chars; return; - case '\\': + } + if (fc_node->path[c] == '\\') { /* If an escape character is found, * skip the next character. */ c++; escape_chars++; - break; } c++; @@ -2208,7 +2223,7 @@ int semanage_fc_sort(semanage_handle_t * sh, const char *buf, size_t buf_len, ssize_t sanity_check; const char *line_buf, *line_end; char *sorted_buf_pos; - int escape_chars, just_saw_escape; + int escape_chars, just_saw_escape, meta_chars; semanage_file_context_node_t *temp; semanage_file_context_node_t *head; @@ -2291,10 +2306,13 @@ int semanage_fc_sort(semanage_handle_t * sh, const char *buf, size_t buf_len, temp->next = NULL; /* Extract the regular expression from the line. */ + meta_chars = 0; escape_chars = 0; just_saw_escape = 0; start = i; while (i < line_len && (!isspace(line_buf[i]))) { + if (is_meta_char(line_buf[i])) + meta_chars++; if (line_buf[i] == '\\') { if (!just_saw_escape) { escape_chars++; @@ -2399,6 +2417,7 @@ int semanage_fc_sort(semanage_handle_t * sh, const char *buf, size_t buf_len, /* Initialize the data about the file context. */ temp->path_len = regex_len; temp->effective_len = regex_len - escape_chars; + temp->nonmeta_len = regex_len - escape_chars - meta_chars; temp->type_len = type_len; temp->context_len = context_len; semanage_fc_find_meta(temp);