/src/php-src/ext/pcre/pcre2lib/pcre2_jit_match.c
Line | Count | Source (jump to first uncovered line) |
1 | | /************************************************* |
2 | | * Perl-Compatible Regular Expressions * |
3 | | *************************************************/ |
4 | | |
5 | | /* PCRE is a library of functions to support regular expressions whose syntax |
6 | | and semantics are as close as possible to those of the Perl 5 language. |
7 | | |
8 | | Written by Philip Hazel |
9 | | Original API code Copyright (c) 1997-2012 University of Cambridge |
10 | | New API code Copyright (c) 2016-2023 University of Cambridge |
11 | | |
12 | | ----------------------------------------------------------------------------- |
13 | | Redistribution and use in source and binary forms, with or without |
14 | | modification, are permitted provided that the following conditions are met: |
15 | | |
16 | | * Redistributions of source code must retain the above copyright notice, |
17 | | this list of conditions and the following disclaimer. |
18 | | |
19 | | * Redistributions in binary form must reproduce the above copyright |
20 | | notice, this list of conditions and the following disclaimer in the |
21 | | documentation and/or other materials provided with the distribution. |
22 | | |
23 | | * Neither the name of the University of Cambridge nor the names of its |
24 | | contributors may be used to endorse or promote products derived from |
25 | | this software without specific prior written permission. |
26 | | |
27 | | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
28 | | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
29 | | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
30 | | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
31 | | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
32 | | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
33 | | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
34 | | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
35 | | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
36 | | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
37 | | POSSIBILITY OF SUCH DAMAGE. |
38 | | ----------------------------------------------------------------------------- |
39 | | */ |
40 | | |
41 | | #ifndef INCLUDED_FROM_PCRE2_JIT_COMPILE |
42 | | #error This file must be included from pcre2_jit_compile.c. |
43 | | #endif |
44 | | |
45 | | #if defined(__has_feature) |
46 | | #if __has_feature(memory_sanitizer) |
47 | | #include <sanitizer/msan_interface.h> |
48 | | #endif /* __has_feature(memory_sanitizer) */ |
49 | | #endif /* defined(__has_feature) */ |
50 | | |
51 | | #ifdef SUPPORT_JIT |
52 | | |
53 | | static SLJIT_NOINLINE int jit_machine_stack_exec(jit_arguments *arguments, jit_function executable_func) |
54 | | { |
55 | | sljit_u8 local_space[MACHINE_STACK_SIZE]; |
56 | | struct sljit_stack local_stack; |
57 | | |
58 | | local_stack.min_start = local_space; |
59 | | local_stack.start = local_space; |
60 | | local_stack.end = local_space + MACHINE_STACK_SIZE; |
61 | | local_stack.top = local_space + MACHINE_STACK_SIZE; |
62 | | arguments->stack = &local_stack; |
63 | | return executable_func(arguments); |
64 | | } |
65 | | |
66 | | #endif |
67 | | |
68 | | |
69 | | /************************************************* |
70 | | * Do a JIT pattern match * |
71 | | *************************************************/ |
72 | | |
73 | | /* This function runs a JIT pattern match. |
74 | | |
75 | | Arguments: |
76 | | code points to the compiled expression |
77 | | subject points to the subject string |
78 | | length length of subject string (may contain binary zeros) |
79 | | start_offset where to start in the subject string |
80 | | options option bits |
81 | | match_data points to a match_data block |
82 | | mcontext points to a match context |
83 | | |
84 | | Returns: > 0 => success; value is the number of ovector pairs filled |
85 | | = 0 => success, but ovector is not big enough |
86 | | -1 => failed to match (PCRE2_ERROR_NOMATCH) |
87 | | < -1 => some kind of unexpected problem |
88 | | */ |
89 | | |
90 | | PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION |
91 | | pcre2_jit_match(const pcre2_code *code, PCRE2_SPTR subject, PCRE2_SIZE length, |
92 | | PCRE2_SIZE start_offset, uint32_t options, pcre2_match_data *match_data, |
93 | | pcre2_match_context *mcontext) |
94 | 0 | { |
95 | 0 | #ifndef SUPPORT_JIT |
96 | |
|
97 | 0 | (void)code; |
98 | 0 | (void)subject; |
99 | 0 | (void)length; |
100 | 0 | (void)start_offset; |
101 | 0 | (void)options; |
102 | 0 | (void)match_data; |
103 | 0 | (void)mcontext; |
104 | 0 | return PCRE2_ERROR_JIT_BADOPTION; |
105 | |
|
106 | | #else /* SUPPORT_JIT */ |
107 | | |
108 | | pcre2_real_code *re = (pcre2_real_code *)code; |
109 | | executable_functions *functions = (executable_functions *)re->executable_jit; |
110 | | pcre2_jit_stack *jit_stack; |
111 | | uint32_t oveccount = match_data->oveccount; |
112 | | uint32_t max_oveccount; |
113 | | union { |
114 | | void *executable_func; |
115 | | jit_function call_executable_func; |
116 | | } convert_executable_func; |
117 | | jit_arguments arguments; |
118 | | int rc; |
119 | | int index = 0; |
120 | | |
121 | | if ((options & PCRE2_PARTIAL_HARD) != 0) |
122 | | index = 2; |
123 | | else if ((options & PCRE2_PARTIAL_SOFT) != 0) |
124 | | index = 1; |
125 | | |
126 | | if (functions == NULL || functions->executable_funcs[index] == NULL) |
127 | | return PCRE2_ERROR_JIT_BADOPTION; |
128 | | |
129 | | /* Sanity checks should be handled by pcre2_match. */ |
130 | | arguments.str = subject + start_offset; |
131 | | arguments.begin = subject; |
132 | | arguments.end = subject + length; |
133 | | arguments.match_data = match_data; |
134 | | arguments.startchar_ptr = subject; |
135 | | arguments.mark_ptr = NULL; |
136 | | arguments.options = options; |
137 | | |
138 | | if (mcontext != NULL) |
139 | | { |
140 | | arguments.callout = mcontext->callout; |
141 | | arguments.callout_data = mcontext->callout_data; |
142 | | arguments.offset_limit = mcontext->offset_limit; |
143 | | arguments.limit_match = (mcontext->match_limit < re->limit_match)? |
144 | | mcontext->match_limit : re->limit_match; |
145 | | if (mcontext->jit_callback != NULL) |
146 | | jit_stack = mcontext->jit_callback(mcontext->jit_callback_data); |
147 | | else |
148 | | jit_stack = (pcre2_jit_stack *)mcontext->jit_callback_data; |
149 | | } |
150 | | else |
151 | | { |
152 | | arguments.callout = NULL; |
153 | | arguments.callout_data = NULL; |
154 | | arguments.offset_limit = PCRE2_UNSET; |
155 | | arguments.limit_match = (MATCH_LIMIT < re->limit_match)? |
156 | | MATCH_LIMIT : re->limit_match; |
157 | | jit_stack = NULL; |
158 | | } |
159 | | |
160 | | |
161 | | max_oveccount = functions->top_bracket; |
162 | | if (oveccount > max_oveccount) |
163 | | oveccount = max_oveccount; |
164 | | arguments.oveccount = oveccount << 1; |
165 | | |
166 | | |
167 | | convert_executable_func.executable_func = functions->executable_funcs[index]; |
168 | | if (jit_stack != NULL) |
169 | | { |
170 | | arguments.stack = (struct sljit_stack *)(jit_stack->stack); |
171 | | rc = convert_executable_func.call_executable_func(&arguments); |
172 | | } |
173 | | else |
174 | | rc = jit_machine_stack_exec(&arguments, convert_executable_func.call_executable_func); |
175 | | |
176 | | if (rc > (int)oveccount) |
177 | | rc = 0; |
178 | | match_data->code = re; |
179 | | match_data->subject = (rc >= 0 || rc == PCRE2_ERROR_PARTIAL)? subject : NULL; |
180 | | match_data->subject_length = length; |
181 | | match_data->rc = rc; |
182 | | match_data->startchar = arguments.startchar_ptr - subject; |
183 | | match_data->leftchar = 0; |
184 | | match_data->rightchar = 0; |
185 | | match_data->mark = arguments.mark_ptr; |
186 | | match_data->matchedby = PCRE2_MATCHEDBY_JIT; |
187 | | |
188 | | #if defined(__has_feature) |
189 | | #if __has_feature(memory_sanitizer) |
190 | | if (rc > 0) |
191 | | __msan_unpoison(match_data->ovector, 2 * rc * sizeof(match_data->ovector[0])); |
192 | | #endif /* __has_feature(memory_sanitizer) */ |
193 | | #endif /* defined(__has_feature) */ |
194 | | |
195 | | return match_data->rc; |
196 | | |
197 | | #endif /* SUPPORT_JIT */ |
198 | 0 | } |
199 | | |
200 | | /* End of pcre2_jit_match.c */ |