diff options
-rw-r--r-- | gio/gactiongroup.c | 25 | ||||
-rw-r--r-- | gio/gactiongroup.h | 2 | ||||
-rw-r--r-- | glib/gunidecomp.c | 39 | ||||
-rw-r--r-- | glib/tests/unicode-normalize.c | 38 |
4 files changed, 87 insertions, 17 deletions
diff --git a/gio/gactiongroup.c b/gio/gactiongroup.c index 73f8faf5f..a327195cc 100644 --- a/gio/gactiongroup.c +++ b/gio/gactiongroup.c @@ -133,9 +133,10 @@ static gboolean g_action_group_real_get_action_enabled (GActionGroup *action_group, const gchar *action_name) { - gboolean enabled = FALSE; + gboolean enabled; - g_action_group_query_action (action_group, action_name, &enabled, NULL, NULL, NULL, NULL); + if (!g_action_group_query_action (action_group, action_name, &enabled, NULL, NULL, NULL, NULL)) + return FALSE; return enabled; } @@ -144,9 +145,10 @@ static const GVariantType * g_action_group_real_get_action_parameter_type (GActionGroup *action_group, const gchar *action_name) { - const GVariantType *type = NULL; + const GVariantType *type; - g_action_group_query_action (action_group, action_name, NULL, &type, NULL, NULL, NULL); + if (!g_action_group_query_action (action_group, action_name, NULL, &type, NULL, NULL, NULL)) + return NULL; return type; } @@ -155,9 +157,10 @@ static const GVariantType * g_action_group_real_get_action_state_type (GActionGroup *action_group, const gchar *action_name) { - const GVariantType *type = NULL; + const GVariantType *type; - g_action_group_query_action (action_group, action_name, NULL, NULL, &type, NULL, NULL); + if (!g_action_group_query_action (action_group, action_name, NULL, NULL, &type, NULL, NULL)) + return NULL; return type; } @@ -166,9 +169,10 @@ static GVariant * g_action_group_real_get_action_state_hint (GActionGroup *action_group, const gchar *action_name) { - GVariant *hint = NULL; + GVariant *hint; - g_action_group_query_action (action_group, action_name, NULL, NULL, NULL, &hint, NULL); + if (!g_action_group_query_action (action_group, action_name, NULL, NULL, NULL, &hint, NULL)) + return NULL; return hint; } @@ -177,9 +181,10 @@ static GVariant * g_action_group_real_get_action_state (GActionGroup *action_group, const gchar *action_name) { - GVariant *state = NULL; + GVariant *state; - g_action_group_query_action (action_group, action_name, NULL, NULL, NULL, NULL, &state); + if (!g_action_group_query_action (action_group, action_name, NULL, NULL, NULL, NULL, &state)) + return NULL; return state; } diff --git a/gio/gactiongroup.h b/gio/gactiongroup.h index f8d20ae69..06213df8a 100644 --- a/gio/gactiongroup.h +++ b/gio/gactiongroup.h @@ -156,7 +156,7 @@ gboolean g_action_group_query_action (GAction const GVariantType **parameter_type, const GVariantType **state_type, GVariant **state_hint, - GVariant **state); + GVariant **state) G_GNUC_WARN_UNUSED_RESULT; G_END_DECLS diff --git a/glib/gunidecomp.c b/glib/gunidecomp.c index 07bc3cb22..f14944397 100644 --- a/glib/gunidecomp.c +++ b/glib/gunidecomp.c @@ -388,9 +388,33 @@ _g_utf8_normalize_wc (const gchar *str, while ((max_len < 0 || p < str + max_len) && *p) { const gchar *decomp; - gunichar wc = g_utf8_get_char (p); + const char *next, *between; + gunichar wc; - if (wc >= SBase && wc < SBase + SCount) + next = g_utf8_next_char (p); + /* Avoid reading truncated multibyte characters + which run past the end of the buffer */ + if (max_len < 0) + { + /* Does the character contain a NUL terminator? */ + for (between = &p[1]; between < next; between++) + { + if (G_UNLIKELY (!*between)) + return NULL; + } + } + else + { + if (G_UNLIKELY (next > str + max_len)) + return NULL; + } + wc = g_utf8_get_char (p); + + if (G_UNLIKELY (wc == (gunichar) -1)) + { + return NULL; + } + else if (wc >= SBase && wc < SBase + SCount) { gsize result_len; decompose_hangul (wc, NULL, &result_len); @@ -406,7 +430,7 @@ _g_utf8_normalize_wc (const gchar *str, n_wc++; } - p = g_utf8_next_char (p); + p = next; } wc_buffer = g_new (gunichar, n_wc + 1); @@ -548,10 +572,13 @@ g_utf8_normalize (const gchar *str, GNormalizeMode mode) { gunichar *result_wc = _g_utf8_normalize_wc (str, len, mode); - gchar *result; + gchar *result = NULL; - result = g_ucs4_to_utf8 (result_wc, -1, NULL, NULL, NULL); - g_free (result_wc); + if (G_LIKELY (result_wc != NULL)) + { + result = g_ucs4_to_utf8 (result_wc, -1, NULL, NULL, NULL); + g_free (result_wc); + } return result; } diff --git a/glib/tests/unicode-normalize.c b/glib/tests/unicode-normalize.c index 451c03f34..191e5bb98 100644 --- a/glib/tests/unicode-normalize.c +++ b/glib/tests/unicode-normalize.c @@ -146,12 +146,50 @@ test_unicode_normalize (void) g_string_free (buffer, TRUE); } +static void +test_unicode_normalize_invalid (void) +{ + /* g_utf8_normalize() should return NULL for all of these invalid inputs */ + const struct + { + gssize max_len; + const gchar *str; + } test_vectors[] = { + /* input ending with truncated multibyte encoding */ + { -1, "\xC0" }, + { 1, "\xC0\x80" }, + { -1, "\xE0\x80" }, + { 2, "\xE0\x80\x80" }, + { -1, "\xF0\x80\x80" }, + { 3, "\xF0\x80\x80\x80" }, + { -1, "\xF8\x80\x80\x80" }, + { 4, "\xF8\x80\x80\x80\x80" }, + { 3, "\x20\xE2\x84\xAA" }, + { -1, "\x20\xE2\x00\xAA" }, + { -1, "\xC0\x80\xE0\x80" }, + { 4, "\xC0\x80\xE0\x80\x80" }, + /* input containing invalid multibyte encoding */ + { -1, "\xED\x85\x9C\xED\x15\x9C\xED\x85\x9C" }, + }; + gsize i; + + for (i = 0; i < G_N_ELEMENTS (test_vectors); i++) + { + g_test_message ("Invalid UTF-8 vector %" G_GSIZE_FORMAT, i); + g_assert_null (g_utf8_normalize (test_vectors[i].str, + test_vectors[i].max_len, + G_NORMALIZE_ALL)); + } +} + int main (int argc, char **argv) { g_test_init (&argc, &argv, NULL); g_test_add_func ("/unicode/normalize", test_unicode_normalize); + g_test_add_func ("/unicode/normalize-invalid", + test_unicode_normalize_invalid); return g_test_run (); } |