From d6a19d2e76654570c056ef328c6fb4fdda939272 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Wed, 6 Nov 2013 12:21:58 +0100 Subject: [PATCH] utf8: report allocation error Make some of the conversion functions a bit more friendly to allocation failure. Even though the glib policy is to abort() on allocation failure by default, it can be quite helpful to return an allocation error for functions already providing a GError. I needed a safer g_utf16_to_utf8() to solve crash on big clipboard operations with win32, related to rhbz#1017250 (and coming gdk handling bug). https://bugzilla.gnome.org/show_bug.cgi?id=711546 --- glib/gconvert.h | 4 +++- glib/gutf8.c | 47 +++++++++++++++++++++++++++++++++++------------ 2 files changed, 38 insertions(+), 13 deletions(-) diff --git a/glib/gconvert.h b/glib/gconvert.h index 1945c07d6..3df66ce15 100644 --- a/glib/gconvert.h +++ b/glib/gconvert.h @@ -44,6 +44,7 @@ G_BEGIN_DECLS * @G_CONVERT_ERROR_PARTIAL_INPUT: Partial character sequence at end of input. * @G_CONVERT_ERROR_BAD_URI: URI is invalid. * @G_CONVERT_ERROR_NOT_ABSOLUTE_PATH: Pathname is not an absolute path. + * @G_CONVERT_ERROR_NO_MEMORY: No memory available. Since: 2.40 * * Error codes returned by character set conversion routines. */ @@ -54,7 +55,8 @@ typedef enum G_CONVERT_ERROR_FAILED, G_CONVERT_ERROR_PARTIAL_INPUT, G_CONVERT_ERROR_BAD_URI, - G_CONVERT_ERROR_NOT_ABSOLUTE_PATH + G_CONVERT_ERROR_NOT_ABSOLUTE_PATH, + G_CONVERT_ERROR_NO_MEMORY } GConvertError; /** diff --git a/glib/gutf8.c b/glib/gutf8.c index 9244fe8c4..149eeef44 100644 --- a/glib/gutf8.c +++ b/glib/gutf8.c @@ -776,6 +776,16 @@ g_utf8_to_ucs4_fast (const gchar *str, return result; } +static gpointer +try_malloc (gsize n_bytes, GError **error) +{ + gpointer ptr = g_try_malloc (n_bytes); + if (ptr == NULL) + g_set_error_literal (error, G_CONVERT_ERROR, G_CONVERT_ERROR_NO_MEMORY, + _("Failed to allocate memory")); + return ptr; +} + /** * g_utf8_to_ucs4: * @str: a UTF-8 encoded string @@ -840,8 +850,10 @@ g_utf8_to_ucs4 (const gchar *str, in = g_utf8_next_char (in); } - result = g_new (gunichar, n_chars + 1); - + result = try_malloc (sizeof (gunichar) * (n_chars + 1), error); + if (result == NULL) + goto err_out; + in = str; for (i=0; i < n_chars; i++) { @@ -911,7 +923,10 @@ g_ucs4_to_utf8 (const gunichar *str, result_length += UTF8_LENGTH (str[i]); } - result = g_malloc (result_length + 1); + result = try_malloc (result_length + 1, error); + if (result == NULL) + goto err_out; + p = result; i = 0; @@ -1043,8 +1058,10 @@ g_utf16_to_utf8 (const gunichar2 *str, /* At this point, everything is valid, and we just need to convert */ /********** DIFFERENT for UTF8/UCS4 **********/ - result = g_malloc (n_bytes + 1); - + result = try_malloc (n_bytes + 1, error); + if (result == NULL) + goto err_out; + high_surrogate = 0; out = result; in = str; @@ -1180,8 +1197,10 @@ g_utf16_to_ucs4 (const gunichar2 *str, /* At this point, everything is valid, and we just need to convert */ /********** DIFFERENT for UTF8/UCS4 **********/ - result = g_malloc (n_bytes + 4); - + result = try_malloc (n_bytes + 4, error); + if (result == NULL) + goto err_out; + high_surrogate = 0; out = result; in = str; @@ -1310,8 +1329,10 @@ g_utf8_to_utf16 (const gchar *str, in = g_utf8_next_char (in); } - result = g_new (gunichar2, n16 + 1); - + result = try_malloc (sizeof (gunichar2) * (n16 + 1), error); + if (result == NULL) + goto err_out; + in = str; for (i = 0; i < n16;) { @@ -1405,9 +1426,11 @@ g_ucs4_to_utf16 (const gunichar *str, i++; } - - result = g_new (gunichar2, n16 + 1); - + + result = try_malloc (sizeof (gunichar2) * (n16 + 1), error); + if (result == NULL) + goto err_out; + for (i = 0, j = 0; j < n16; i++) { gunichar wc = str[i];