mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-01-12 15:36:17 +01:00
Merge branch 'wryun-gregex-handle-multiple-failed-optimise-matches-with-fallback' into 'main'
gregex: clean up usage of _GRegex.jit_status Closes #2824 See merge request GNOME/glib!3750
This commit is contained in:
commit
4608b87469
@ -252,6 +252,13 @@ struct _GRegex
|
||||
GRegexMatchFlags orig_match_opts; /* options used as default match options, gregex values */
|
||||
uint32_t jit_options; /* options which were enabled for jit compiler */
|
||||
JITStatus jit_status; /* indicates the status of jit compiler for this compiled regex */
|
||||
/* The jit_status here does _not_ correspond to whether we used the JIT in the last invocation,
|
||||
* which may be affected by match_options or a JIT_STACK_LIMIT error, but whether it was ever
|
||||
* enabled for the current regex AND current set of jit_options.
|
||||
* JIT_STATUS_DEFAULT means enablement was never tried,
|
||||
* JIT_STATUS_ENABLED means it was tried and successful (even if we're not currently using it),
|
||||
* and JIT_STATUS_DISABLED means it was tried and failed (so we shouldn't try again).
|
||||
*/
|
||||
};
|
||||
|
||||
/* TRUE if ret is an error code, FALSE otherwise. */
|
||||
@ -918,35 +925,47 @@ enable_jit_with_match_options (GMatchInfo *match_info,
|
||||
|
||||
/* no new options enabled */
|
||||
if (new_jit_options == old_jit_options)
|
||||
return match_info->regex->jit_status;
|
||||
{
|
||||
g_assert (match_info->regex->jit_status != JIT_STATUS_DEFAULT);
|
||||
return match_info->regex->jit_status;
|
||||
}
|
||||
|
||||
retval = pcre2_jit_compile (match_info->regex->pcre_re, new_jit_options);
|
||||
switch (retval)
|
||||
if (retval == 0)
|
||||
{
|
||||
case 0: /* JIT enabled successfully */
|
||||
match_info->regex->jit_status = JIT_STATUS_ENABLED;
|
||||
|
||||
match_info->regex->jit_options = new_jit_options;
|
||||
/* Set min stack size for JIT to 32KiB and max to 512KiB */
|
||||
match_info->jit_stack = pcre2_jit_stack_create (1 << 15, 1 << 19, NULL);
|
||||
pcre2_jit_stack_assign (match_info->match_context, NULL, match_info->jit_stack);
|
||||
return JIT_STATUS_ENABLED;
|
||||
case PCRE2_ERROR_NOMEMORY:
|
||||
g_debug ("JIT compilation was requested with G_REGEX_OPTIMIZE, "
|
||||
"but JIT was unable to allocate executable memory for the "
|
||||
"compiler. Falling back to interpretive code.");
|
||||
return JIT_STATUS_DISABLED;
|
||||
case PCRE2_ERROR_JIT_BADOPTION:
|
||||
g_debug ("JIT compilation was requested with G_REGEX_OPTIMIZE, "
|
||||
"but JIT support is not available. Falling back to "
|
||||
"interpretive code.");
|
||||
return JIT_STATUS_DISABLED;
|
||||
break;
|
||||
default:
|
||||
g_debug ("JIT compilation was requested with G_REGEX_OPTIMIZE, "
|
||||
"but request for JIT support had unexpectedly failed (error %d). "
|
||||
"Falling back to interpretive code.", retval);
|
||||
return JIT_STATUS_DISABLED;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
match_info->regex->jit_status = JIT_STATUS_DISABLED;
|
||||
|
||||
switch (retval)
|
||||
{
|
||||
case PCRE2_ERROR_NOMEMORY:
|
||||
g_debug ("JIT compilation was requested with G_REGEX_OPTIMIZE, "
|
||||
"but JIT was unable to allocate executable memory for the "
|
||||
"compiler. Falling back to interpretive code.");
|
||||
break;
|
||||
case PCRE2_ERROR_JIT_BADOPTION:
|
||||
g_debug ("JIT compilation was requested with G_REGEX_OPTIMIZE, "
|
||||
"but JIT support is not available. Falling back to "
|
||||
"interpretive code.");
|
||||
break;
|
||||
default:
|
||||
g_debug ("JIT compilation was requested with G_REGEX_OPTIMIZE, "
|
||||
"but request for JIT support had unexpectedly failed (error %d). "
|
||||
"Falling back to interpretive code.",
|
||||
retval);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return match_info->regex->jit_status;
|
||||
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
|
@ -2517,6 +2517,28 @@ test_unmatched_named_subpattern (void)
|
||||
g_regex_unref (regex);
|
||||
}
|
||||
|
||||
static void
|
||||
test_compiled_regex_after_jit_failure (void)
|
||||
{
|
||||
GRegex *regex = NULL;
|
||||
char string[LARGE_TEST_STRING_LEN];
|
||||
|
||||
g_test_summary ("Test that failed OPTIMIZE regex doesn't cause issues on subsequent matches");
|
||||
g_test_bug ("https://gitlab.gnome.org/GNOME/glib/-/issues/2824");
|
||||
|
||||
regex = g_regex_new ("^(?:[ \t\n]|[^[:cntrl:]])*$", G_REGEX_OPTIMIZE, 0, NULL);
|
||||
|
||||
/* Generate large enough string to cause JIT failure on this regex. */
|
||||
memset (string, '*', LARGE_TEST_STRING_LEN);
|
||||
string[LARGE_TEST_STRING_LEN - 1] = '\0';
|
||||
|
||||
g_assert_true (g_regex_match (regex, string, 0, NULL));
|
||||
/* Second assert here is the key - does the first JIT overflow mess up our state? */
|
||||
g_assert_true (g_regex_match (regex, string, 0, NULL));
|
||||
|
||||
g_regex_unref (regex);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
@ -2537,6 +2559,7 @@ main (int argc, char *argv[])
|
||||
g_test_add_func ("/regex/compile-errors", test_compile_errors);
|
||||
g_test_add_func ("/regex/jit-unsupported-matching", test_jit_unsupported_matching_options);
|
||||
g_test_add_func ("/regex/unmatched-named-subpattern", test_unmatched_named_subpattern);
|
||||
g_test_add_func ("/regex/compiled-regex-after-jit-failure", test_compiled_regex_after_jit_failure);
|
||||
|
||||
/* TEST_NEW(pattern, compile_opts, match_opts) */
|
||||
TEST_NEW("[A-Z]+", G_REGEX_CASELESS | G_REGEX_EXTENDED | G_REGEX_OPTIMIZE, G_REGEX_MATCH_NOTBOL | G_REGEX_MATCH_PARTIAL);
|
||||
|
Loading…
Reference in New Issue
Block a user