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 
91 SLJIT_UNUSED_ARG(offs1);
92 SLJIT_UNUSED_ARG(offs2);
93 
94 ic.x = chars;
95 
96 #if defined(FFCS)
97 sljit_u8 c1 = ic.c.c1;
98 vect_t vc1 = VDUPQ(c1);
99 
100 #elif defined(FFCS_2)
101 sljit_u8 c1 = ic.c.c1;
102 vect_t vc1 = VDUPQ(c1);
103 sljit_u8 c2 = ic.c.c2;
104 vect_t vc2 = VDUPQ(c2);
105 
106 #elif defined(FFCS_MASK)
107 sljit_u8 c1 = ic.c.c1;
108 vect_t vc1 = VDUPQ(c1);
109 sljit_u8 mask = ic.c.c2;
110 vect_t vmask = VDUPQ(mask);
111 #endif
112 
113 #if defined(FFCPS)
114 compare_type compare1_type = compare_match1;
115 compare_type compare2_type = compare_match1;
116 vect_t cmp1a, cmp1b, cmp2a, cmp2b;
117 const sljit_u32 diff = IN_UCHARS(offs1 - offs2);
118 PCRE2_UCHAR char1a = ic.c.c1;
119 PCRE2_UCHAR char2a = ic.c.c3;
120 
121 # ifdef FFCPS_CHAR1A2A
122 cmp1a = VDUPQ(char1a);
123 cmp2a = VDUPQ(char2a);
124 cmp1b = VDUPQ(0); /* to avoid errors on older compilers -Werror=maybe-uninitialized */
125 cmp2b = VDUPQ(0); /* to avoid errors on older compilers -Werror=maybe-uninitialized */
126 # else
127 PCRE2_UCHAR char1b = ic.c.c2;
128 PCRE2_UCHAR char2b = ic.c.c4;
129 if (char1a == char1b)
130   {
131   cmp1a = VDUPQ(char1a);
132   cmp1b = VDUPQ(0); /* to avoid errors on older compilers -Werror=maybe-uninitialized */
133   }
134 else
135   {
136   sljit_u32 bit1 = char1a ^ char1b;
137   if (is_powerof2(bit1))
138     {
139     compare1_type = compare_match1i;
140     cmp1a = VDUPQ(char1a | bit1);
141     cmp1b = VDUPQ(bit1);
142     }
143   else
144     {
145     compare1_type = compare_match2;
146     cmp1a = VDUPQ(char1a);
147     cmp1b = VDUPQ(char1b);
148     }
149   }
150 
151 if (char2a == char2b)
152   {
153   cmp2a = VDUPQ(char2a);
154   cmp2b = VDUPQ(0); /* to avoid errors on older compilers -Werror=maybe-uninitialized */
155   }
156 else
157   {
158   sljit_u32 bit2 = char2a ^ char2b;
159   if (is_powerof2(bit2))
160     {
161     compare2_type = compare_match1i;
162     cmp2a = VDUPQ(char2a | bit2);
163     cmp2b = VDUPQ(bit2);
164     }
165   else
166     {
167     compare2_type = compare_match2;
168     cmp2a = VDUPQ(char2a);
169     cmp2b = VDUPQ(char2b);
170     }
171   }
172 # endif
173 
174 str_ptr += IN_UCHARS(offs1);
175 #endif
176 
177 #if PCRE2_CODE_UNIT_WIDTH != 8
178 vect_t char_mask = VDUPQ(0xff);
179 #endif
180 
181 #if defined(FF_UTF)
182 restart:;
183 #endif
184 
185 #if defined(FFCPS)
186 sljit_u8 *p1 = str_ptr - diff;
187 #endif
188 sljit_s32 align_offset = ((uint64_t)str_ptr & 0xf);
189 str_ptr = (sljit_u8 *) ((uint64_t)str_ptr & ~0xf);
190 vect_t data = VLD1Q(str_ptr);
191 #if PCRE2_CODE_UNIT_WIDTH != 8
192 data = VANDQ(data, char_mask);
193 #endif
194 
195 #if defined(FFCS)
196 vect_t eq = VCEQQ(data, vc1);
197 
198 #elif defined(FFCS_2)
199 vect_t eq1 = VCEQQ(data, vc1);
200 vect_t eq2 = VCEQQ(data, vc2);
201 vect_t eq = VORRQ(eq1, eq2);
202 
203 #elif defined(FFCS_MASK)
204 vect_t eq = VORRQ(data, vmask);
205 eq = VCEQQ(eq, vc1);
206 
207 #elif defined(FFCPS)
208 # if defined(FFCPS_DIFF1)
209 vect_t prev_data = data;
210 # endif
211 
212 vect_t data2;
213 if (p1 < str_ptr)
214   {
215   data2 = VLD1Q(str_ptr - diff);
216 #if PCRE2_CODE_UNIT_WIDTH != 8
217   data2 = VANDQ(data2, char_mask);
218 #endif
219   }
220 else
221   data2 = shift_left_n_lanes(data, offs1 - offs2);
222 
223 if (compare1_type == compare_match1)
224   data = VCEQQ(data, cmp1a);
225 else
226   data = fast_forward_char_pair_compare(compare1_type, data, cmp1a, cmp1b);
227 
228 if (compare2_type == compare_match1)
229   data2 = VCEQQ(data2, cmp2a);
230 else
231   data2 = fast_forward_char_pair_compare(compare2_type, data2, cmp2a, cmp2b);
232 
233 vect_t eq = VANDQ(data, data2);
234 #endif
235 
236 VST1Q(qw.mem, eq);
237 /* Ignore matches before the first STR_PTR. */
238 if (align_offset < 8)
239   {
240   qw.dw[0] >>= align_offset * 8;
241   if (qw.dw[0])
242     {
243     str_ptr += align_offset + __builtin_ctzll(qw.dw[0]) / 8;
244     goto match;
245     }
246   if (qw.dw[1])
247     {
248     str_ptr += 8 + __builtin_ctzll(qw.dw[1]) / 8;
249     goto match;
250     }
251   }
252 else
253   {
254   qw.dw[1] >>= (align_offset - 8) * 8;
255   if (qw.dw[1])
256     {
257     str_ptr += align_offset + __builtin_ctzll(qw.dw[1]) / 8;
258     goto match;
259     }
260   }
261 str_ptr += 16;
262 
263 while (str_ptr < str_end)
264   {
265   vect_t orig_data = VLD1Q(str_ptr);
266 #if PCRE2_CODE_UNIT_WIDTH != 8
267   orig_data = VANDQ(orig_data, char_mask);
268 #endif
269   data = orig_data;
270 
271 #if defined(FFCS)
272   eq = VCEQQ(data, vc1);
273 
274 #elif defined(FFCS_2)
275   eq1 = VCEQQ(data, vc1);
276   eq2 = VCEQQ(data, vc2);
277   eq = VORRQ(eq1, eq2);
278 
279 #elif defined(FFCS_MASK)
280   eq = VORRQ(data, vmask);
281   eq = VCEQQ(eq, vc1);
282 #endif
283 
284 #if defined(FFCPS)
285 # if defined (FFCPS_DIFF1)
286   data2 = VEXTQ(prev_data, data, VECTOR_FACTOR - 1);
287 # else
288   data2 = VLD1Q(str_ptr - diff);
289 #  if PCRE2_CODE_UNIT_WIDTH != 8
290   data2 = VANDQ(data2, char_mask);
291 #  endif
292 # endif
293 
294 # ifdef FFCPS_CHAR1A2A
295   data = VCEQQ(data, cmp1a);
296   data2 = VCEQQ(data2, cmp2a);
297 # else
298   if (compare1_type == compare_match1)
299     data = VCEQQ(data, cmp1a);
300   else
301     data = fast_forward_char_pair_compare(compare1_type, data, cmp1a, cmp1b);
302   if (compare2_type == compare_match1)
303     data2 = VCEQQ(data2, cmp2a);
304   else
305     data2 = fast_forward_char_pair_compare(compare2_type, data2, cmp2a, cmp2b);
306 # endif
307 
308   eq = VANDQ(data, data2);
309 #endif
310 
311   VST1Q(qw.mem, eq);
312   if (qw.dw[0])
313     str_ptr += __builtin_ctzll(qw.dw[0]) / 8;
314   else if (qw.dw[1])
315     str_ptr += 8 + __builtin_ctzll(qw.dw[1]) / 8;
316   else {
317     str_ptr += 16;
318 #if defined (FFCPS_DIFF1)
319     prev_data = orig_data;
320 #endif
321     continue;
322   }
323 
324 match:;
325   if (str_ptr >= str_end)
326     /* Failed match. */
327     return NULL;
328 
329 #if defined(FF_UTF)
330   if (utf_continue(str_ptr + IN_UCHARS(-offs1)))
331     {
332     /* Not a match. */
333     str_ptr += IN_UCHARS(1);
334     goto restart;
335     }
336 #endif
337 
338   /* Match. */
339 #if defined (FFCPS)
340   str_ptr -= IN_UCHARS(offs1);
341 #endif
342   return str_ptr;
343   }
344 
345 /* Failed match. */
346 return NULL;
347 }
348