Branch data Line data Source code
1 : : #include "precizer.h"
2 : :
3 : : /**
4 : : * @brief Attempt optional JIT compilation for a compiled PCRE2 pattern
5 : : *
6 : : * JIT is a performance optimization only. Its absence must not prevent the
7 : : * pattern from being used through the normal interpretive matcher.
8 : : *
9 : : * @param[in] compiled_pattern Successfully compiled PCRE2 pattern
10 : : * @param[in] pattern_text Original pattern text used for logging
11 : : */
12 : 138 : static void try_jit_compile(
13 : : pcre2_code *compiled_pattern,
14 : : const char *pattern_text)
15 : : {
16 [ + - - + ]: 138 : if(compiled_pattern == NULL || pattern_text == NULL)
17 : : {
18 : 138 : return;
19 : : }
20 : :
21 : 138 : int jit_status = pcre2_jit_compile(compiled_pattern,PCRE2_JIT_COMPLETE);
22 : :
23 [ - + ]: 138 : if(
24 [ # # ]: 0 : jit_status == 0 ||
25 [ # # ]: 0 : jit_status == PCRE2_ERROR_JIT_BADOPTION ||
26 : : jit_status == PCRE2_ERROR_NOMEMORY)
27 : : {
28 : 138 : return;
29 : : }
30 : :
31 : : PCRE2_UCHAR8 error_message_buffer[MAX_CHARACTERS];
32 : 0 : pcre2_get_error_message(jit_status,error_message_buffer,MAX_CHARACTERS);
33 : 0 : slog(ERROR,"PCRE2 JIT compilation error %d for pattern \"%s\": %s\n",jit_status,pattern_text,error_message_buffer);
34 : : }
35 : :
36 : : /**
37 : : * @brief Compile one string array of PCRE2 pattern strings into a pcre2_code array
38 : : *
39 : : * Allocates a NULL-terminated array of pcre2_code pointers parallel to @p patterns.
40 : : * On the first compilation error the function logs the message and returns FAILURE;
41 : : * any patterns compiled before that point are freed before returning.
42 : : *
43 : : * @param[in] patterns NULL-terminated array of pattern strings to compile.
44 : : * If NULL the function is a no-op and returns SUCCESS.
45 : : * @param[out] compiled Receives the allocated pcre2_code pointer array on SUCCESS.
46 : : * Set to NULL on FAILURE.
47 : : * @return SUCCESS or FAILURE
48 : : */
49 : 1209 : static Return compile_one_array(
50 : : char **patterns,
51 : : pcre2_code ***compiled)
52 : : {
53 : : /* Status returned by this function through provide()
54 : : Default value assumes successful completion */
55 : 1209 : Return status = SUCCESS;
56 : :
57 : 1209 : *compiled = NULL;
58 : :
59 [ + + ]: 1209 : if(patterns == NULL)
60 : : {
61 : 1099 : provide(status);
62 : : }
63 : :
64 : : /* Count patterns */
65 : 110 : int pattern_count = 0;
66 : :
67 [ + + ]: 248 : while(patterns[pattern_count] != NULL)
68 : : {
69 : 138 : pattern_count++;
70 : : }
71 : :
72 : : /* Allocate pointer array: pattern_count entries + NULL terminator */
73 : 110 : pcre2_code **compiled_patterns = (pcre2_code **)calloc((size_t)(pattern_count + 1),sizeof(pcre2_code *));
74 : :
75 [ - + ]: 110 : if(compiled_patterns == NULL)
76 : : {
77 : 0 : report("Memory allocation failed for compiled pattern array");
78 : 0 : provide(FAILURE);
79 : : }
80 : :
81 : : /* Compile each pattern */
82 [ + + ]: 248 : for(int i = 0; i < pattern_count; i++)
83 : : {
84 : : PCRE2_SIZE compile_error_offset;
85 : : int compile_error_code;
86 : :
87 : 276 : compiled_patterns[i] = pcre2_compile(
88 : 138 : (const unsigned char *)patterns[i],
89 : 138 : strlen(patterns[i]),
90 : : 0,
91 : : &compile_error_code,
92 : : &compile_error_offset,
93 : : NULL);
94 : :
95 [ - + ]: 138 : if(compiled_patterns[i] == NULL)
96 : : {
97 : : PCRE2_UCHAR8 error_message_buffer[MAX_CHARACTERS];
98 : 0 : pcre2_get_error_message(compile_error_code,error_message_buffer,MAX_CHARACTERS);
99 : 0 : slog(ERROR,"PCRE2 failed to compile pattern \"%s\" at offset %zu: %s\n",patterns[i],(size_t)compile_error_offset,error_message_buffer);
100 : :
101 : 0 : free_compiled_array(&compiled_patterns);
102 : 0 : provide(FAILURE);
103 : : }
104 : :
105 : 138 : try_jit_compile(compiled_patterns[i],patterns[i]);
106 : : }
107 : :
108 : 110 : *compiled = compiled_patterns;
109 : :
110 : 110 : provide(status);
111 : : }
112 : :
113 : : /**
114 : : * @brief Compile all PCRE2 pattern strings stored in Config into pcre2_code objects
115 : : *
116 : : * Processes the ignore, include and lock_checksum string arrays.
117 : : * Each non-NULL array gets a matching _pcre_compiled array stored in Config.
118 : : * Called once from main() after parse_arguments() and before file traversal.
119 : : *
120 : : * @return SUCCESS or FAILURE
121 : : */
122 : 403 : Return compile_patterns(void)
123 : : {
124 : : /* Status returned by this function through provide()
125 : : Default value assumes successful completion */
126 : 403 : Return status = SUCCESS;
127 : :
128 [ + - - + ]: 403 : run(compile_one_array(config->ignore,&config->ignore_pcre_compiled));
129 [ + - - + ]: 403 : run(compile_one_array(config->include,&config->include_pcre_compiled));
130 [ + - - + ]: 403 : run(compile_one_array(config->lock_checksum,&config->lock_checksum_pcre_compiled));
131 : :
132 : 403 : provide(status);
133 : : }
|