gnutls-devel
[Top][All Lists]
Advanced

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

Re: Bug in gnutls breaking Pidgin Jabber support


From: Nikos Mavrogiannopoulos
Subject: Re: Bug in gnutls breaking Pidgin Jabber support
Date: Tue, 30 Jun 2009 21:44:29 +0300
User-agent: Thunderbird 2.0.0.22 (X11/20090608)

Tim Kosse wrote:
> Hi,
> 
> found the problem. Happens if _gnutls_io_write_buffered gets called with
> iptr == NULL and n < session->internals.record_send_buffer.length
> 
> It then gets up to n bytes from the send buffer into ptr. At that point
> session->internals.record_send_buffer still contains additional
> outstanding data.
> 
> If sending fails, it pushes the remaining data from ptr to the end of
> the send buffer, causing the buffer contents to become reordered.
> Instead it should have put it to the beginning. A gnutls_buffer_prepend
> function would be needed.
> 
> A workaround is to always request the complete buffer, see attached
> patch. That's identical to the behavior of older GnuTLS versions.

I did a quick hack to make a prepend function. Does this solve the issue?
diff --git a/lib/gnutls_buffers.c b/lib/gnutls_buffers.c
index 0b94f6f..e313018 100644
--- a/lib/gnutls_buffers.c
+++ b/lib/gnutls_buffers.c
@@ -713,7 +713,7 @@ _gnutls_io_write_buffered (gnutls_session_t session,
              session->internals.record_send_buffer_prev_size += n - left;
 
              retval =
-               _gnutls_buffer_append (&session->internals.record_send_buffer,
+               _gnutls_buffer_prepend (&session->internals.record_send_buffer,
                                       &ptr[n - left], left);
              if (retval < 0)
                {
diff --git a/lib/gnutls_str.c b/lib/gnutls_str.c
index f1bc46e..ab04218 100644
--- a/lib/gnutls_str.c
+++ b/lib/gnutls_str.c
@@ -169,6 +169,47 @@ _gnutls_string_append_data (gnutls_string * dest, const 
void *data,
 }
 
 int
+_gnutls_string_prepend_data (gnutls_string * dest, const void *data,
+                           size_t data_size)
+{
+  size_t tot_len = data_size + dest->length;
+
+  if (dest->max_length >= tot_len)
+    {
+      if (dest->length && dest->data)
+        memmove(&dest->allocd[data_size], dest->data, dest->length);
+
+      memcpy (dest->allocd, data, data_size);
+      dest->length = tot_len;
+      dest->data = dest->allocd;
+
+      return tot_len;
+    }
+  else
+    {
+      size_t new_len =
+       MAX (data_size, MIN_CHUNK) + MAX (dest->max_length, MIN_CHUNK);
+      opaque * tmp;
+
+      tmp = dest->alloc_func (new_len);
+      if (tmp == NULL)
+       {
+         gnutls_assert ();
+         return GNUTLS_E_MEMORY_ERROR;
+       }
+      memcpy(tmp, data, data_size);
+      memcpy(&tmp[data_size], dest->data, dest->length);
+      dest->max_length = new_len;
+      
+      dest->free_func(dest->allocd);
+      dest->allocd = dest->data = tmp;
+      dest->length = tot_len;
+
+      return tot_len;
+    }
+}
+
+int
 _gnutls_string_resize (gnutls_string * dest, size_t new_size)
 {
   if (dest->max_length >= new_size)
diff --git a/lib/gnutls_str.h b/lib/gnutls_str.h
index 1a5dec6..e8bea1e 100644
--- a/lib/gnutls_str.h
+++ b/lib/gnutls_str.h
@@ -51,6 +51,8 @@ int _gnutls_string_resize (gnutls_string *, size_t new_size);
 int _gnutls_string_append_str (gnutls_string *, const char *str);
 int _gnutls_string_append_data (gnutls_string *, const void *data,
                                size_t data_size);
+int _gnutls_string_prepend_data (gnutls_string *, const void *data,
+                               size_t data_size);
 
 void _gnutls_string_get_data( gnutls_string *, void*, size_t *size);
 void _gnutls_string_get_datum( gnutls_string *, gnutls_datum*, size_t 
max_size);
@@ -70,6 +72,7 @@ typedef gnutls_string gnutls_buffer;
 #define _gnutls_buffer_init(buf) _gnutls_string_init(buf, gnutls_malloc, 
gnutls_realloc, gnutls_free);
 #define _gnutls_buffer_clear _gnutls_string_clear
 #define _gnutls_buffer_append _gnutls_string_append_data
+#define _gnutls_buffer_prepend _gnutls_string_prepend_data
 #define _gnutls_buffer_get_datum _gnutls_string_get_datum
 #define _gnutls_buffer_get_data _gnutls_string_get_data
 #define _gnutls_buffer_resize _gnutls_string_resize

reply via email to

[Prev in Thread] Current Thread [Next in Thread]