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 const char *OSRegex_Execute_pcre2_match(const char *str, OSRegex *reg);
17 const char *OSRegex_Execute_strncmp(const char *subject, OSRegex *reg);
18 const char *OSRegex_Execute_strrcmp(const char *subject, OSRegex *reg);
19 const char *OSRegex_Execute_strcasecmp(const char *subject, OSRegex *reg);
20 const char *OSRegex_Execute_strncasecmp(const char *subject, OSRegex *reg);
21 const char *OSRegex_Execute_strrcasecmp(const char *subject, OSRegex *reg);
22 const char *OSRegex_Execute_strcmp(const char *subject, OSRegex *reg);
23 int OSRegex_CouldBeOptimized(const char *pattern2check);
25 /* Compile a regular expression to be used later
28 * - OS_RETURN_SUBSTRING
29 * Returns 1 on success or 0 on error
30 * The error code is set on reg->error
32 int OSRegex_Compile(const char *pattern, OSRegex *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;
42 /* Check for references not initialized */
47 /* Initialize OSRegex structure */
49 reg->sub_strings = NULL;
51 reg->match_data = NULL;
52 reg->pattern_len = 0UL;
54 reg->exec_function = NULL;
56 /* The pattern can't be null */
57 if (pattern == NULL) {
58 reg->error = OS_REGEX_PATTERN_NULL;
62 /* Maximum size of the pattern */
63 pattern_len = strlen(pattern);
64 if (pattern_len > OS_PATTERN_MAXSIZE) {
65 reg->error = OS_REGEX_MAXSIZE;
69 if (OSRegex_CouldBeOptimized(pattern)) {
70 first_char = pattern[0];
71 last_char = pattern[pattern_len - 1];
73 if (first_char == '^') {
74 if (last_char == '$') {
75 reg->pattern = strdup(&pattern[1]);
76 reg->pattern_len = pattern_len - 2;
77 reg->pattern[reg->pattern_len] = '\0';
78 if (flags & OS_CASE_SENSITIVE) {
79 reg->exec_function = OSRegex_Execute_strcmp;
81 reg->exec_function = OSRegex_Execute_strcasecmp;
85 reg->pattern = strdup(&pattern[1]);
86 reg->pattern_len = pattern_len - 1;
87 if (flags & OS_CASE_SENSITIVE) {
88 reg->exec_function = OSRegex_Execute_strncmp;
90 reg->exec_function = OSRegex_Execute_strncasecmp;
95 if (last_char == '$') {
96 reg->pattern = strdup(pattern);
97 reg->pattern_len = pattern_len - 1;
98 reg->pattern[reg->pattern_len] = '\0';
99 if (flags & OS_CASE_SENSITIVE) {
100 reg->exec_function = OSRegex_Execute_strrcmp;
102 reg->exec_function = OSRegex_Execute_strrcasecmp;
109 reg->exec_function = OSRegex_Execute_pcre2_match;
111 /* Ossec pattern conversion */
112 if (OSRegex_Convert(pattern, &pattern_pcre2, OS_CONVERT_REGEX) == 0) {
113 reg->error = OS_REGEX_BADREGEX;
117 flags_compile |= PCRE2_UTF;
118 flags_compile |= PCRE2_NO_UTF_CHECK;
119 flags_compile |= (flags & OS_CASE_SENSITIVE) ? 0 : PCRE2_CASELESS;
120 reg->regex = pcre2_compile((PCRE2_SPTR)pattern_pcre2, PCRE2_ZERO_TERMINATED, flags_compile,
121 &error, &erroroffset, NULL);
122 if (reg->regex == NULL) {
123 reg->error = OS_REGEX_BADREGEX;
127 reg->match_data = pcre2_match_data_create_from_pattern(reg->regex, NULL);
128 if (reg->match_data == NULL) {
129 reg->error = OS_REGEX_OUTOFMEMORY;
134 /* Just In Time compilation for faster execution */
135 if (pcre2_jit_compile(reg->regex, PCRE2_JIT_COMPLETE) != 0) {
136 reg->error = OS_REGEX_NO_JIT;
141 if (flags & OS_RETURN_SUBSTRING) {
142 pcre2_pattern_info(reg->regex, PCRE2_INFO_CAPTURECOUNT, (void *)&count);
143 count++; // to store NULL pointer at the end
144 reg->sub_strings = calloc(count, sizeof(char *));
145 if (reg->sub_strings == NULL) {
146 reg->error = OS_REGEX_OUTOFMEMORY;
149 for (i = 0; i < count; i++) {
150 reg->sub_strings[i] = NULL;
165 OSRegex_FreePattern(reg);
170 int OSRegex_CouldBeOptimized(const char *pattern2check) {
171 return OS_Pcre2("^\\^?[A-Za-z0-9 !\"#%&',/:;<=>@_`~-]*\\$?$", pattern2check);