[gedit] Make sure text passed to insert_text is null terminated



commit d50108e57935871125cb42f275ebc2f096448452
Author: Jesse van den Kieboom <jessevdk gmail com>
Date:   Wed Mar 19 13:47:54 2014 +0100

    Make sure text passed to insert_text is null terminated
    
    https://bugzilla.gnome.org/show_bug.cgi?id=726390

 gedit/gedit-document-output-stream.c |   62 ++++++++++++++++++++++++++++-----
 1 files changed, 52 insertions(+), 10 deletions(-)
---
diff --git a/gedit/gedit-document-output-stream.c b/gedit/gedit-document-output-stream.c
index dd5a95d..d8e4789 100644
--- a/gedit/gedit-document-output-stream.c
+++ b/gedit/gedit-document-output-stream.c
@@ -579,12 +579,14 @@ insert_fallback (GeditDocumentOutputStream *stream,
 
 static void
 validate_and_insert (GeditDocumentOutputStream *stream,
-                     const gchar               *buffer,
-                     gsize                      count)
+                     gchar                     *buffer,
+                     gsize                      count,
+                     gboolean                   owned)
 {
        GtkTextBuffer *text_buffer;
        GtkTextIter   *iter;
        gsize len;
+       gchar *freetext = NULL;
 
        text_buffer = GTK_TEXT_BUFFER (stream->priv->doc);
        iter = &stream->priv->pos;
@@ -613,8 +615,9 @@ validate_and_insert (GeditDocumentOutputStream *stream,
 
                        if (ptr && *ptr == '\r' && ptr - buffer == len - 1)
                        {
-                               stream->priv->buffer = g_new (gchar, 1);
+                               stream->priv->buffer = g_new (gchar, 2);
                                stream->priv->buffer[0] = '\r';
+                               stream->priv->buffer[1] = '\0';
                                stream->priv->buflen = 1;
 
                                /* Decrease also the len so in the check
@@ -627,10 +630,41 @@ validate_and_insert (GeditDocumentOutputStream *stream,
                /* if we've got any valid char we must tag the invalid chars */
                if (nvalid > 0)
                {
+                       gchar orignonnull = '\0';
+
                        apply_error_tag (stream);
-               }
 
-               gtk_text_buffer_insert (text_buffer, iter, buffer, nvalid);
+                       if (nvalid != len && buffer[nvalid] != '\0')
+                       {
+                               /* make sure the buffer is always properly null
+                                * terminated. This is needed, at least for now,
+                                * to avoid issues with pygobject marshalling of
+                                * the insert-text signal of gtktextbuffer
+                                *
+                                * https://bugzilla.gnome.org/show_bug.cgi?id=726689
+                                */
+                               if (!owned)
+                               {
+                                       /* forced to make a copy */
+                                       freetext = g_new (gchar, len + 1);
+                                       memcpy (freetext, buffer, len);
+
+                                       buffer = freetext;
+                                       owned = TRUE;
+                               }
+
+                               orignonnull = buffer[nvalid];
+                               buffer[nvalid] = '\0';
+                       }
+
+                       gtk_text_buffer_insert (text_buffer, iter, buffer, nvalid);
+
+                       if (orignonnull != '\0')
+                       {
+                               /* restore null terminated replaced byte */
+                               buffer[nvalid] = orignonnull;
+                       }
+               }
 
                /* If we inserted all return */
                if (nvalid == len)
@@ -660,6 +694,8 @@ validate_and_insert (GeditDocumentOutputStream *stream,
                ++buffer;
                --len;
        }
+
+       g_free (freetext);
 }
 
 /* If the last char is a newline, remove it from the buffer (otherwise
@@ -723,7 +759,9 @@ convert_text (GeditDocumentOutputStream *stream,
        outbuf_size = (inbuf_len > 0) ? inbuf_len : 100;
 
        out_left = outbuf_size;
-       out = dest = g_malloc (outbuf_size);
+
+       /* keep room for null termination */
+       out = dest = g_malloc (sizeof (gchar) * (outbuf_size + 1));
 
        done = FALSE;
        have_error = FALSE;
@@ -756,7 +794,10 @@ convert_text (GeditDocumentOutputStream *stream,
                                                gsize used = out - dest;
 
                                                outbuf_size *= 2;
-                                               dest = g_realloc (dest, outbuf_size);
+
+                                               /* make sure to allocate room for
+                                                  terminating null byte */
+                                               dest = g_realloc (dest, outbuf_size + 1);
 
                                                out = dest + used;
                                                out_left = outbuf_size - used;
@@ -792,9 +833,10 @@ convert_text (GeditDocumentOutputStream *stream,
                return FALSE;
        }
 
-       *outbuf = dest;
        *outbuf_len = out - dest;
+       dest[*outbuf_len] = '\0';
 
+       *outbuf = dest;
        return TRUE;
 }
 
@@ -971,7 +1013,7 @@ gedit_document_output_stream_write (GOutputStream            *stream,
                len = outbuf_len;
        }
 
-       validate_and_insert (ostream, text, len);
+       validate_and_insert (ostream, text, len, freetext);
 
        if (freetext)
        {
@@ -1003,7 +1045,7 @@ gedit_document_output_stream_flush (GOutputStream  *stream,
 
                if (convert_text (ostream, NULL, 0, &outbuf, &outbuf_len, error))
                {
-                       validate_and_insert (ostream, outbuf, outbuf_len);
+                       validate_and_insert (ostream, outbuf, outbuf_len, TRUE);
                        g_free (outbuf);
                }
                else


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