From 4288ad76922da01d1f452c6c257e97008b16aaf0 Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Wed, 28 Oct 2009 19:18:20 +0100 Subject: [PATCH] Properly nul-terminate return values from g_convert() The patch ensures that multibyte character sets are properly nul-terminated. This is an issue because the documentation claims to return a "nul-terminated" string and users of the API assume that means a proper nul-termination in the resulting character set. I looked at Pidgin and GStreamer code and found at least 3 cases where this was happening. This patch also reverts the documentation change from 5a633f82dbbce067c56fba0ee372fd341b76368d as that is now no longer necessary. --- glib/gconvert.c | 44 ++++++++++++++++++++------------------------ 1 file changed, 20 insertions(+), 24 deletions(-) diff --git a/glib/gconvert.c b/glib/gconvert.c index f2141a35..5ec8f1d9 100644 --- a/glib/gconvert.c +++ b/glib/gconvert.c @@ -57,6 +57,12 @@ #include "galias.h" +/* We try to terminate strings in unknown charsets with this many zero bytes + * to ensure that multibyte strings really are nul-terminated when we return + * them from g_convert() and friends. + */ +#define NUL_TERMINATOR_LENGTH 4 + GQuark g_convert_error_quark (void) { @@ -566,16 +572,8 @@ close_converter (GIConv cd) * . * * Return value: If the conversion was successful, a newly allocated - * nul-terminated - * - * Nul-terminated return values from conversion functions - * are terminated by a single 0 byte only. This means that - * for multibyte character sets like UTF-16, they must be - * treated as not nul-terminated. - * - * - * string, which must be freed with g_free(). Otherwise %NULL - * and @error will be set. + * nul-terminated string, which must be freed with + * g_free(). Otherwise %NULL and @error will be set. **/ gchar* g_convert_with_iconv (const gchar *str, @@ -603,9 +601,9 @@ g_convert_with_iconv (const gchar *str, p = str; inbytes_remaining = len; - outbuf_size = len + 1; /* + 1 for nul in case len == 1 */ + outbuf_size = len + NUL_TERMINATOR_LENGTH; - outbytes_remaining = outbuf_size - 1; /* -1 for nul */ + outbytes_remaining = outbuf_size - NUL_TERMINATOR_LENGTH; outp = dest = g_malloc (outbuf_size); while (!done && !have_error) @@ -631,7 +629,7 @@ g_convert_with_iconv (const gchar *str, dest = g_realloc (dest, outbuf_size); outp = dest + used; - outbytes_remaining = outbuf_size - used - 1; /* -1 for nul */ + outbytes_remaining = outbuf_size - used - NUL_TERMINATOR_LENGTH; } break; case EILSEQ: @@ -665,7 +663,7 @@ g_convert_with_iconv (const gchar *str, } } - *outp = '\0'; + memset (outp, 0, NUL_TERMINATOR_LENGTH); if (bytes_read) *bytes_read = p - str; @@ -727,9 +725,8 @@ g_convert_with_iconv (const gchar *str, * conversions. * * Return value: If the conversion was successful, a newly allocated - * nul-terminated string, - * which must be freed with g_free(). Otherwise %NULL and - * @error will be set. + * nul-terminated string, which must be freed with + * g_free(). Otherwise %NULL and @error will be set. **/ gchar* g_convert (const gchar *str, @@ -803,9 +800,8 @@ g_convert (const gchar *str, * conversions. * * Return value: If the conversion was successful, a newly allocated - * nul-terminated string, - * which must be freed with g_free(). Otherwise %NULL and - * @error will be set. + * nul-terminated string, which must be freed with + * g_free(). Otherwise %NULL and @error will be set. **/ gchar* g_convert_with_fallback (const gchar *str, @@ -894,8 +890,8 @@ g_convert_with_fallback (const gchar *str, */ p = utf8; - outbuf_size = len + 1; /* + 1 for nul in case len == 1 */ - outbytes_remaining = outbuf_size - 1; /* -1 for nul */ + outbuf_size = len + NUL_TERMINATOR_LENGTH; + outbytes_remaining = outbuf_size - NUL_TERMINATOR_LENGTH; outp = dest = g_malloc (outbuf_size); while (!done && !have_error) @@ -919,7 +915,7 @@ g_convert_with_fallback (const gchar *str, dest = g_realloc (dest, outbuf_size); outp = dest + used; - outbytes_remaining = outbuf_size - used - 1; /* -1 for nul */ + outbytes_remaining = outbuf_size - used - NUL_TERMINATOR_LENGTH; break; } @@ -988,7 +984,7 @@ g_convert_with_fallback (const gchar *str, /* Cleanup */ - *outp = '\0'; + memset (outp, 0, NUL_TERMINATOR_LENGTH); close_converter (cd); -- 2.34.1