1 /* Copyright (C) 2009 Trend Micro Inc.
4 * This program is a free software; you can redistribute it
5 * and/or modify it under the terms of the GNU General Public
6 * License (version 2) as published by the FSF - Free Software
16 int OSMatch_Execute_pcre2_match(const char *subject, size_t len, OSMatch *match);
17 int OSMatch_Execute_true(const char *subject, size_t len, OSMatch *match);
18 int OSMatch_Execute_strncmp(const char *subject, size_t len, OSMatch *match);
19 int OSMatch_Execute_strrcmp(const char *subject, size_t len, OSMatch *match);
20 int OSMatch_Execute_strcmp(const char *subject, size_t len, OSMatch *match);
21 int OSMatch_Execute_strncasecmp(const char *subject, size_t len, OSMatch *match);
22 int OSMatch_Execute_strrcasecmp(const char *subject, size_t len, OSMatch *match);
23 int OSMatch_Execute_strcasecmp(const char *subject, size_t len, OSMatch *match);
24 int OSMatch_CouldBeOptimized(const char *pattern2check);
26 /* Compile a pattern to be used later
29 * Returns 1 on success or 0 on error
30 * The error code is set on reg->error
32 int OSMatch_Compile(const char *pattern, OSMatch *reg, int flags)
34 char *pattern_pcre2 = NULL;
35 int flags_compile = 0;
37 PCRE2_SIZE erroroffset = 0;
38 size_t pattern_len = 0UL;
39 char first_char, last_char;
41 /* Check for references not initialized */
46 /* Initialize OSMatch structure */
49 reg->match_data = NULL;
50 reg->pattern_len = 0UL;
52 reg->exec_function = NULL;
54 /* The pattern can't be null */
55 if (pattern == NULL) {
56 reg->error = OS_REGEX_PATTERN_NULL;
60 /* Maximum size of the pattern */
61 pattern_len = strlen(pattern);
62 if (pattern_len > OS_PATTERN_MAXSIZE) {
63 reg->error = OS_REGEX_MAXSIZE;
67 if (pattern_len == 0) {
68 reg->exec_function = OSMatch_Execute_true;
70 } else if (OSMatch_CouldBeOptimized(pattern)) {
71 first_char = pattern[0];
72 last_char = pattern[pattern_len - 1];
74 if (first_char == '^') {
75 if (last_char == '$') {
76 reg->pattern = strdup(&pattern[1]);
77 reg->pattern_len = pattern_len - 2;
78 reg->pattern[reg->pattern_len] = '\0';
79 if (flags & OS_CASE_SENSITIVE) {
80 reg->exec_function = OSMatch_Execute_strcmp;
82 reg->exec_function = OSMatch_Execute_strcasecmp;
86 reg->pattern = strdup(&pattern[1]);
87 reg->pattern_len = pattern_len - 1;
88 if (flags & OS_CASE_SENSITIVE) {
89 reg->exec_function = OSMatch_Execute_strncmp;
91 reg->exec_function = OSMatch_Execute_strncasecmp;
96 if (last_char == '$') {
97 reg->pattern = strdup(pattern);
98 reg->pattern_len = pattern_len - 1;
99 reg->pattern[reg->pattern_len] = '\0';
100 if (flags & OS_CASE_SENSITIVE) {
101 reg->exec_function = OSMatch_Execute_strrcmp;
103 reg->exec_function = OSMatch_Execute_strrcasecmp;
110 reg->exec_function = OSMatch_Execute_pcre2_match;
112 /* Ossec pattern conversion */
113 if (OSRegex_Convert(pattern, &pattern_pcre2, OS_CONVERT_MATCH) == 0) {
114 reg->error = OS_REGEX_BADREGEX;
118 flags_compile |= PCRE2_UTF;
119 flags_compile |= PCRE2_NO_UTF_CHECK;
120 flags_compile |= (flags & OS_CASE_SENSITIVE) ? 0 : PCRE2_CASELESS;
121 reg->regex = pcre2_compile((PCRE2_SPTR)pattern_pcre2, PCRE2_ZERO_TERMINATED, flags_compile,
122 &error, &erroroffset, NULL);
123 if (reg->regex == NULL) {
124 reg->error = OS_REGEX_BADREGEX;
128 reg->match_data = pcre2_match_data_create_from_pattern(reg->regex, NULL);
129 if (reg->match_data == NULL) {
130 reg->error = OS_REGEX_OUTOFMEMORY;
135 /* Just In Time compilation for faster execution */
136 if (pcre2_jit_compile(reg->regex, PCRE2_JIT_COMPLETE) != 0) {
137 reg->error = OS_REGEX_NO_JIT;
153 OSMatch_FreePattern(reg);
158 int OSMatch_CouldBeOptimized(const char *pattern2check)
160 return OS_Pcre2("^\\^?[^$|^]+\\$?$", pattern2check);