@@ -262,6 +262,31 @@ static void pcre2_free(void *pointer, MAYBE_UNUSED void *memory_data)
262
262
free (pointer );
263
263
}
264
264
265
+ static int pcre2_jit_functional (void )
266
+ {
267
+ static int jit_working = -1 ;
268
+ pcre2_code * code ;
269
+ size_t off ;
270
+ int err ;
271
+
272
+ if (jit_working != -1 )
273
+ return jit_working ;
274
+
275
+ /*
276
+ * Try to JIT compile a simple pattern to probe if the JIT is
277
+ * working in general. It might fail for systems where creating
278
+ * memory mappings for runtime code generation is restricted.
279
+ */
280
+ code = pcre2_compile ((PCRE2_SPTR )"." , 1 , 0 , & err , & off , NULL );
281
+ if (!code )
282
+ return 0 ;
283
+
284
+ jit_working = pcre2_jit_compile (code , PCRE2_JIT_COMPLETE ) == 0 ;
285
+ pcre2_code_free (code );
286
+
287
+ return jit_working ;
288
+ }
289
+
265
290
static void compile_pcre2_pattern (struct grep_pat * p , const struct grep_opt * opt )
266
291
{
267
292
int error ;
@@ -317,8 +342,29 @@ static void compile_pcre2_pattern(struct grep_pat *p, const struct grep_opt *opt
317
342
pcre2_config (PCRE2_CONFIG_JIT , & p -> pcre2_jit_on );
318
343
if (p -> pcre2_jit_on ) {
319
344
jitret = pcre2_jit_compile (p -> pcre2_pattern , PCRE2_JIT_COMPLETE );
320
- if (jitret )
321
- die ("Couldn't JIT the PCRE2 pattern '%s', got '%d'\n" , p -> pattern , jitret );
345
+ if (jitret == PCRE2_ERROR_NOMEMORY && !pcre2_jit_functional ()) {
346
+ /*
347
+ * Even though pcre2_config(PCRE2_CONFIG_JIT, ...)
348
+ * indicated JIT support, the library might still
349
+ * fail to generate JIT code for various reasons,
350
+ * e.g. when SELinux's 'deny_execmem' or PaX's
351
+ * MPROTECT prevent creating W|X memory mappings.
352
+ *
353
+ * Instead of faling hard, fall back to interpreter
354
+ * mode, just as if the pattern was prefixed with
355
+ * '(*NO_JIT)'.
356
+ */
357
+ p -> pcre2_jit_on = 0 ;
358
+ return ;
359
+ } else if (jitret ) {
360
+ int need_clip = p -> patternlen > 64 ;
361
+ int clip_len = need_clip ? 64 : p -> patternlen ;
362
+ die ("Couldn't JIT the PCRE2 pattern '%.*s'%s, got '%d'%s" ,
363
+ clip_len , p -> pattern , need_clip ? "..." : "" , jitret ,
364
+ pcre2_jit_functional ()
365
+ ? "\nPerhaps prefix (*NO_JIT) to your pattern?"
366
+ : "" );
367
+ }
322
368
323
369
/*
324
370
* The pcre2_config(PCRE2_CONFIG_JIT, ...) call just
0 commit comments