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
17 const char *OSPcre2_Execute_pcre2_match(const char *str, OSPcre2 *reg);
18 const char *OSPcre2_Execute_strncmp(const char *subject, OSPcre2 *reg);
19 const char *OSPcre2_Execute_strrcmp(const char *subject, OSPcre2 *reg);
20 const char *OSPcre2_Execute_strcasecmp(const char *subject, OSPcre2 *reg);
21 const char *OSPcre2_Execute_strncasecmp(const char *subject, OSPcre2 *reg);
22 const char *OSPcre2_Execute_strrcasecmp(const char *subject, OSPcre2 *reg);
23 const char *OSPcre2_Execute_strcmp(const char *subject, OSPcre2 *reg);
24 int OSPcre2_CouldBeOptimized(const char *pattern);
26 int OSPcre2_Compile(const char *pattern, OSPcre2 *reg, int flags)
29 PCRE2_SIZE erroroffset;
30 size_t pattern_len = 0UL;
31 char first_char, last_char;
34 /* Check for references not initialized */
39 /* Initialize OSRegex structure */
41 reg->sub_strings = NULL;
43 reg->match_data = NULL;
44 reg->pattern_len = 0UL;
46 reg->exec_function = NULL;
48 /* The pattern can't be null */
49 if (pattern == NULL) {
50 reg->error = OS_REGEX_PATTERN_NULL;
54 /* Maximum size of the pattern */
55 pattern_len = strlen(pattern);
57 if (pattern_len > OS_PATTERN_MAXSIZE) {
58 reg->error = OS_REGEX_MAXSIZE;
63 if (OSPcre2_CouldBeOptimized(pattern)) {
64 first_char = pattern[0];
65 last_char = pattern[pattern_len - 1];
67 if (first_char == '^') {
68 if (last_char == '$') {
69 reg->pattern = strdup(&pattern[1]);
70 reg->pattern_len = pattern_len - 2;
71 reg->pattern[reg->pattern_len] = '\0';
72 if (flags & PCRE2_CASELESS) {
73 reg->exec_function = OSPcre2_Execute_strcasecmp;
75 reg->exec_function = OSPcre2_Execute_strcmp;
79 reg->pattern = strdup(&pattern[1]);
80 reg->pattern_len = pattern_len - 1;
81 if (flags & PCRE2_CASELESS) {
82 reg->exec_function = OSPcre2_Execute_strncasecmp;
84 reg->exec_function = OSPcre2_Execute_strncmp;
89 if (last_char == '$') {
90 reg->pattern = strdup(pattern);
91 reg->pattern_len = pattern_len - 1;
92 reg->pattern[reg->pattern_len] = '\0';
93 if (flags & PCRE2_CASELESS) {
94 reg->exec_function = OSPcre2_Execute_strrcasecmp;
96 reg->exec_function = OSPcre2_Execute_strrcmp;
103 reg->exec_function = OSPcre2_Execute_pcre2_match;
105 reg->regex = pcre2_compile((PCRE2_SPTR)pattern, pattern_len, flags, &error, &erroroffset, NULL);
106 if (reg->regex == NULL) {
107 reg->error = OS_REGEX_BADREGEX;
111 reg->match_data = pcre2_match_data_create_from_pattern(reg->regex, NULL);
112 if (reg->match_data == NULL) {
113 reg->error = OS_REGEX_OUTOFMEMORY;
117 pcre2_pattern_info(reg->regex, PCRE2_INFO_CAPTURECOUNT, (void *)&count);
118 count++; // to store NULL pointer at the end
119 reg->sub_strings = calloc(count, sizeof(char *));
120 if (reg->sub_strings == NULL) {
121 reg->error = OS_REGEX_OUTOFMEMORY;
124 for (i = 0; i < count; i++) {
125 reg->sub_strings[i] = NULL;
129 /* Just In Time compilation for faster execution */
130 if (pcre2_jit_compile(reg->regex, PCRE2_JIT_COMPLETE) != 0) {
131 reg->error = OS_REGEX_NO_JIT;
141 OSPcre2_FreePattern(reg);
146 int OSPcre2_CouldBeOptimized(const char *pattern)
148 pcre2_code *preg = NULL;
149 pcre2_match_data *md = NULL;
150 PCRE2_SPTR re = (PCRE2_SPTR) "^\\^?[a-zA-Z0-9 !\"#%&',/:;<=>@_`~-]*\\$?$";
152 PCRE2_SIZE erroroffset = 0;
153 int should_be_optimized = 0;
155 preg = pcre2_compile(re, PCRE2_ZERO_TERMINATED, PCRE2_UTF | PCRE2_NO_UTF_CHECK, &error,
157 md = pcre2_match_data_create_from_pattern(preg, NULL);
159 if (pcre2_match(preg, (PCRE2_SPTR)pattern, strlen(pattern), 0, 0, md, NULL) >= 0) {
160 should_be_optimized = 1;
163 pcre2_match_data_free(md);
164 pcre2_code_free(preg);
166 return should_be_optimized;