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
5a633f82db as that is now no longer
necessary.
This commit is contained in:
Benjamin Otte 2009-10-28 19:18:20 +01:00
parent 5a633f82db
commit 4288ad7692

View File

@ -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)
* </footnote>.
*
* Return value: If the conversion was successful, a newly allocated
* nul-terminated<footnote id="nul-returns">
* <para>
* 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.
* </para>
* </footnote>
* 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<footnoteref linkend="streaming-state"/>.
*
* Return value: If the conversion was successful, a newly allocated
* nul-terminated<footnoteref linkend="nul-returns"/> 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<footnoteref linkend="streaming-state"/>.
*
* Return value: If the conversion was successful, a newly allocated
* nul-terminated<footnoteref linkend="nul-returns"/> 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);