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
This commit is contained in:
Marc-André Lureau 2013-11-06 12:21:58 +01:00
parent 0dbe5c43df
commit d6a19d2e76
2 changed files with 38 additions and 13 deletions

View File

@ -44,6 +44,7 @@ G_BEGIN_DECLS
* @G_CONVERT_ERROR_PARTIAL_INPUT: Partial character sequence at end of input. * @G_CONVERT_ERROR_PARTIAL_INPUT: Partial character sequence at end of input.
* @G_CONVERT_ERROR_BAD_URI: URI is invalid. * @G_CONVERT_ERROR_BAD_URI: URI is invalid.
* @G_CONVERT_ERROR_NOT_ABSOLUTE_PATH: Pathname is not an absolute path. * @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. * Error codes returned by character set conversion routines.
*/ */
@ -54,7 +55,8 @@ typedef enum
G_CONVERT_ERROR_FAILED, G_CONVERT_ERROR_FAILED,
G_CONVERT_ERROR_PARTIAL_INPUT, G_CONVERT_ERROR_PARTIAL_INPUT,
G_CONVERT_ERROR_BAD_URI, G_CONVERT_ERROR_BAD_URI,
G_CONVERT_ERROR_NOT_ABSOLUTE_PATH G_CONVERT_ERROR_NOT_ABSOLUTE_PATH,
G_CONVERT_ERROR_NO_MEMORY
} GConvertError; } GConvertError;
/** /**

View File

@ -776,6 +776,16 @@ g_utf8_to_ucs4_fast (const gchar *str,
return result; 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: * g_utf8_to_ucs4:
* @str: a UTF-8 encoded string * @str: a UTF-8 encoded string
@ -840,8 +850,10 @@ g_utf8_to_ucs4 (const gchar *str,
in = g_utf8_next_char (in); 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; in = str;
for (i=0; i < n_chars; i++) 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_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; p = result;
i = 0; 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 /* At this point, everything is valid, and we just need to convert
*/ */
/********** DIFFERENT for UTF8/UCS4 **********/ /********** 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; high_surrogate = 0;
out = result; out = result;
in = str; 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 /* At this point, everything is valid, and we just need to convert
*/ */
/********** DIFFERENT for UTF8/UCS4 **********/ /********** 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; high_surrogate = 0;
out = result; out = result;
in = str; in = str;
@ -1310,8 +1329,10 @@ g_utf8_to_utf16 (const gchar *str,
in = g_utf8_next_char (in); 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; in = str;
for (i = 0; i < n16;) for (i = 0; i < n16;)
{ {
@ -1405,9 +1426,11 @@ g_ucs4_to_utf16 (const gunichar *str,
i++; 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++) for (i = 0, j = 0; j < n16; i++)
{ {
gunichar wc = str[i]; gunichar wc = str[i];