summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilip Withnall <pwithnall@endlessos.org>2023-01-11 11:32:34 +0000
committerPhilip Withnall <pwithnall@endlessos.org>2023-01-12 15:37:21 +0000
commit0d99c57e22ec9be9eb82fd237d0ff80cf26bf5d5 (patch)
tree26c37f3aff1ecf6ac3f8ee56690899553a991387
parent3ba701a4993b2e3a6dd899a3439534ef8d316fbc (diff)
downloadglib-0d99c57e22ec9be9eb82fd237d0ff80cf26bf5d5.tar.gz
gregex: Prevent invalid memory access for unmatched subpatterns
Based on a test by Emmanuel Pacaud. Signed-off-by: Philip Withnall <pwithnall@endlessos.org> Fixes: #2881
-rw-r--r--glib/gregex.c4
-rw-r--r--glib/tests/regex.c34
2 files changed, 36 insertions, 2 deletions
diff --git a/glib/gregex.c b/glib/gregex.c
index 41ad675a7..c1955c6ce 100644
--- a/glib/gregex.c
+++ b/glib/gregex.c
@@ -1492,8 +1492,8 @@ get_matched_substring_number (const GMatchInfo *match_info,
for (entry = (guchar*) first; entry <= (guchar*) last; entry += entrysize)
{
- gint n = (entry[0] << 8) + entry[1];
- if (match_info->offsets[n*2] >= 0)
+ guint n = (entry[0] << 8) + entry[1];
+ if (n * 2 < match_info->n_offsets && match_info->offsets[n * 2] >= 0)
return n;
}
diff --git a/glib/tests/regex.c b/glib/tests/regex.c
index 847676e1b..cf2bb8199 100644
--- a/glib/tests/regex.c
+++ b/glib/tests/regex.c
@@ -2480,6 +2480,39 @@ test_jit_unsupported_matching_options (void)
g_regex_unref (regex);
}
+static void
+test_unmatched_named_subpattern (void)
+{
+ GRegex *regex = NULL;
+ GMatchInfo *match_info = NULL;
+ const char *string = "Test";
+
+ g_test_summary ("Test that unmatched subpatterns can still be queried");
+ g_test_bug ("https://gitlab.gnome.org/GNOME/glib/-/issues/2881");
+
+ regex = g_regex_new ("((?<Key>[^\\s\"'\\=]+)|\"(?<Key>[^\"]*)\"|'(?<Key>[^']*)')"
+ "(?:\\=((?<Value>[^\\s\"']+)|\"(?<Value>[^\"]*)\"|'(?<Value>[^']*)'))?",
+ G_REGEX_DUPNAMES, 0, NULL);
+
+ g_assert_true (g_regex_match (regex, string, 0, &match_info));
+
+ while (g_match_info_matches (match_info))
+ {
+ char *key = g_match_info_fetch_named (match_info, "Key");
+ char *value = g_match_info_fetch_named (match_info, "Value");
+
+ g_assert_cmpstr (key, ==, "Test");
+ g_assert_cmpstr (value, ==, "");
+
+ g_free (key);
+ g_free (value);
+ g_match_info_next (match_info, NULL);
+ }
+
+ g_match_info_unref (match_info);
+ g_regex_unref (regex);
+}
+
int
main (int argc, char *argv[])
{
@@ -2499,6 +2532,7 @@ main (int argc, char *argv[])
g_test_add_func ("/regex/max-lookbehind", test_max_lookbehind);
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);
/* 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);