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             This module by Zoltan Herczeg and Sebastian Pop
10      Original API code Copyright (c) 1997-2012 University of Cambridge
11           New API code Copyright (c) 2016-2019 University of Cambridge
12 
13 -----------------------------------------------------------------------------
14 Redistribution and use in source and binary forms, with or without
15 modification, are permitted provided that the following conditions are met:
16 
17     * Redistributions of source code must retain the above copyright notice,
18       this list of conditions and the following disclaimer.
19 
20     * Redistributions in binary form must reproduce the above copyright
21       notice, this list of conditions and the following disclaimer in the
22       documentation and/or other materials provided with the distribution.
23 
24     * Neither the name of the University of Cambridge nor the names of its
25       contributors may be used to endorse or promote products derived from
26       this software without specific prior written permission.
27 
28 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
29 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
32 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
33 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
34 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
35 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
36 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
37 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38 POSSIBILITY OF SUCH DAMAGE.
39 -----------------------------------------------------------------------------
40 */
41 
42 # if defined(FFCS)
43 #  if defined(FF_UTF)
44 #   define FF_FUN ffcs_utf
45 #  else
46 #   define FF_FUN ffcs
47 #  endif
48 
49 # elif defined(FFCS_2)
50 #  if defined(FF_UTF)
51 #   define FF_FUN ffcs_2_utf
52 #  else
53 #   define FF_FUN ffcs_2
54 #  endif
55 
56 # elif defined(FFCS_MASK)
57 #  if defined(FF_UTF)
58 #   define FF_FUN ffcs_mask_utf
59 #  else
60 #   define FF_FUN ffcs_mask
61 #  endif
62 
63 # elif defined(FFCPS_0)
64 #  if defined (FF_UTF)
65 #   define FF_FUN ffcps_0_utf
66 #  else
67 #   define FF_FUN ffcps_0
68 #  endif
69 
70 # elif defined (FFCPS_1)
71 #  if defined (FF_UTF)
72 #   define FF_FUN ffcps_1_utf
73 #  else
74 #   define FF_FUN ffcps_1
75 #  endif
76 
77 # elif defined (FFCPS_DEFAULT)
78 #  if defined (FF_UTF)
79 #   define FF_FUN ffcps_default_utf
80 #  else
81 #   define FF_FUN ffcps_default
82 #  endif
83 # endif
84 
FF_FUN(sljit_u8 * str_end,sljit_u8 * str_ptr,sljit_uw offs1,sljit_uw offs2,sljit_uw chars)85 static sljit_u8* SLJIT_FUNC FF_FUN(sljit_u8 *str_end, sljit_u8 *str_ptr, sljit_uw offs1, sljit_uw offs2, sljit_uw chars)
86 #undef FF_FUN
87 {
88 quad_word qw;
89 int_char ic;
90 ic.x = chars;
91 
92 #if defined(FFCS)
93 sljit_u8 c1 = ic.c.c1;
94 vect_t vc1 = VDUPQ(c1);
95 
96 #elif defined(FFCS_2)
97 sljit_u8 c1 = ic.c.c1;
98 vect_t vc1 = VDUPQ(c1);
99 sljit_u8 c2 = ic.c.c2;
100 vect_t vc2 = VDUPQ(c2);
101 
102 #elif defined(FFCS_MASK)
103 sljit_u8 c1 = ic.c.c1;
104 vect_t vc1 = VDUPQ(c1);
105 sljit_u8 mask = ic.c.c2;
106 vect_t vmask = VDUPQ(mask);
107 #endif
108 
109 #if defined(FFCPS)
110 compare_type compare1_type = compare_match1;
111 compare_type compare2_type = compare_match1;
112 vect_t cmp1a, cmp1b, cmp2a, cmp2b;
113 const sljit_u32 diff = IN_UCHARS(offs1 - offs2);
114 PCRE2_UCHAR char1a = ic.c.c1;
115 PCRE2_UCHAR char2a = ic.c.c3;
116 
117 # ifdef FFCPS_CHAR1A2A
118 cmp1a = VDUPQ(char1a);
119 cmp2a = VDUPQ(char2a);
120 cmp1b = VDUPQ(0); /* to avoid errors on older compilers -Werror=maybe-uninitialized */
121 cmp2b = VDUPQ(0); /* to avoid errors on older compilers -Werror=maybe-uninitialized */
122 # else
123 PCRE2_UCHAR char1b = ic.c.c2;
124 PCRE2_UCHAR char2b = ic.c.c4;
125 if (char1a == char1b)
126   {
127   cmp1a = VDUPQ(char1a);
128   cmp1b = VDUPQ(0); /* to avoid errors on older compilers -Werror=maybe-uninitialized */
129   }
130 else
131   {
132   sljit_u32 bit1 = char1a ^ char1b;
133   if (is_powerof2(bit1))
134     {
135     compare1_type = compare_match1i;
136     cmp1a = VDUPQ(char1a | bit1);
137     cmp1b = VDUPQ(bit1);
138     }
139   else
140     {
141     compare1_type = compare_match2;
142     cmp1a = VDUPQ(char1a);
143     cmp1b = VDUPQ(char1b);
144     }
145   }
146 
147 if (char2a == char2b)
148   {
149   cmp2a = VDUPQ(char2a);
150   cmp2b = VDUPQ(0); /* to avoid errors on older compilers -Werror=maybe-uninitialized */
151   }
152 else
153   {
154   sljit_u32 bit2 = char2a ^ char2b;
155   if (is_powerof2(bit2))
156     {
157     compare2_type = compare_match1i;
158     cmp2a = VDUPQ(char2a | bit2);
159     cmp2b = VDUPQ(bit2);
160     }
161   else
162     {
163     compare2_type = compare_match2;
164     cmp2a = VDUPQ(char2a);
165     cmp2b = VDUPQ(char2b);
166     }
167   }
168 # endif
169 
170 str_ptr += IN_UCHARS(offs1);
171 #endif
172 
173 #if PCRE2_CODE_UNIT_WIDTH != 8
174 vect_t char_mask = VDUPQ(0xff);
175 #endif
176 
177 #if defined(FF_UTF)
178 restart:;
179 #endif
180 
181 #if defined(FFCPS)
182 sljit_u8 *p1 = str_ptr - diff;
183 #endif
184 sljit_s32 align_offset = ((uint64_t)str_ptr & 0xf);
185 str_ptr = (sljit_u8 *) ((uint64_t)str_ptr & ~0xf);
186 vect_t data = VLD1Q(str_ptr);
187 #if PCRE2_CODE_UNIT_WIDTH != 8
188 data = VANDQ(data, char_mask);
189 #endif
190 
191 #if defined(FFCS)
192 vect_t eq = VCEQQ(data, vc1);
193 
194 #elif defined(FFCS_2)
195 vect_t eq1 = VCEQQ(data, vc1);
196 vect_t eq2 = VCEQQ(data, vc2);
197 vect_t eq = VORRQ(eq1, eq2);
198 
199 #elif defined(FFCS_MASK)
200 vect_t eq = VORRQ(data, vmask);
201 eq = VCEQQ(eq, vc1);
202 
203 #elif defined(FFCPS)
204 # if defined(FFCPS_DIFF1)
205 vect_t prev_data = data;
206 # endif
207 
208 vect_t data2;
209 if (p1 < str_ptr)
210   {
211   data2 = VLD1Q(str_ptr - diff);
212 #if PCRE2_CODE_UNIT_WIDTH != 8
213   data2 = VANDQ(data2, char_mask);
214 #endif
215   }
216 else
217   data2 = shift_left_n_lanes(data, offs1 - offs2);
218 
219 if (compare1_type == compare_match1)
220   data = VCEQQ(data, cmp1a);
221 else
222   data = fast_forward_char_pair_compare(compare1_type, data, cmp1a, cmp1b);
223 
224 if (compare2_type == compare_match1)
225   data2 = VCEQQ(data2, cmp2a);
226 else
227   data2 = fast_forward_char_pair_compare(compare2_type, data2, cmp2a, cmp2b);
228 
229 vect_t eq = VANDQ(data, data2);
230 #endif
231 
232 VST1Q(qw.mem, eq);
233 /* Ignore matches before the first STR_PTR. */
234 if (align_offset < 8)
235   {
236   qw.dw[0] >>= align_offset * 8;
237   if (qw.dw[0])
238     {
239     str_ptr += align_offset + __builtin_ctzll(qw.dw[0]) / 8;
240     goto match;
241     }
242   if (qw.dw[1])
243     {
244     str_ptr += 8 + __builtin_ctzll(qw.dw[1]) / 8;
245     goto match;
246     }
247   }
248 else
249   {
250   qw.dw[1] >>= (align_offset - 8) * 8;
251   if (qw.dw[1])
252     {
253     str_ptr += align_offset + __builtin_ctzll(qw.dw[1]) / 8;
254     goto match;
255     }
256   }
257 str_ptr += 16;
258 
259 while (str_ptr < str_end)
260   {
261   vect_t orig_data = VLD1Q(str_ptr);
262 #if PCRE2_CODE_UNIT_WIDTH != 8
263   orig_data = VANDQ(orig_data, char_mask);
264 #endif
265   data = orig_data;
266 
267 #if defined(FFCS)
268   eq = VCEQQ(data, vc1);
269 
270 #elif defined(FFCS_2)
271   eq1 = VCEQQ(data, vc1);
272   eq2 = VCEQQ(data, vc2);
273   eq = VORRQ(eq1, eq2);
274 
275 #elif defined(FFCS_MASK)
276   eq = VORRQ(data, vmask);
277   eq = VCEQQ(eq, vc1);
278 #endif
279 
280 #if defined(FFCPS)
281 # if defined (FFCPS_DIFF1)
282   data2 = VEXTQ(prev_data, data, VECTOR_FACTOR - 1);
283 # else
284   data2 = VLD1Q(str_ptr - diff);
285 #  if PCRE2_CODE_UNIT_WIDTH != 8
286   data2 = VANDQ(data2, char_mask);
287 #  endif
288 # endif
289 
290 # ifdef FFCPS_CHAR1A2A
291   data = VCEQQ(data, cmp1a);
292   data2 = VCEQQ(data2, cmp2a);
293 # else
294   if (compare1_type == compare_match1)
295     data = VCEQQ(data, cmp1a);
296   else
297     data = fast_forward_char_pair_compare(compare1_type, data, cmp1a, cmp1b);
298   if (compare2_type == compare_match1)
299     data2 = VCEQQ(data2, cmp2a);
300   else
301     data2 = fast_forward_char_pair_compare(compare2_type, data2, cmp2a, cmp2b);
302 # endif
303 
304   eq = VANDQ(data, data2);
305 #endif
306 
307   VST1Q(qw.mem, eq);
308   if (qw.dw[0])
309     str_ptr += __builtin_ctzll(qw.dw[0]) / 8;
310   else if (qw.dw[1])
311     str_ptr += 8 + __builtin_ctzll(qw.dw[1]) / 8;
312   else {
313     str_ptr += 16;
314 #if defined (FFCPS_DIFF1)
315     prev_data = orig_data;
316 #endif
317     continue;
318   }
319 
320 match:;
321   if (str_ptr >= str_end)
322     /* Failed match. */
323     return NULL;
324 
325 #if defined(FF_UTF)
326   if (utf_continue(str_ptr + IN_UCHARS(-offs1)))
327     {
328     /* Not a match. */
329     str_ptr += IN_UCHARS(1);
330     goto restart;
331     }
332 #endif
333 
334   /* Match. */
335 #if defined (FFCPS)
336   str_ptr -= IN_UCHARS(offs1);
337 #endif
338   return str_ptr;
339   }
340 
341 /* Failed match. */
342 return NULL;
343 }
344