mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-01-26 14:06:15 +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 */
|
GRegexMatchFlags orig_match_opts; /* options used as default match options, gregex values */
|
||||||
uint32_t jit_options; /* options which were enabled for jit compiler */
|
uint32_t jit_options; /* options which were enabled for jit compiler */
|
||||||
JITStatus jit_status; /* indicates the status of jit compiler for this compiled regex */
|
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. */
|
/* 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 */
|
/* no new options enabled */
|
||||||
if (new_jit_options == old_jit_options)
|
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);
|
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;
|
match_info->regex->jit_options = new_jit_options;
|
||||||
/* Set min stack size for JIT to 32KiB and max to 512KiB */
|
/* 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);
|
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);
|
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 ();
|
g_assert_not_reached ();
|
||||||
}
|
}
|
||||||
|
@ -2517,6 +2517,28 @@ test_unmatched_named_subpattern (void)
|
|||||||
g_regex_unref (regex);
|
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
|
int
|
||||||
main (int argc, char *argv[])
|
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/compile-errors", test_compile_errors);
|
||||||
g_test_add_func ("/regex/jit-unsupported-matching", test_jit_unsupported_matching_options);
|
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/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(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);
|
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