@@ -34,7 +34,7 @@ Written by Philip Hazel, October 2016
34
34
#define ALLOWED_MATCH_OPTIONS \
35
35
(PCRE2_ANCHORED|PCRE2_ENDANCHORED|PCRE2_NOTBOL|PCRE2_NOTEOL|PCRE2_NOTEMPTY| \
36
36
PCRE2_NOTEMPTY_ATSTART|PCRE2_PARTIAL_HARD| \
37
- PCRE2_PARTIAL_SOFT|PCRE2_NO_JIT )
37
+ PCRE2_PARTIAL_SOFT)
38
38
39
39
/* This is the callout function. Its only purpose is to halt matching if there
40
40
are more than 100 callouts, as one way of stopping too much time being spent on
@@ -58,40 +58,34 @@ int LLVMFuzzerTestOneInput(const unsigned char *data, size_t size)
58
58
{
59
59
uint32_t compile_options ;
60
60
uint32_t match_options ;
61
- uint32_t random_options ;
61
+ uint64_t random_options ;
62
62
pcre2_match_data * match_data = NULL ;
63
+ pcre2_match_data * match_data_jit = NULL ;
63
64
pcre2_match_context * match_context = NULL ;
64
65
size_t match_size ;
65
66
int dfa_workspace [DFA_WORKSPACE_COUNT ];
66
- int r1 , r2 ;
67
67
int i ;
68
68
69
- if (size < 1 ) return 0 ;
69
+ if (size < sizeof ( random_options )) return -1 ;
70
70
71
71
/* Limiting the length of the subject for matching stops fruitless searches
72
72
in large trees taking too much time. */
73
73
74
- match_size = (size > MAX_MATCH_SIZE )? MAX_MATCH_SIZE : size ;
75
-
76
- /* Figure out some options to use. Initialize the random number to ensure
77
- repeatability. Ensure that we get a 32-bit unsigned random number for testing
78
- options. (RAND_MAX is required to be at least 32767, but is commonly
79
- 2147483647, which excludes the top bit.) */
74
+ random_options = * (uint64_t * )(data );
75
+ data += sizeof (random_options );
76
+ size -= sizeof (random_options );
80
77
81
- srand ((unsigned int )(data [size /2 ]));
82
- r1 = rand () & 0xffff ;
83
- r2 = rand () & 0xffff ;
84
- random_options = ((uint32_t )r1 << 16 ) | (uint32_t )r2 ;
78
+ match_size = (size > MAX_MATCH_SIZE )? MAX_MATCH_SIZE : size ;
85
79
86
80
/* Ensure that all undefined option bits are zero (waste of time trying them)
87
81
and also that PCRE2_NO_UTF_CHECK is unset, as there is no guarantee that the
88
82
input is UTF-8. Also unset PCRE2_NEVER_UTF and PCRE2_NEVER_UCP as there is no
89
83
reason to disallow UTF and UCP. Force PCRE2_NEVER_BACKSLASH_C to be set because
90
84
\C in random patterns is highly likely to cause a crash. */
91
85
92
- compile_options = (random_options & ALLOWED_COMPILE_OPTIONS ) |
86
+ compile_options = (( random_options >> 32 ) & ALLOWED_COMPILE_OPTIONS ) |
93
87
PCRE2_NEVER_BACKSLASH_C ;
94
- match_options = random_options & ALLOWED_MATCH_OPTIONS ;
88
+ match_options = ((( uint32_t ) random_options ) & ALLOWED_MATCH_OPTIONS ) | PCRE2_NO_JIT ;
95
89
96
90
/* Discard partial matching if PCRE2_ENDANCHORED is set, because they are not
97
91
allowed together and just give an immediate error return. */
@@ -105,7 +99,8 @@ likewise do the match with and without the options. */
105
99
for (i = 0 ; i < 2 ; i ++ )
106
100
{
107
101
uint32_t callout_count ;
108
- int errorcode ;
102
+ int errorcode , errorcode_jit ;
103
+ uint32_t ovector_count ;
109
104
PCRE2_SIZE erroroffset ;
110
105
pcre2_code * code ;
111
106
@@ -151,7 +146,7 @@ for (i = 0; i < 2; i++)
151
146
uint32_t save_match_options = match_options ;
152
147
153
148
#ifdef SUPPORT_JIT
154
- pcre2_jit_compile (code , PCRE2_JIT_COMPLETE );
149
+ int jit_ret = pcre2_jit_compile (code , PCRE2_JIT_COMPLETE );
155
150
#endif
156
151
157
152
/* Create match data and context blocks only when we first need them. Set
@@ -161,12 +156,13 @@ for (i = 0; i < 2; i++)
161
156
if (match_data == NULL )
162
157
{
163
158
match_data = pcre2_match_data_create (32 , NULL );
164
- if (match_data == NULL )
159
+ match_data_jit = pcre2_match_data_create (32 , NULL );
160
+ if (match_data == NULL || match_data_jit == NULL )
165
161
{
166
162
#ifdef STANDALONE
167
163
printf ("** Failed to create match data block\n" );
168
164
#endif
169
- return 0 ;
165
+ abort () ;
170
166
}
171
167
}
172
168
@@ -178,7 +174,7 @@ for (i = 0; i < 2; i++)
178
174
#ifdef STANDALONE
179
175
printf ("** Failed to create match context block\n" );
180
176
#endif
181
- return 0 ;
177
+ abort () ;
182
178
}
183
179
(void )pcre2_set_match_limit (match_context , 100 );
184
180
(void )pcre2_set_depth_limit (match_context , 100 );
@@ -217,7 +213,66 @@ for (i = 0; i < 2; i++)
217
213
}
218
214
#endif
219
215
220
- match_options = 0 ; /* For second time */
216
+ #ifdef SUPPORT_JIT
217
+ if (jit_ret >= 0 )
218
+ {
219
+ callout_count = 0 ;
220
+ errorcode_jit = pcre2_match (code , (PCRE2_SPTR )data , (PCRE2_SIZE )match_size , 0 ,
221
+ match_options & ~PCRE2_NO_JIT , match_data_jit , match_context );
222
+
223
+ if (errorcode_jit != errorcode )
224
+ {
225
+ printf ("JIT errorcode %d did not match original errorcode %d\n" , errorcode_jit , errorcode );
226
+ abort ();
227
+ }
228
+
229
+ ovector_count = pcre2_get_ovector_count (match_data );
230
+
231
+ if (ovector_count != pcre2_get_ovector_count (match_data_jit ))
232
+ {
233
+ puts ("JIT ovector count did not match original" );
234
+ abort ();
235
+ }
236
+
237
+ for (uint32_t ovector = 0 ; ovector < ovector_count ; ovector ++ )
238
+ {
239
+ PCRE2_UCHAR * bufferptr , * bufferptr_jit ;
240
+ PCRE2_SIZE bufflen , bufflen_jit ;
241
+
242
+ bufferptr = bufferptr_jit = NULL ;
243
+ bufflen = bufflen_jit = 0 ;
244
+
245
+ errorcode = pcre2_substring_get_bynumber (match_data , ovector , & bufferptr , & bufflen );
246
+ errorcode_jit = pcre2_substring_get_bynumber (match_data_jit , ovector , & bufferptr_jit , & bufflen_jit );
247
+
248
+ if (errorcode != errorcode_jit )
249
+ {
250
+ printf ("when extracting substring, JIT errorcode %d did not match original %d\n" , errorcode_jit , errorcode );
251
+ abort ();
252
+ }
253
+
254
+ if (errorcode >= 0 )
255
+ {
256
+ if (bufflen != bufflen_jit )
257
+ {
258
+ printf ("when extracting substring, JIT buffer length %zu did not match original %zu\n" , bufflen_jit , bufflen );
259
+ abort ();
260
+ }
261
+
262
+ if (memcmp (bufferptr , bufferptr_jit , bufflen ) != 0 )
263
+ {
264
+ puts ("when extracting substring, JIT buffer contents did not match original" );
265
+ abort ();
266
+ }
267
+ }
268
+
269
+ pcre2_substring_free (bufferptr );
270
+ pcre2_substring_free (bufferptr_jit );
271
+ }
272
+ }
273
+ #endif
274
+
275
+ match_options = PCRE2_NO_JIT ; /* For second time */
221
276
}
222
277
223
278
/* Match with DFA twice, with and without options. */
@@ -278,6 +333,7 @@ for (i = 0; i < 2; i++)
278
333
}
279
334
280
335
if (match_data != NULL ) pcre2_match_data_free (match_data );
336
+ if (match_data_jit != NULL ) pcre2_match_data_free (match_data_jit );
281
337
if (match_context != NULL ) pcre2_match_context_free (match_context );
282
338
283
339
return 0 ;
0 commit comments