[glib/glib-2-22] Properly nul-terminate return values from g_convert()



commit 07e22befadf1dc8cb53eb669831cde3bb194595c
Author: Benjamin Otte <otte gnome org>
Date:   Wed Oct 28 19:18:20 2009 +0100

    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
    8c936178a130f06511164dbd317180177da6b448 as that is now no longer
    necessary.

 glib/gconvert.c |   44 ++++++++++++++++++++------------------------
 1 files changed, 20 insertions(+), 24 deletions(-)
---
diff --git a/glib/gconvert.c b/glib/gconvert.c
index f2141a3..5ec8f1d 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)
  * </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);
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]