Merge branch 'regex-errors-msg-cleanups' into 'main'

gregex: Use pcre2 error messages if we don't provide a specific one

See merge request GNOME/glib!2913
This commit is contained in:
Philip Withnall 2022-10-12 13:48:29 +00:00
commit 0cdbc530ca
2 changed files with 59 additions and 9 deletions

View File

@ -444,8 +444,25 @@ get_pcre2_bsr_match_options (GRegexMatchFlags match_flags)
return 0;
}
static char *
get_pcre2_error_string (int errcode)
{
PCRE2_UCHAR8 error_msg[2048];
int err_length;
err_length = pcre2_get_error_message (errcode, error_msg,
G_N_ELEMENTS (error_msg));
if (err_length <= 0)
return NULL;
/* The array is always filled with a trailing zero */
g_assert ((size_t) err_length < G_N_ELEMENTS (error_msg));
return g_memdup2 (error_msg, err_length + 1);
}
static const gchar *
match_error (gint errcode)
translate_match_error (gint errcode)
{
switch (errcode)
{
@ -454,7 +471,7 @@ match_error (gint errcode)
break;
case PCRE2_ERROR_NULL:
/* NULL argument, this should not happen in GRegex */
g_warning ("A NULL argument was passed to PCRE");
g_critical ("A NULL argument was passed to PCRE");
break;
case PCRE2_ERROR_BADOPTION:
return "bad options";
@ -499,7 +516,24 @@ match_error (gint errcode)
default:
break;
}
return _("unknown error");
return NULL;
}
static char *
get_match_error_message (int errcode)
{
const char *msg = translate_match_error (errcode);
char *error_string;
if (msg)
return g_strdup (msg);
error_string = get_pcre2_error_string (errcode);
if (error_string)
return error_string;
return g_strdup (_("unknown error"));
}
static void
@ -731,7 +765,6 @@ translate_compile_error (gint *errcode, const gchar **errmsg)
case PCRE2_ERROR_INTERNAL_BAD_CODE:
case PCRE2_ERROR_INTERNAL_BAD_CODE_IN_SKIP:
*errcode = G_REGEX_ERROR_INTERNAL;
*errmsg = _("internal error");
break;
case PCRE2_ERROR_INVALID_SUBPATTERN_NAME:
case PCRE2_ERROR_CLASS_INVALID_RANGE:
@ -760,12 +793,10 @@ translate_compile_error (gint *errcode, const gchar **errmsg)
case PCRE2_ERROR_BAD_LITERAL_OPTIONS:
default:
*errcode = G_REGEX_ERROR_COMPILE;
*errmsg = _("internal error");
break;
}
g_assert (*errcode != -1);
g_assert (*errmsg != NULL);
}
/* GMatchInfo */
@ -1084,9 +1115,12 @@ g_match_info_next (GMatchInfo *match_info,
if (IS_PCRE2_ERROR (match_info->matches))
{
gchar *error_msg = get_match_error_message (match_info->matches);
g_set_error (error, G_REGEX_ERROR, G_REGEX_ERROR_MATCH,
_("Error while matching regular expression %s: %s"),
match_info->regex->pattern, match_error (match_info->matches));
match_info->regex->pattern, error_msg);
g_clear_pointer (&error_msg, g_free);
return FALSE;
}
else if (match_info->matches == 0)
@ -1791,11 +1825,20 @@ regex_compile (const gchar *pattern,
{
GError *tmp_error;
gchar *offset_str;
gchar *pcre2_errmsg = NULL;
int original_errcode;
/* Translate the PCRE error code to GRegexError and use a translated
* error message if possible */
original_errcode = errcode;
translate_compile_error (&errcode, &errmsg);
if (!errmsg)
{
errmsg = _("unknown error");
pcre2_errmsg = get_pcre2_error_string (original_errcode);
}
/* PCRE uses byte offsets but we want to show character offsets */
erroffset = g_utf8_pointer_to_offset (pattern, &pattern[erroffset]);
@ -1803,9 +1846,11 @@ regex_compile (const gchar *pattern,
tmp_error = g_error_new (G_REGEX_ERROR, errcode,
_("Error while compiling regular expression %s "
"at char %s: %s"),
pattern, offset_str, errmsg);
pattern, offset_str,
pcre2_errmsg ? pcre2_errmsg : errmsg);
g_propagate_error (error, tmp_error);
g_free (offset_str);
g_clear_pointer (&pcre2_errmsg, g_free);
return NULL;
}
@ -2393,9 +2438,12 @@ g_regex_match_all_full (const GRegex *regex,
}
else if (IS_PCRE2_ERROR (info->matches))
{
gchar *error_msg = get_match_error_message (info->matches);
g_set_error (error, G_REGEX_ERROR, G_REGEX_ERROR_MATCH,
_("Error while matching regular expression %s: %s"),
regex->pattern, match_error (info->matches));
regex->pattern, error_msg);
g_clear_pointer (&error_msg, g_free);
}
else if (info->matches != PCRE2_ERROR_NOMATCH)
{

View File

@ -2564,6 +2564,7 @@ G_GNUC_END_IGNORE_DEPRECATIONS
TEST_NEW_FAIL ("[a-z", 0, G_REGEX_ERROR_UNTERMINATED_CHARACTER_CLASS);
TEST_NEW_FAIL ("[\\B]", 0, G_REGEX_ERROR_INVALID_ESCAPE_IN_CHARACTER_CLASS);
TEST_NEW_FAIL ("[z-a]", 0, G_REGEX_ERROR_RANGE_OUT_OF_ORDER);
TEST_NEW_FAIL ("^[[:alnum:]-_.]+$", 0, G_REGEX_ERROR_COMPILE);
TEST_NEW_FAIL ("{2,4}", 0, G_REGEX_ERROR_NOTHING_TO_REPEAT);
TEST_NEW_FAIL ("a(?u)", 0, G_REGEX_ERROR_UNRECOGNIZED_CHARACTER);
TEST_NEW_FAIL ("a(?<$foo)bar", 0, G_REGEX_ERROR_MISSING_SUBPATTERN_NAME);
@ -2640,6 +2641,7 @@ G_GNUC_END_IGNORE_DEPRECATIONS
TEST_MATCH_SIMPLE("a", "a", G_REGEX_CASELESS, 0, TRUE);
TEST_MATCH_SIMPLE("a", "A", G_REGEX_CASELESS, 0, TRUE);
TEST_MATCH_SIMPLE("\\C\\C", "ab", G_REGEX_OPTIMIZE | G_REGEX_RAW, 0, TRUE);
TEST_MATCH_SIMPLE("^[[:alnum:]\\-_.]+$", "admin-foo", 0, 0, TRUE);
/* These are needed to test extended properties. */
TEST_MATCH_SIMPLE(AGRAVE, AGRAVE, G_REGEX_CASELESS, 0, TRUE);
TEST_MATCH_SIMPLE(AGRAVE, AGRAVE_UPPER, G_REGEX_CASELESS, 0, TRUE);