From 0d99c57e22ec9be9eb82fd237d0ff80cf26bf5d5 Mon Sep 17 00:00:00 2001 From: Philip Withnall Date: Wed, 11 Jan 2023 11:32:34 +0000 Subject: [PATCH] gregex: Prevent invalid memory access for unmatched subpatterns Based on a test by Emmanuel Pacaud. Signed-off-by: Philip Withnall Fixes: #2881 --- glib/gregex.c | 4 ++-- glib/tests/regex.c | 34 ++++++++++++++++++++++++++++++++++ 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 ("((?[^\\s\"'\\=]+)|\"(?[^\"]*)\"|'(?[^']*)')" + "(?:\\=((?[^\\s\"']+)|\"(?[^\"]*)\"|'(?[^']*)'))?", + 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);