@@ -262,6 +262,31 @@ static void pcre2_free(void *pointer, MAYBE_UNUSED void *memory_data)
262262 free (pointer );
263263}
264264
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+
265290static void compile_pcre2_pattern (struct grep_pat * p , const struct grep_opt * opt )
266291{
267292 int error ;
@@ -317,8 +342,29 @@ static void compile_pcre2_pattern(struct grep_pat *p, const struct grep_opt *opt
317342 pcre2_config (PCRE2_CONFIG_JIT , & p -> pcre2_jit_on );
318343 if (p -> pcre2_jit_on ) {
319344 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+ }
322368
323369 /*
324370 * The pcre2_config(PCRE2_CONFIG_JIT, ...) call just
0 commit comments