-/* $OSSEC, os_regex.c, v0.3, 2005/04/05, Daniel B. Cid$ */
-
/* Copyright (C) 2009 Trend Micro Inc.
* All right reserved.
*
* Foundation
*/
-
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "os_regex.h"
-#include "os_regex_internal.h"
-
-
-/** Internal prototypes **/
-char *_OS_Regex(char *pattern, char *str, char **prts_closure,
- char **prts_str, int flags);
-
-
-/** char *OSRegex_Execute(char *str, OSRegex *reg) v0.1
- * Compare an already compiled regular expression with
+/* Compare an already compiled regular expression with
* a not NULL string.
* Returns the end of the string on success or NULL on error.
* The error code is set on reg->error.
*/
-char *OSRegex_Execute(char *str, OSRegex *reg)
+const char *OSRegex_Execute(const char *str, OSRegex *reg)
{
- char *ret;
- int i = 0;
-
/* The string can't be NULL */
- if(str == NULL)
- {
+ if (str == NULL) {
reg->error = OS_REGEX_STR_NULL;
- return(0);
+ return (NULL);
}
+ return reg->exec_function(str, reg);
+}
+const char *OSRegex_Execute_pcre2_match(const char *str, OSRegex *reg)
+{
+ int rc = 0, nbs = 0, i = 0;
+ PCRE2_SIZE *ov = NULL;
+
+ /* Execute the reg */
+#ifdef USE_PCRE2_JIT
+ rc = pcre2_jit_match(reg->regex, (PCRE2_SPTR)str, strlen(str), 0, 0, reg->match_data, NULL);
+#else
+ rc = pcre2_match(reg->regex, (PCRE2_SPTR)str, strlen(str), 0, 0, reg->match_data, NULL);
+#endif
+
+ /* Check execution result */
+ if (rc <= 0) {
+ return NULL;
+ }
- /* If we need the sub strings */
- if(reg->prts_closure)
- {
- int j = 0, k = 0, str_char = 0;
-
- /* Looping on all sub patterns */
- while(reg->patterns[i])
- {
- /* Cleaning the prts_str */
- j = 0;
- while(reg->prts_closure[i][j])
- {
- reg->prts_str[i][j] = NULL;
- j++;
- }
-
- if((ret = _OS_Regex(reg->patterns[i], str, reg->prts_closure[i],
- reg->prts_str[i], reg->flags[i])))
- {
- j = 0;
-
- /* We must always have the open and the close */
- while(reg->prts_str[i][j] && reg->prts_str[i][j+1])
- {
- str_char = reg->prts_str[i][j+1][0];
-
- reg->prts_str[i][j+1][0] = '\0';
-
- reg->sub_strings[k] = strdup(reg->prts_str[i][j]);
- if(!reg->sub_strings[k])
- {
- OSRegex_FreeSubStrings(reg);
- return(NULL);
- }
-
- /* Set the next one to null */
- reg->prts_str[i][j+1][0] = str_char;
- k++;
- reg->sub_strings[k] = NULL;
-
- /* Go two by two */
- j+=2;
- }
-
- return(ret);
+ /* get the offsets informations for the match */
+ ov = pcre2_get_ovector_pointer(reg->match_data);
+
+ if (reg->sub_strings) {
+ /* get the substrings if required */
+ for (i = 1; i < rc; i++) {
+ PCRE2_SIZE sub_string_start = ov[2 * i];
+ PCRE2_SIZE sub_string_end = ov[2 * i + 1];
+ PCRE2_SIZE sub_string_len = sub_string_end - sub_string_start;
+ if (sub_string_end > sub_string_start) {
+ reg->sub_strings[nbs] = (char *)calloc(sub_string_len + 1, sizeof(char));
+ strncpy(reg->sub_strings[nbs], &str[sub_string_start], sub_string_len);
+ nbs++;
}
- i++;
}
-
- return(0);
-
+ reg->sub_strings[nbs] = NULL;
}
- /* If we don't need the sub strings */
+ return &str[ov[1]];
+}
- /* Looping on all sub patterns */
- while(reg->patterns[i])
- {
- if((ret = _OS_Regex(reg->patterns[i], str, NULL, NULL, reg->flags[i])))
- {
- return(ret);
- }
- i++;
+const char *OSRegex_Execute_strcmp(const char *subject, OSRegex *reg)
+{
+ if (!strcmp(reg->pattern, subject)) {
+ return &subject[reg->pattern_len];
}
-
- return(NULL);
+ return NULL;
}
-#define PRTS(x) ((prts(*x) && x++) || 1)
-#define ENDOFFILE(x) ( PRTS(x) && (*x == '\0'))
-
-/** int _OS_Regex(char *pattern, char *str, char **prts_closure,
- char **prts_str, int flags) v0.1
- * Perform the pattern matching on the pattern/string provided.
- * Returns 1 on success and 0 on failure.
- * If prts_closure is set, the parenthesis locations will be
- * written on prts_str (which must not be NULL)
- */
-char *_OS_Regex(char *pattern, char *str, char **prts_closure,
- char **prts_str, int flags)
+const char *OSRegex_Execute_strncmp(const char *subject, OSRegex *reg)
{
- char *r_code = NULL;
-
- int ok_here;
- int _regex_matched = 0;
-
- int prts_int;
-
- char *st = str;
- char *st_error = NULL;
-
- char *pt = pattern;
- char *next_pt;
-
- char *pt_error[4] = {NULL, NULL, NULL, NULL};
- char *pt_error_str[4];
-
-
- /* Will loop the whole string, trying to find a match */
- do
- {
- switch(*pt)
- {
- case '\0':
- if(!(flags & END_SET) || (flags & END_SET && (*st == '\0')))
- return(r_code);
- break;
-
- /* If it is a parenthesis do not match against the character */
- case '(':
- /* Find the closure for the parenthesis */
- if(prts_closure)
- {
- prts_int = 0;
- while(prts_closure[prts_int])
- {
- if(prts_closure[prts_int] == pt)
- {
- prts_str[prts_int] = st;
- break;
- }
- prts_int++;
- }
- }
-
- pt++;
- if(*pt == '\0')
- {
- if(!(flags & END_SET) || (flags & END_SET && (*st == '\0')))
- return(r_code);
- }
- break;
- }
-
- /* If it starts on Backslash (future regex) */
- if(*pt == BACKSLASH)
- {
- if(Regex((uchar)*(pt+1), (uchar)*st))
- {
- next_pt = pt+2;
-
- /* If we don't have a '+' or '*', we should skip
- * searching using this pattern.
- */
- if(!isPlus(*next_pt))
- {
- pt = next_pt;
- if(!st_error)
- {
- /* If st_error is not set, we need to set it here.
- * In case of error in the matching later, we need
- * to continue from here (it will be incremented in
- * the while loop)
- */
- st_error = st;
- }
- r_code = st;
- continue;
- }
-
- /* If it is a '*', we need to set the _regex_matched
- * for the first pattern even.
- */
- if(*next_pt == '*')
- {
- _regex_matched = 1;
- }
-
-
- /* If our regex matches and we have a "+" set, we will
- * try the next one to see if it matches. If yes, we
- * can jump to it, but saving our currently location
- * in case of error.
- * _regex_matched will set set to true after the first
- * round of matches
- */
- if(_regex_matched)
- {
- next_pt++;
- ok_here = -1;
-
- /* If it is a parenthesis, jump to the next and write
- * the location down if 'ok_here >= 0'
- */
- if(prts(*next_pt))
- {
- next_pt++;
- }
-
- if(*next_pt == '\0')
- {
- ok_here = 1;
- }
- else if(*next_pt == BACKSLASH)
- {
- if(Regex((uchar)*(next_pt+1), (uchar)*st))
- {
- /* If the next one does not have
- * a '+' or '*', we can set it as
- * being read and continue.
- */
- if(!isPlus(*(next_pt+2)))
- {
- ok_here = 2;
- }
- else
- {
- ok_here = 0;
- }
- }
- }
- else if(*next_pt == charmap[(uchar)*st])
- {
- _regex_matched = 0;
- ok_here = 1;
- }
-
- /* If the next character matches in here */
- if(ok_here >= 0)
- {
- if(prts_closure && prts(*(next_pt - 1)))
- {
- prts_int = 0;
- while(prts_closure[prts_int])
- {
- if(prts_closure[prts_int] == (next_pt -1))
- {
- if(*(st+1) == '\0')
- prts_str[prts_int] = st+1;
- else
- prts_str[prts_int] = st;
- break;
- }
- prts_int++;
- }
- }
-
-
- /* If next_pt == \0, return the r_code */
- if(*next_pt == '\0')
- {
- continue;
- }
-
-
- /* Each "if" will increment the amount
- * necessary for the next pattern in ok_here
- */
- if(ok_here)
- next_pt+=ok_here;
-
-
- if(!pt_error[0])
- {
- pt_error[0] = pt;
- pt_error_str[0] = st;
- }
- else if(!pt_error[1])
- {
- pt_error[1] = pt;
- pt_error_str[1] = st;
- }
- else if(!pt_error[2])
- {
- pt_error[2] = pt;
- pt_error_str[2] = st;
-
- }
- else if(!pt_error[3])
- {
- pt_error[3] = pt;
- pt_error_str[3] = st;
- }
-
- pt = next_pt;
- }
- }
- else
- {
- next_pt++;
-
- /* If it is a parenthesis, mark the location */
- if(prts_closure && prts(*next_pt))
- {
- prts_int = 0;
- while(prts_closure[prts_int])
- {
- if(prts_closure[prts_int] == next_pt)
- {
- if(*(st+1) == '\0')
- prts_str[prts_int] = st +1;
- else
- prts_str[prts_int] = st;
- break;
- }
- prts_int++;
- }
- next_pt++;
- }
-
- _regex_matched = 1;
- }
-
- r_code = st;
- continue;
- }
-
- else if((*(pt+3) == '\0') && (_regex_matched == 1)&&(r_code))
- {
- r_code = st;
- if(!(flags & END_SET) || (flags & END_SET && (*st == '\0')))
- return(r_code);
- }
-
- /* If we didn't match regex, but _regex_matched == 1, jump
- * to the next available pattern
- */
- else if((*(pt+2) == '+') && (_regex_matched == 1))
- {
- pt+=3;
- st--;
- _regex_matched = 0;
- continue;
- }
- /* We may not match with '*' */
- else if(*(pt+2) == '*')
- {
- pt+=3;
- st--;
- r_code = st;
- _regex_matched = 0;
- continue;
- }
-
- _regex_matched = 0;
- }
- else if(*pt == charmap[(uchar)*st])
- {
- pt++;
- if(!st_error)
- {
- /* If st_error is not set, we need to set it here.
- * In case of error in the matching later, we need
- * to continue from here (it will be incremented in
- * the while loop)
- */
- st_error = st;
- }
- r_code = st;
- continue;
- }
-
- /* Error Handling */
- if(pt_error[3])
- {
- pt = pt_error[3];
- st = pt_error_str[3];
- pt_error[3] = NULL;
- continue;
- }
- else if(pt_error[2])
- {
- pt = pt_error[2];
- st = pt_error_str[2];
- pt_error[2] = NULL;
- continue;
- }
- else if(pt_error[1])
- {
- pt = pt_error[1];
- st = pt_error_str[1];
- pt_error[1] = NULL;
- continue;
- }
- else if(pt_error[0])
- {
- pt = pt_error[0];
- st = pt_error_str[0];
- pt_error[0] = NULL;
- continue;
- }
- else if(flags & BEGIN_SET)
- {
- /* If we get an error and the "^" option is
- * set, we can return "not matched" in here.
- */
- return(NULL);
- }
- else if(st_error)
- {
- st = st_error;
- st_error = NULL;
- }
- pt = pattern;
- r_code = NULL;
-
- }while(*(++st) != '\0');
-
-
- /* Matching for a possible last parenthesis */
- if(prts_closure)
- {
- while(!prts(*pt) && *pt != '\0')
- {
- if(*pt == BACKSLASH && *(pt+2) == '*')
- pt+=3;
- else
- break;
- }
-
- if(prts(*pt))
- {
- prts_int = 0;
- while(prts_closure[prts_int])
- {
- if(prts_closure[prts_int] == pt)
- {
- prts_str[prts_int] = st;
- break;
- }
- prts_int++;
- }
- }
+ if (!strncmp(reg->pattern, subject, reg->pattern_len)) {
+ return &subject[reg->pattern_len];
}
+ return NULL;
+}
- /* Cleaning up */
- if(ENDOFFILE(pt) ||
- (*pt == BACKSLASH &&
- _regex_matched &&
- (pt+=2) &&
- isPlus(*pt) &&
- (pt++) &&
- ((ENDOFFILE(pt)) ||
- ((*pt == BACKSLASH) &&
- (pt+=2) &&
- (*pt == '*') &&
- (pt++) &&
- (ENDOFFILE(pt)) ))) ||
- (*pt == BACKSLASH &&
- (pt+=2) &&
- (*pt == '*') &&
- (pt++) &&
- ENDOFFILE(pt))
- )
- {
- return(r_code);
+const char *OSRegex_Execute_strrcmp(const char *subject, OSRegex *reg)
+{
+ size_t len = strlen(subject);
+ if (len >= reg->pattern_len && !strcmp(reg->pattern, &subject[len - reg->pattern_len])) {
+ return &subject[len];
}
+ return NULL;
+}
- return(NULL);
+const char *OSRegex_Execute_strcasecmp(const char *subject, OSRegex *reg)
+{
+ if (!strcasecmp(reg->pattern, subject)) {
+ return &subject[reg->pattern_len];
+ }
+ return NULL;
}
+const char *OSRegex_Execute_strncasecmp(const char *subject, OSRegex *reg)
+{
+ if (!strncasecmp(reg->pattern, subject, reg->pattern_len)) {
+ return &subject[reg->pattern_len];
+ }
+ return NULL;
+}
-/* EOF */
+const char *OSRegex_Execute_strrcasecmp(const char *subject, OSRegex *reg)
+{
+ size_t len = strlen(subject);
+ if (len >= reg->pattern_len && !strcasecmp(reg->pattern, &subject[len - reg->pattern_len])) {
+ return &subject[len];
+ }
+ return NULL;
+}