1 /*
2 * Copyright (c) 2015-2017, Intel Corporation
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * * Redistributions of source code must retain the above copyright notice,
8 * this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of Intel Corporation nor the names of its contributors
13 * may be used to endorse or promote products derived from this software
14 * without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include "config.h"
30
31 #include "gtest/gtest.h"
32 #include "nfa/truffle.h"
33 #include "nfa/trufflecompile.h"
34 #include "util/charreach.h"
35 #include "util/simd_utils.h"
36
37 using namespace ue2;
38
TEST(Truffle,CompileDot)39 TEST(Truffle, CompileDot) {
40 m128 mask1, mask2;
41 memset(&mask1, 0, sizeof(mask1));
42 memset(&mask2, 0, sizeof(mask2));
43
44 CharReach chars;
45
46 chars.setall();
47
48 truffleBuildMasks(chars, (u8 *)&mask1, (u8 *)&mask2);
49
50 CharReach out = truffle2cr((u8 *)&mask1, (u8 *)&mask2);
51
52 ASSERT_EQ(out, chars);
53
54 }
55
TEST(Truffle,CompileChars)56 TEST(Truffle, CompileChars) {
57 m128 mask1, mask2;
58
59 CharReach chars;
60
61 // test one char at a time
62 for (u32 c = 0; c < 256; ++c) {
63 mask1 = zeroes128();
64 mask2 = zeroes128();
65 chars.clear();
66 chars.set((u8)c);
67 truffleBuildMasks(chars, (u8 *)&mask1, (u8 *)&mask2);
68 CharReach out = truffle2cr((u8 *)&mask1, (u8 *)&mask2);
69 ASSERT_EQ(out, chars);
70 }
71
72 // set all chars up to dot
73 for (u32 c = 0; c < 256; ++c) {
74 mask1 = zeroes128();
75 mask2 = zeroes128();
76 chars.set((u8)c);
77 truffleBuildMasks(chars, (u8 *)&mask1, (u8 *)&mask2);
78 CharReach out = truffle2cr((u8 *)&mask1, (u8 *)&mask2);
79 ASSERT_EQ(out, chars);
80 }
81
82 // unset all chars from dot
83 for (u32 c = 0; c < 256; ++c) {
84 mask1 = zeroes128();
85 mask2 = zeroes128();
86 chars.clear((u8)c);
87 truffleBuildMasks(chars, (u8 *)&mask1, (u8 *)&mask2);
88 CharReach out = truffle2cr((u8 *)&mask1, (u8 *)&mask2);
89 ASSERT_EQ(out, chars);
90 }
91
92 }
93
TEST(Truffle,ExecNoMatch1)94 TEST(Truffle, ExecNoMatch1) {
95 m128 mask1, mask2;
96 memset(&mask1, 0, sizeof(mask1));
97 memset(&mask2, 0, sizeof(mask2));
98
99 CharReach chars;
100
101 chars.set('a');
102
103 truffleBuildMasks(chars, (u8 *)&mask1, (u8 *)&mask2);
104
105 char t1[] = "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\xff";
106
107 for (size_t i = 0; i < 16; i++) {
108 const u8 *rv = truffleExec(mask1, mask2, (u8 *)t1 + i, (u8 *)t1 + strlen(t1));
109
110 ASSERT_EQ((size_t)t1 + strlen(t1), (size_t)rv);
111 }
112 }
113
TEST(Truffle,ExecNoMatch2)114 TEST(Truffle, ExecNoMatch2) {
115 m128 mask1, mask2;
116
117 CharReach chars;
118
119 chars.set('a');
120 chars.set('B');
121
122 truffleBuildMasks(chars, (u8 *)&mask1, (u8 *)&mask2);
123
124 char t1[] = "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb";
125
126 for (size_t i = 0; i < 16; i++) {
127 const u8 *rv = truffleExec(mask1, mask2, (u8 *)t1 + i, (u8 *)t1 + strlen(t1));
128
129 ASSERT_EQ((size_t)t1 + strlen(t1), (size_t)rv);
130 }
131 }
132
TEST(Truffle,ExecNoMatch3)133 TEST(Truffle, ExecNoMatch3) {
134 m128 mask1, mask2;
135
136 CharReach chars;
137
138 chars.set('V'); /* V = 0x56, e = 0x65 */
139
140 truffleBuildMasks(chars, (u8 *)&mask1, (u8 *)&mask2);
141
142 char t1[] = "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee";
143
144 for (size_t i = 0; i < 16; i++) {
145 const u8 *rv = truffleExec(mask1, mask2, (u8 *)t1 + i, (u8 *)t1 + strlen(t1));
146
147 ASSERT_EQ((size_t)t1 + strlen(t1), (size_t)rv);
148 }
149 }
150
TEST(Truffle,ExecMiniMatch0)151 TEST(Truffle, ExecMiniMatch0) {
152 m128 lo, hi;
153
154 CharReach chars;
155 chars.set('a');
156
157 truffleBuildMasks(chars, (u8 *)&lo, (u8 *)&hi);
158
159 char t1[] = "a";
160
161 const u8 *rv = truffleExec(lo, hi, (u8 *)t1, (u8 *)t1 + strlen(t1));
162
163 ASSERT_EQ((size_t)t1, (size_t)rv);
164 }
165
TEST(Truffle,ExecMiniMatch1)166 TEST(Truffle, ExecMiniMatch1) {
167 m128 lo, hi;
168
169 CharReach chars;
170 chars.set('a');
171
172 truffleBuildMasks(chars, (u8 *)&lo, (u8 *)&hi);
173
174 char t1[] = "bbbbbbbabbb";
175
176 const u8 *rv = truffleExec(lo, hi, (u8 *)t1, (u8 *)t1 + strlen(t1));
177
178 ASSERT_EQ((size_t)t1 + 7, (size_t)rv);
179 }
180
TEST(Truffle,ExecMiniMatch2)181 TEST(Truffle, ExecMiniMatch2) {
182 m128 lo, hi;
183
184 CharReach chars;
185 chars.set(0);
186
187 truffleBuildMasks(chars, (u8 *)&lo, (u8 *)&hi);
188
189 char t1[] = "bbbbbbb\0bbb";
190
191 const u8 *rv = truffleExec(lo, hi, (u8 *)t1, (u8 *)t1 + 11);
192
193 ASSERT_EQ((size_t)t1 + 7, (size_t)rv);
194 }
195
TEST(Truffle,ExecMiniMatch3)196 TEST(Truffle, ExecMiniMatch3) {
197 m128 lo, hi;
198
199 CharReach chars;
200 chars.set('a');
201
202 truffleBuildMasks(chars, (u8 *)&lo, (u8 *)&hi);
203
204 char t1[] = "\0\0\0\0\0\0\0a\0\0\0";
205
206 const u8 *rv = truffleExec(lo, hi, (u8 *)t1, (u8 *)t1 + 11);
207
208 ASSERT_EQ((size_t)t1 + 7, (size_t)rv);
209 }
210
TEST(Truffle,ExecMatchBig)211 TEST(Truffle, ExecMatchBig) {
212 m128 lo, hi;
213
214 CharReach chars;
215 chars.set('a');
216
217 truffleBuildMasks(chars, (u8 *)&lo, (u8 *)&hi);
218
219 std::array<u8, 400> t1;
220 t1.fill('b');
221 t1[120] = 'a';
222
223 for (size_t i = 0; i < 16; i++) {
224 const u8 *rv = truffleExec(lo, hi, (u8 *)t1.data() + i, (u8 *)t1.data() + 399);
225
226 ASSERT_LE(((size_t)t1.data() + 120) & ~0xf, (size_t)rv);
227 }
228 }
229
TEST(Truffle,ExecMatch1)230 TEST(Truffle, ExecMatch1) {
231 m128 mask1, mask2;
232
233 CharReach chars;
234
235 chars.set('a');
236
237 truffleBuildMasks(chars, (u8 *)&mask1, (u8 *)&mask2);
238
239 /* 0123456789012345678901234567890 */
240 char t1[] = "bbbbbbbbbbbbbbbbbabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbabbbbbbbbbbbb";
241
242 for (size_t i = 0; i < 16; i++) {
243 const u8 *rv = truffleExec(mask1, mask2, (u8 *)t1 + i, (u8 *)t1 + strlen(t1));
244
245 ASSERT_EQ((size_t)t1 + 17, (size_t)rv);
246 }
247 }
248
TEST(Truffle,ExecMatch2)249 TEST(Truffle, ExecMatch2) {
250 m128 mask1, mask2;
251
252 CharReach chars;
253
254 chars.set('a');
255
256 truffleBuildMasks(chars, (u8 *)&mask1, (u8 *)&mask2);
257
258 /* 0123456789012345678901234567890 */
259 char t1[] = "bbbbbbbbbbbbbbbbbaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbabbbbbbbbbbbb";
260
261 for (size_t i = 0; i < 16; i++) {
262 const u8 *rv = truffleExec(mask1, mask2, (u8 *)t1 + i, (u8 *)t1 + strlen(t1));
263
264 ASSERT_EQ((size_t)t1 + 17, (size_t)rv);
265 }
266 }
267
TEST(Truffle,ExecMatch3)268 TEST(Truffle, ExecMatch3) {
269 m128 mask1, mask2;
270
271 CharReach chars;
272
273 chars.set('a');
274 chars.set('B');
275
276 truffleBuildMasks(chars, (u8 *)&mask1, (u8 *)&mask2);
277
278 /* 0123456789012345678901234567890 */
279 char t1[] = "bbbbbbbbbbbbbbbbbBaaaaaaaaaaaaaaabbbbbbbbbbbbbbbabbbbbbbbbbbb";
280
281 for (size_t i = 0; i < 16; i++) {
282 const u8 *rv = truffleExec(mask1, mask2, (u8 *)t1 + i, (u8 *)t1 + strlen(t1));
283
284 ASSERT_EQ((size_t)t1 + 17, (size_t)rv);
285 }
286 }
287
TEST(Truffle,ExecMatch4)288 TEST(Truffle, ExecMatch4) {
289 m128 mask1, mask2;
290
291 CharReach chars;
292
293 chars.set('a');
294 chars.set('C');
295 chars.set('A');
296 chars.set('c');
297
298 truffleBuildMasks(chars, (u8 *)&mask1, (u8 *)&mask2);
299
300 /* 0123456789012345678901234567890 */
301 char t1[] = "bbbbbbbbbbbbbbbbbAaaaaaaaaaaaaaaabbbbbbbbbbbbbbbabbbbbbbbbbbb";
302 char t2[] = "bbbbbbbbbbbbbbbbbCaaaaaaaaaaaaaaabbbbbbbbbbbbbbbabbbbbbbbbbbb";
303 char t3[] = "bbbbbbbbbbbbbbbbbcaaaaaaaaaaaaaaabbbbbbbbbbbbbbbabbbbbbbbbbbb";
304 char t4[] = "bbbbbbbbbbbbbbbbbaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbabbbbbbbbbbbb";
305
306 for (size_t i = 0; i < 16; i++) {
307 const u8 *rv = truffleExec(mask1, mask2, (u8 *)t1 + i, (u8 *)t1 + strlen(t1));
308
309 ASSERT_EQ((size_t)t1 + 17, (size_t)rv);
310
311 rv = truffleExec(mask1, mask2, (u8 *)t2 + i, (u8 *)t2 + strlen(t1));
312
313 ASSERT_EQ((size_t)t2 + 17, (size_t)rv);
314
315 rv = truffleExec(mask1, mask2, (u8 *)t3 + i, (u8 *)t3 + strlen(t3));
316
317 ASSERT_EQ((size_t)t3 + 17, (size_t)rv);
318
319 rv = truffleExec(mask1, mask2, (u8 *)t4 + i, (u8 *)t4 + strlen(t4));
320
321 ASSERT_EQ((size_t)t4 + 17, (size_t)rv);
322 }
323 }
324
TEST(Truffle,ExecMatch5)325 TEST(Truffle, ExecMatch5) {
326 m128 mask1, mask2;
327
328 CharReach chars;
329
330 chars.set('a');
331
332 truffleBuildMasks(chars, (u8 *)&mask1, (u8 *)&mask2);
333
334 char t1[] = "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb";
335
336 for (size_t i = 0; i < 31; i++) {
337 t1[48 - i] = 'a';
338 const u8 *rv = truffleExec(mask1, mask2, (u8 *)t1, (u8 *)t1 + strlen(t1));
339
340 ASSERT_EQ((size_t)&t1[48 - i], (size_t)rv);
341 }
342 }
343
TEST(Truffle,ExecMatch6)344 TEST(Truffle, ExecMatch6) {
345 m128 mask1, mask2;
346
347 CharReach chars;
348
349 // [0-Z] - includes some graph chars
350 chars.setRange('0', 'Z');
351
352 truffleBuildMasks(chars, (u8 *)&mask1, (u8 *)&mask2);
353
354 std::array<u8, 128> t1;
355 t1.fill('*'); // it's full of stars!
356
357 for (u8 c = '0'; c <= 'Z'; c++) {
358 t1[17] = c;
359 const u8 *rv = truffleExec(mask1, mask2, (u8 *)t1.data(), (u8 *)t1.data() + 128);
360
361 ASSERT_EQ((size_t)t1.data() + 17, (size_t)rv);
362 }
363 }
364
TEST(Truffle,ExecMatch7)365 TEST(Truffle, ExecMatch7) {
366 m128 mask1, mask2;
367
368 CharReach chars;
369
370 // hi bits
371 chars.setRange(127, 255);
372
373 truffleBuildMasks(chars, (u8 *)&mask1, (u8 *)&mask2);
374
375 std::array<u8, 128> t1;
376 t1.fill('*'); // it's full of stars!
377
378 for (unsigned int c = 127; c <= 255; c++) {
379 t1[40] = (u8)c;
380 const u8 *rv = truffleExec(mask1, mask2, (u8 *)t1.data(), (u8 *)t1.data() + 128);
381
382 ASSERT_EQ((size_t)t1.data() + 40, (size_t)rv);
383 }
384 }
385
TEST(ReverseTruffle,ExecNoMatch1)386 TEST(ReverseTruffle, ExecNoMatch1) {
387 m128 mask1, mask2;
388
389 CharReach chars;
390 chars.set('a');
391
392 truffleBuildMasks(chars, (u8 *)&mask1, (u8 *)&mask2);
393
394 char t[] = " bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb";
395 char *t1 = t + 1;
396 size_t len = strlen(t1);
397
398 for (size_t i = 0; i < 16; i++) {
399 const u8 *rv = rtruffleExec(mask1, mask2, (u8 *)t1, (u8 *)t1 + len - i);
400 ASSERT_EQ((const u8 *)t, rv);
401 }
402 }
403
TEST(ReverseTruffle,ExecNoMatch2)404 TEST(ReverseTruffle, ExecNoMatch2) {
405 m128 mask1, mask2;
406
407 CharReach chars;
408
409 chars.set('a');
410 chars.set('B');
411
412 truffleBuildMasks(chars, (u8 *)&mask1, (u8 *)&mask2);
413
414 char t[] = " bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb";
415 char *t1 = t + 1;
416 size_t len = strlen(t1);
417
418 for (size_t i = 0; i < 16; i++) {
419 const u8 *rv = rtruffleExec(mask1, mask2, (u8 *)t1, (u8 *)t1 + len - i);
420 ASSERT_EQ((const u8 *)t, rv);
421 }
422 }
423
TEST(ReverseTruffle,ExecNoMatch3)424 TEST(ReverseTruffle, ExecNoMatch3) {
425 m128 mask1, mask2;
426
427 CharReach chars;
428 chars.set('V'); /* V = 0x56, e = 0x65 */
429
430 truffleBuildMasks(chars, (u8 *)&mask1, (u8 *)&mask2);
431
432 char t[] = "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee";
433 char *t1 = t + 1;
434 size_t len = strlen(t1);
435
436 for (size_t i = 0; i < 16; i++) {
437 const u8 *rv = rtruffleExec(mask1, mask2, (u8 *)t1, (u8 *)t1 + len - i);
438 ASSERT_EQ((const u8 *)t, rv);
439 }
440 }
441
TEST(ReverseTruffle,ExecMiniMatch0)442 TEST(ReverseTruffle, ExecMiniMatch0) {
443 m128 lo, hi;
444
445 CharReach chars;
446 chars.set('a');
447
448 truffleBuildMasks(chars, (u8 *)&lo, (u8 *)&hi);
449
450 char t1[] = "a";
451
452 const u8 *rv = rtruffleExec(lo, hi, (u8 *)t1, (u8 *)t1 + strlen(t1));
453
454 ASSERT_EQ((size_t)t1, (size_t)rv);
455 }
456
TEST(ReverseTruffle,ExecMiniMatch1)457 TEST(ReverseTruffle, ExecMiniMatch1) {
458 m128 mask1, mask2;
459
460 CharReach chars;
461 chars.set('a');
462
463 truffleBuildMasks(chars, (u8 *)&mask1, (u8 *)&mask2);
464
465 /* 0123456789012345678901234567890 */
466 char t1[] = "bbbbbbbabbbb";
467 size_t len = strlen(t1);
468
469 const u8 *rv = rtruffleExec(mask1, mask2, (u8 *)t1, (u8 *)t1 + len);
470 ASSERT_NE((const u8 *)t1 - 1, rv); // not found
471 EXPECT_EQ('a', (char)*rv);
472 ASSERT_EQ((const u8 *)t1 + 7, rv);
473 }
474
TEST(ReverseTruffle,ExecMiniMatch2)475 TEST(ReverseTruffle, ExecMiniMatch2) {
476 m128 mask1, mask2;
477
478 CharReach chars;
479 chars.set('a');
480
481 truffleBuildMasks(chars, (u8 *)&mask1, (u8 *)&mask2);
482
483 /* 0123456789012345678901234567890 */
484 char t1[] = "babbbbbabbbb";
485 size_t len = strlen(t1);
486
487 const u8 *rv = rtruffleExec(mask1, mask2, (u8 *)t1, (u8 *)t1 + len);
488 ASSERT_NE((const u8 *)t1 - 1, rv); // not found
489 EXPECT_EQ('a', (char)*rv);
490 ASSERT_EQ((const u8 *)t1 + 7, rv);
491 }
492
493
TEST(ReverseTruffle,ExecMatch1)494 TEST(ReverseTruffle, ExecMatch1) {
495 m128 mask1, mask2;
496
497 CharReach chars;
498 chars.set('a');
499
500 truffleBuildMasks(chars, (u8 *)&mask1, (u8 *)&mask2);
501
502 /* 0123456789012345678901234567890 */
503 char t1[] = "bbbbbbabbbbbbbbbbabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb";
504 size_t len = strlen(t1);
505
506 for (size_t i = 0; i < 16; i++) {
507 const u8 *rv = rtruffleExec(mask1, mask2, (u8 *)t1, (u8 *)t1 + len - i);
508 ASSERT_NE((const u8 *)t1 - 1, rv); // not found
509 EXPECT_EQ('a', (char)*rv);
510 ASSERT_EQ((const u8 *)t1 + 17, rv);
511 }
512 }
513
TEST(ReverseTruffle,ExecMatch2)514 TEST(ReverseTruffle, ExecMatch2) {
515 m128 mask1, mask2;
516
517 CharReach chars;
518 chars.set('a');
519
520 truffleBuildMasks(chars, (u8 *)&mask1, (u8 *)&mask2);
521
522 /* 0123456789012345678901234567890 */
523 char t1[] = "bbbbabbbbbbbbbbbbaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbb";
524 size_t len = strlen(t1);
525
526 for (size_t i = 0; i < 16; i++) {
527 const u8 *rv = rtruffleExec(mask1, mask2, (u8 *)t1, (u8 *)t1 + len - i);
528 ASSERT_NE((const u8 *)t1 - 1, rv); // not found
529 EXPECT_EQ('a', (char)*rv);
530 ASSERT_EQ((const u8 *)t1 + 32, rv);
531 }
532 }
533
TEST(ReverseTruffle,ExecMatch3)534 TEST(ReverseTruffle, ExecMatch3) {
535 m128 mask1, mask2;
536
537 CharReach chars;
538 chars.set('a');
539 chars.set('B');
540
541 truffleBuildMasks(chars, (u8 *)&mask1, (u8 *)&mask2);
542
543 /* 0123456789012345678901234567890 */
544 char t1[] = "bbbbbbbbbbbbbbbbbaaaaaaaaaaaaaaaBbbbbbbbbbbbbbbbbbbbbbbbbbbbb";
545 size_t len = strlen(t1);
546
547 for (size_t i = 0; i < 16; i++) {
548 const u8 *rv = rtruffleExec(mask1, mask2, (u8 *)t1, (u8 *)t1 + len - i);
549 ASSERT_NE((const u8 *)t1 - 1, rv); // not found
550 EXPECT_EQ('B', (char)*rv);
551 ASSERT_EQ((const u8 *)t1 + 32, rv);
552 }
553
554 // check that we match the 'a' bytes as well.
555 ASSERT_EQ('B', t1[32]);
556 t1[32] = 'b';
557 for (size_t i = 0; i < 16; i++) {
558 const u8 *rv = rtruffleExec(mask1, mask2, (u8 *)t1, (u8 *)t1 + len - i);
559 ASSERT_NE((const u8 *)t1 - 1, rv); // not found
560 EXPECT_EQ('a', (char)*rv);
561 ASSERT_EQ((const u8 *)t1 + 31, rv);
562 }
563 }
564
TEST(ReverseTruffle,ExecMatch4)565 TEST(ReverseTruffle, ExecMatch4) {
566 m128 mask1, mask2;
567
568 CharReach chars;
569 chars.set('a');
570 chars.set('C');
571 chars.set('A');
572 chars.set('c');
573
574 truffleBuildMasks(chars, (u8 *)&mask1, (u8 *)&mask2);
575
576 /* 0123456789012345678901234567890 */
577 char t1[] = "bbbbbbbbbbbbbbbbbaaaaaaaaaaaaaaaAbbbbbbbbbbbbbbbbbbbbbbbbbbbb";
578 char t2[] = "bbbbbbbbbbbbbbbbbaaaaaaaaaaaaaaaCbbbbbbbbbbbbbbbbbbbbbbbbbbbb";
579 char t3[] = "bbbbbbbbbbbbbbbbbaaaaaaaaaaaaaaacbbbbbbbbbbbbbbbbbbbbbbbbbbbb";
580 char t4[] = "bbbbbbbbbbbbbbbbbaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbb";
581 size_t len = strlen(t1);
582
583 for (size_t i = 0; i < 16; i++) {
584 const u8 *rv = rtruffleExec(mask1, mask2, (u8 *)t1, (u8 *)t1 + len - i);
585 EXPECT_EQ('A', (char)*rv);
586 ASSERT_EQ((const u8 *)t1 + 32, rv);
587
588 rv = rtruffleExec(mask1, mask2, (u8 *)t2, (u8 *)t2 + len - i);
589 EXPECT_EQ('C', (char)*rv);
590 ASSERT_EQ((const u8 *)t2 + 32, rv);
591
592 rv = rtruffleExec(mask1, mask2, (u8 *)t3, (u8 *)t3 + len - i);
593 EXPECT_EQ('c', (char)*rv);
594 ASSERT_EQ((const u8 *)t3 + 32, rv);
595
596 rv = rtruffleExec(mask1, mask2, (u8 *)t4, (u8 *)t4 + len - i);
597 EXPECT_EQ('a', (char)*rv);
598 ASSERT_EQ((const u8 *)t4 + 32, rv);
599 }
600 }
601
TEST(ReverseTruffle,ExecMatch5)602 TEST(ReverseTruffle, ExecMatch5) {
603 m128 mask1, mask2;
604
605 CharReach chars;
606 chars.set('a');
607
608 truffleBuildMasks(chars, (u8 *)&mask1, (u8 *)&mask2);
609
610 char t1[] = "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb";
611 size_t len = strlen(t1);
612
613 for (size_t i = 0; i < len; i++) {
614 t1[i] = 'a';
615 const u8 *rv = rtruffleExec(mask1, mask2, (u8 *)t1, (u8 *)t1 + len);
616
617 ASSERT_EQ((const u8 *)t1 + i, rv);
618 }
619 }
620