188 lines
6.5 KiB
Diff
188 lines
6.5 KiB
Diff
From 6caf952e48dbed40b5dcff01a94f57ba079b526c Mon Sep 17 00:00:00 2001
|
||
From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= <mail@3v1n0.net>
|
||
Date: Tue, 20 Sep 2022 18:06:35 +0200
|
||
Subject: [PATCH] gregex: Use pcre2 error messages if we don't provide a
|
||
specific one
|
||
|
||
In case we got a compilation or match error we should try to provide
|
||
some useful error message, if possible, before returning a quite obscure
|
||
"internal error" or "unknown error" string.
|
||
|
||
So rely on PCRE2 strings even if they're not translated they can provide
|
||
better information than the ones we're currently giving.
|
||
|
||
Related to: https://gitlab.gnome.org/GNOME/glib/-/issues/2691
|
||
Related to: https://gitlab.gnome.org/GNOME/glib/-/issues/2760
|
||
|
||
Conflict:NA
|
||
Reference:https://gitlab.gnome.org/GNOME/glib/-/commit/6caf952e48dbed40b5dcff01a94f57ba079b526c
|
||
|
||
---
|
||
glib/gregex.c | 64 ++++++++++++++++++++++++++++++++++++++++------
|
||
glib/tests/regex.c | 2 ++
|
||
2 files changed, 58 insertions(+), 8 deletions(-)
|
||
|
||
diff --git a/glib/gregex.c b/glib/gregex.c
|
||
index 220a1a11ac..fcc28d62f4 100644
|
||
--- a/glib/gregex.c
|
||
+++ b/glib/gregex.c
|
||
@@ -456,8 +456,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)
|
||
{
|
||
@@ -511,7 +528,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
|
||
@@ -743,7 +777,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:
|
||
@@ -772,12 +805,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 */
|
||
@@ -1096,9 +1127,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)
|
||
@@ -1800,11 +1834,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]);
|
||
|
||
@@ -1812,9 +1855,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;
|
||
}
|
||
@@ -2402,9 +2447,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)
|
||
{
|
||
diff --git a/glib/tests/regex.c b/glib/tests/regex.c
|
||
index 9803d49659..52af212f29 100644
|
||
--- a/glib/tests/regex.c
|
||
+++ b/glib/tests/regex.c
|
||
@@ -2560,6 +2560,7 @@ main (int argc, char *argv[])
|
||
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);
|
||
@@ -2636,6 +2637,7 @@ main (int argc, char *argv[])
|
||
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);
|
||
--
|
||
GitLab
|
||
|