r11138 - prelude-lml/trunk/plugins/pcre

[email protected]
Newsgroups gmane.comp.security.ids.prelude.cvs
Message-ID <[email protected]>
Author: yoann
Date: 2009-04-10 11:53:42 +0200 (Fri, 10 Apr 2009)
New Revision: 11138

Modified:
   prelude-lml/trunk/plugins/pcre/rule-regex.c
Log:
This simplify the whole regular expression handling a lot, making the
code much easier to read, and fixing potential problem with ovector
assignement. This code should also improve performance by a small
factor.

Modified: prelude-lml/trunk/plugins/pcre/rule-regex.c
===================================================================
--- prelude-lml/trunk/plugins/pcre/rule-regex.c	2009-04-10 09:53:38 UTC (rev 11137)
+++ prelude-lml/trunk/plugins/pcre/rule-regex.c	2009-04-10 09:53:42 UTC (rev 11138)
@@ -57,6 +57,8 @@
 
         pcre *regex;
         pcre_extra *extra;
+
+        int capture_count;
         char *regex_string;
         prelude_bool_t optreg;
 };
@@ -69,73 +71,82 @@
 
 
 
+#define OVECSIZE MAX_REFERENCE_PER_RULE * 3
+
+
+static int ovector[OVECSIZE];
+static unsigned int ovector_index;
+
+
+
 /*
- * In a match where some of the capture are not required, pcre_exec will
- * not always return the _full_ number of captured substring. This function
- * make sure that all not captured substring are set to -1, and then return
- * the total of substring, including the one that were not captured.
+ * This function implement pcre_exec() call in a way that allow the same
+ * ovector to be used accross multiple call.
+ *
+ * This result in a single ovector containing all the reference to
+ * all subpatterns.
  */
-static int do_pcre_exec(rule_regex_t *item, int *real_ret,
-                        const char *subject, int length, int *ovector, int ovecsize)
+static int do_pcre_exec(rule_regex_t *item, const char *in, size_t len, int *omin, int *omax)
 {
-        int cnt = 0, i;
+        int *optr, obkp0, obkp1, ret, osize;
 
-        *real_ret = pcre_exec(item->regex, item->extra, subject, length, 0, 0, ovector, ovecsize);
+        osize = OVECSIZE - ovector_index - 2;
+        if ( osize < 3 )
+                return -1;
 
-        prelude_log_debug(5, "match %s ret %d\n", item->regex_string, *real_ret);
+        optr = &ovector[ovector_index - 2];
+        obkp0 = optr[0];
+        obkp1 = optr[1];
 
-        if ( *real_ret <= 0 && ! item->optreg )
-                return *real_ret;
+        ret = pcre_exec(item->regex, item->extra, in, len, 0, 0, optr, osize);
+        if ( ret < -1 || ret == 0 ) {
+                prelude_log(PRELUDE_LOG_ERR, "unexpected PCRE error: %d.\n", ret);
+                return -1;
+        }
 
-        pcre_fullinfo(item->regex, item->extra, PCRE_INFO_CAPTURECOUNT, &cnt);
-        if ( cnt == 0 )
-                return *real_ret;
+        *omin = optr[0];
+        *omax = optr[1];
+        optr[0] = obkp0;
+        optr[1] = obkp1;
 
-        for ( i = (*real_ret * 2); (i + 2) < (MIN(ovecsize, cnt + 1) * 2); i += 2 )
-                ovector[i] = ovector[i + 1] = -1;
+        ovector_index += (item->capture_count * 2);
 
-        return cnt + 1;
+        return ret;
 }
 
 
-
-static int exec_regex(pcre_rule_t *rule, const lml_log_entry_t *log_entry, int *ovector, size_t size)
+static int exec_regex(pcre_rule_t *rule, const lml_log_entry_t *log_entry)
 {
+        size_t len;
         rule_regex_t *item;
         prelude_list_t *tmp;
-        int tmpovector[size];
-        int optional_match = 0, real_ret = 0, ret, retval = 0, i = 0;
+        const char *subject;
+        int optional_match = 0, ret, retval = 1, omin, omax;
 
+        len = lml_log_entry_get_message_len(log_entry);
+        subject = lml_log_entry_get_message(log_entry);
+
         prelude_list_for_each(&rule->regex_list, tmp) {
                 item = prelude_linked_object_get_object(tmp);
 
-                ret = do_pcre_exec(item, &real_ret, lml_log_entry_get_message(log_entry),
-                                   lml_log_entry_get_message_len(log_entry),
-                                   tmpovector, sizeof(tmpovector) / sizeof(int));
-                prelude_log_debug(5, "id=%d match=%s ret=%d (real=%d)\n", rule->id, item->regex_string, ret, real_ret);
-                if ( ret <= 0 && ! item->optreg )
+                ret = do_pcre_exec(item, subject, len, &omin, &omax);
+                prelude_log_debug(5, "id=%d match=%s pcre_exec=%d\n", rule->id, item->regex_string, ret);
+
+                retval += item->capture_count;
+                if ( ret < 0 && ! item->optreg )
                         return -1;
 
-                ovector[0] = MIN(tmpovector[0], ovector[0]);
-                ovector[1] = MAX(tmpovector[1], ovector[1]);
+                else {
+                        if ( ret > 1 ) {
+                                ovector[0] = MIN(ovector[0], omin);
+                                ovector[1] = MAX(ovector[1], omax);
+                        }
 
-                if ( item->optreg && real_ret > 0 )
-                        optional_match++;
-
-                if ( ret == 1 )
-                        continue;
-
-                for ( i = 2; i < (ret * 2); i += 2 ) {
-                        prelude_log_debug(10, "assign %d-%d\n", retval * 2 + i, retval * 2 + i + 1);
-                        ovector[(retval * 2) + i] = tmpovector[i];
-                        ovector[(retval * 2) + i + 1] = tmpovector[i + 1];
+                        if ( item->optreg )
+                                optional_match++;
                 }
-
-                retval += (ret - 1);
         }
 
-        retval++;
-
         if ( rule->min_optregex_match ) {
                 prelude_log_debug(10, "optmatch=%d >= wanted=%d\n", optional_match, rule->min_optregex_match);
                 return (optional_match >= rule->min_optregex_match) ? retval : -1;
@@ -147,12 +158,12 @@
 
 
 static pcre_context_t *lookup_context(value_container_t *vcont, pcre_plugin_t *plugin,
-                                      pcre_rule_t *rule, const lml_log_entry_t *log_entry, int *ovector, size_t osize)
+                                      pcre_rule_t *rule, const lml_log_entry_t *log_entry)
 {
         pcre_context_t *ctx;
         prelude_string_t *str;
 
-        str = value_container_resolve(vcont, rule, log_entry, ovector, osize);
+        str = value_container_resolve(vcont, rule, log_entry, ovector, ovector_index);
         if ( ! str )
                 return NULL;
 
@@ -207,7 +218,7 @@
 
 
 static int match_rule_single(pcre_plugin_t *plugin, pcre_rule_t *rule, pcre_state_t *state,
-                             const lml_log_source_t *ls, const lml_log_entry_t *log_entry, int *ovector, int *osize)
+                             const lml_log_source_t *ls, const lml_log_entry_t *log_entry)
 {
         int ret;
         prelude_list_t *tmp;
@@ -216,19 +227,20 @@
 
         ovector[0] = 0x7fffffff;
         ovector[1] = 0;
+        ovector_index = 2;
 
-        *osize = exec_regex(rule, log_entry, ovector, (size_t) *osize);
-        if ( *osize < 0 )
+        ret = exec_regex(rule, log_entry);
+        if ( ret < 0 )
                 return -1;
 
         prelude_list_for_each(&rule->not_context_list, tmp) {
                 vcont = prelude_linked_object_get_object(tmp);
-                if ( lookup_context(vcont, plugin, rule, log_entry, ovector, *osize) )
+                if ( lookup_context(vcont, plugin, rule, log_entry) )
                         return -1;
         }
 
         if ( rule->required_context ) {
-                ctx = lookup_context(rule->required_context, plugin, rule, log_entry, ovector, *osize);
+                ctx = lookup_context(rule->required_context, plugin, rule, log_entry);
                 if ( ! ctx )
                         return -1;
 
@@ -237,12 +249,12 @@
         }
 
         if ( rule->optional_context ) {
-                ctx = lookup_context(rule->optional_context, plugin, rule, log_entry, ovector, *osize);
+                ctx = lookup_context(rule->optional_context, plugin, rule, log_entry);
                 if ( ctx && pcre_context_get_idmef(ctx) )
                         state->idmef = idmef_message_ref(pcre_context_get_idmef(ctx));
         }
 
-        ret = rule_object_build_message(rule, rule->object_list, &state->idmef, log_entry, ovector, *osize);
+        ret = rule_object_build_message(rule, rule->object_list, &state->idmef, log_entry, ovector, ovector_index);
         if ( ret < 0 )
                 return ret;
 
@@ -269,7 +281,7 @@
 
 
 static void create_context_if_needed(pcre_plugin_t *plugin, pcre_rule_t *rule, pcre_state_t *state,
-                                     const lml_log_entry_t *log_entry, int *ovector, int osize)
+                                     const lml_log_entry_t *log_entry)
 {
         prelude_list_t *tmp;
         prelude_string_t *str;
@@ -279,7 +291,7 @@
         prelude_list_for_each(&rule->create_context_list, tmp) {
                 vcont = prelude_linked_object_get_object(tmp);
 
-                str = value_container_resolve(vcont, rule, log_entry, ovector, osize);
+                str = value_container_resolve(vcont, rule, log_entry, ovector, ovector_index);
                 if ( ! str )
                         continue;
 
@@ -292,7 +304,7 @@
 
 
 static void destroy_context_if_needed(pcre_plugin_t *plugin, pcre_rule_t *rule,
-                                      const lml_log_entry_t *log_entry, int *ovector, int osize)
+                                      const lml_log_entry_t *log_entry)
 {
         pcre_context_t *ctx;
         prelude_list_t *tmp;
@@ -302,7 +314,7 @@
         prelude_list_for_each(&rule->destroy_context_list, tmp) {
                 vcont = prelude_linked_object_get_object(tmp);
 
-                str = value_container_resolve(vcont, rule, log_entry, ovector, osize);
+                str = value_container_resolve(vcont, rule, log_entry, ovector, ovector_index);
                 if ( ! str )
                         continue;
 
@@ -327,9 +339,8 @@
         pcre_match_flags_t gl = 0;
         pcre_rule_t *rule = rc->rule;
         pcre_rule_container_t *child;
-        int ovector[MAX_REFERENCE_PER_RULE * 3], osize = sizeof(ovector) / sizeof(int);;
 
-        ret = match_rule_single(plugin, rule, state, ls, log_entry, ovector, &osize);
+        ret = match_rule_single(plugin, rule, state, ls, log_entry);
         if ( ret < 0 )
                 return -1;
 
@@ -355,7 +366,7 @@
                 return -1;
         }
 
-        create_context_if_needed(plugin, rule, state, log_entry, ovector, osize);
+        create_context_if_needed(plugin, rule, state, log_entry);
 
         if ( ! (rule->flags & PCRE_RULE_FLAGS_SILENT) && state->idmef ) {
                 prelude_log_debug(4, "lml alert emit id=%d (last=%d) %s\n",
@@ -371,7 +382,7 @@
         if ( rule->flags & PCRE_RULE_FLAGS_LAST )
                 *match_flags |= PCRE_MATCH_FLAGS_LAST;
 
-        destroy_context_if_needed(plugin, rule, log_entry, ovector, osize);
+        destroy_context_if_needed(plugin, rule, log_entry);
 
         return 0;
 }
@@ -426,6 +437,8 @@
         new->optreg = optional;
         new->extra = pcre_study(new->regex, 0, &err_ptr);
 
+        pcre_fullinfo(new->regex, new->extra, PCRE_INFO_CAPTURECOUNT, &new->capture_count);
+
         return new;
 }
 

_______________________________________________
Prelude-cvslog site list
[email protected]
http://lists.prelude-ids.org/mailman/listinfo/prelude-cvslog
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.