File gnutls-fix-compression.patch of Package gnutls.openSUSE_12.1_Update

From f3abb3c8e37dfdb0881c23499abf4fe3aa779e14 Mon Sep 17 00:00:00 2001
From: Nikos Mavrogiannopoulos <nmav@gnutls.org>
Date: Thu, 22 Sep 2011 18:48:07 +0200
Subject: [PATCH] Simplified and corrected decompression and compression.
 Added test program.

---
 lib/gnutls_cipher.c   |  203 +++++++++++++++++++++++--------------------------
 lib/gnutls_compress.c |  137 ++++-----------------------------
 lib/gnutls_compress.h |   15 +---
 lib/gnutls_record.c   |    5 +-
 tests/Makefile.am     |    2 +-
 tests/eagain-common.h |    5 +
 tests/mini-deflate.c  |  113 +++++++++++++++++++++++++++
 7 files changed, 234 insertions(+), 246 deletions(-)
 create mode 100644 tests/mini-deflate.c

diff --git a/lib/gnutls_cipher.c b/lib/gnutls_cipher.c
index 1629b4d..75ca6ab 100644
--- a/lib/gnutls_cipher.c
+++ b/lib/gnutls_cipher.c
@@ -41,15 +41,16 @@
 #include <gnutls_state.h>
 #include <random.h>
 
-static int _gnutls_compressed2ciphertext (gnutls_session_t session,
+static int compressed_to_ciphertext (gnutls_session_t session,
                                    opaque * cipher_data, int cipher_size,
-                                   gnutls_datum_t compressed,
+                                   gnutls_datum_t *compressed,
                                    content_type_t _type, 
                                    record_parameters_st * params);
-static int _gnutls_ciphertext2compressed (gnutls_session_t session,
+static int ciphertext_to_compressed (gnutls_session_t session,
+                                   gnutls_datum_t *ciphertext, 
                                    opaque * compress_data,
                                    int compress_size,
-                                   gnutls_datum_t ciphertext, uint8_t type,
+                                   uint8_t type,
                                    record_parameters_st * params, uint64* sequence);
 
 inline static int
@@ -83,45 +84,47 @@ _gnutls_encrypt (gnutls_session_t session, const opaque * headers,
                  size_t ciphertext_size, content_type_t type, 
                  record_parameters_st * params)
 {
-  gnutls_datum_t plain;
   gnutls_datum_t comp;
+  int free_comp = 0;
   int ret;
-  int free_comp = 1;
-  record_parameters_st *cur_record_params;
 
-  ret = _gnutls_epoch_get (session, EPOCH_WRITE_CURRENT, &cur_record_params);
-  if (ret < 0)
-    return gnutls_assert_val(ret);
-
-  plain.data = (opaque *) data;
-  plain.size = data_size;
-
-  if (plain.size == 0 || is_write_comp_null (cur_record_params) == 0)
+  if (data_size == 0 || is_write_comp_null (params) == 0)
     {
-      comp = plain;
-      free_comp = 0;
+      comp.data = (opaque*)data;
+      comp.size = data_size;
     }
   else
     {
       /* Here comp is allocated and must be 
        * freed.
        */
-      ret = _gnutls_m_plaintext2compressed (session, &comp, &plain, params);
+      free_comp = 1;
+      
+      comp.size = ciphertext_size - headers_size;
+      comp.data = gnutls_malloc(comp.size);
+      if (comp.data == NULL)
+        return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
+      
+      ret = _gnutls_compress( params->write.compression_state, data, data_size, comp.data, comp.size);
       if (ret < 0)
-        return gnutls_assert_val(ret);
+        {
+          gnutls_free(comp.data);
+          return gnutls_assert_val(ret);
+        }
+      
+      comp.size = ret;
     }
 
-  ret = _gnutls_compressed2ciphertext (session, &ciphertext[headers_size],
+  ret = compressed_to_ciphertext (session, &ciphertext[headers_size],
                                        ciphertext_size - headers_size,
-                                       comp, type, params);
+                                       &comp, type, params);
 
   if (free_comp)
-    _gnutls_free_datum (&comp);
+    gnutls_free(comp.data);
 
   if (ret < 0)
     return gnutls_assert_val(ret);
 
-
   /* copy the headers */
   memcpy (ciphertext, headers, headers_size);
   
@@ -142,14 +145,8 @@ _gnutls_decrypt (gnutls_session_t session, opaque * ciphertext,
                  size_t max_data_size, content_type_t type,
                  record_parameters_st * params, uint64 *sequence)
 {
-  gnutls_datum_t gtxt;
   gnutls_datum_t gcipher;
-  int ret;
-  record_parameters_st *cur_record_params;
-
-  ret = _gnutls_epoch_get (session, EPOCH_READ_CURRENT, &cur_record_params);
-  if (ret < 0)
-    return gnutls_assert_val(ret);
+  int ret, data_size;
 
   if (ciphertext_size == 0)
     return 0;
@@ -157,57 +154,43 @@ _gnutls_decrypt (gnutls_session_t session, opaque * ciphertext,
   gcipher.size = ciphertext_size;
   gcipher.data = ciphertext;
 
-  ret =
-    _gnutls_ciphertext2compressed (session, data, max_data_size,
-                                   gcipher, type, params, sequence);
-  if (ret < 0)
+  if (is_read_comp_null (params) == 0)
     {
+      ret =
+        ciphertext_to_compressed (session, &gcipher, data, max_data_size,
+                                   type, params, sequence);
+      if (ret < 0)
+        return gnutls_assert_val(ret);
+      
       return ret;
     }
-
-  if (ret == 0 || is_read_comp_null (cur_record_params) == 0)
-    {
-      /* ret == ret */
-
-    }
   else
     {
-      gnutls_datum_t gcomp;
-
-      /* compression has this malloc overhead.
-       */
-
-      gcomp.data = data;
-      gcomp.size = ret;
-      ret = _gnutls_m_compressed2plaintext (session, &gtxt, &gcomp, params);
+      opaque* tmp_data;
+      
+      tmp_data = gnutls_malloc(max_data_size);
+      if (tmp_data == NULL)
+        return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
+      
+      ret =
+        ciphertext_to_compressed (session, &gcipher, tmp_data, max_data_size,
+                                   type, params, sequence);
       if (ret < 0)
+        goto leave;
+      
+      data_size = ret;
+        
+      if (ret != 0)
         {
-          return ret;
-        }
-
-      if (gtxt.size > MAX_RECORD_RECV_SIZE(session))
-        {
-          _gnutls_free_datum (&gtxt);
-          /* This shouldn't have happen and
-           * is a TLS fatal error.
-           */
-          return gnutls_assert_val(GNUTLS_E_DECOMPRESSION_FAILED);
-        }
-
-      /* This check is not really needed */
-      if (max_data_size < MAX_RECORD_RECV_SIZE(session))
-        {
-          _gnutls_free_datum (&gtxt);
-          return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
+          ret = _gnutls_decompress(params->read.compression_state, tmp_data, data_size, data, max_data_size);
+          if (ret < 0)
+            goto leave;
         }
-
-      memcpy (data, gtxt.data, gtxt.size);
-      ret = gtxt.size;
-
-      _gnutls_free_datum (&gtxt);
+        
+leave:
+      gnutls_free(tmp_data);
+      return ret;
     }
-
-  return ret;
 }
 
 
@@ -305,9 +288,9 @@ make_preamble (opaque * uint64_data, opaque type, int length,
  * return the actual encrypted data length.
  */
 static int
-_gnutls_compressed2ciphertext (gnutls_session_t session,
+compressed_to_ciphertext (gnutls_session_t session,
                                opaque * cipher_data, int cipher_size,
-                               gnutls_datum_t compressed,
+                               gnutls_datum_t *compressed,
                                content_type_t type, 
                                record_parameters_st * params)
 {
@@ -336,15 +319,16 @@ _gnutls_compressed2ciphertext (gnutls_session_t session,
   _gnutls_hard_log("ENC[%p]: cipher: %s, MAC: %s, Epoch: %u\n",
     session, gnutls_cipher_get_name(params->cipher_algorithm), gnutls_mac_get_name(params->mac_algorithm),
     (unsigned int)params->epoch);
+
   preamble_size =
     make_preamble (UINT64DATA
                    (params->write.sequence_number),
-                   type, compressed.size, ver, preamble);
+                   type, compressed->size, ver, preamble);
 
   /* Calculate the encrypted length (padding etc.)
    */
   length_to_encrypt = length =
-    calc_enc_length (session, compressed.size, tag_size, &pad,
+    calc_enc_length (session, compressed->size, tag_size, &pad,
                      random_pad, block_algo, auth_cipher, blocksize);
   if (length < 0)
     {
@@ -411,8 +395,8 @@ _gnutls_compressed2ciphertext (gnutls_session_t session,
       if (auth_cipher) return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
     }
 
-  memcpy (data_ptr, compressed.data, compressed.size);
-  data_ptr += compressed.size;
+  memcpy (data_ptr, compressed->data, compressed->size);
+  data_ptr += compressed->size;
 
   if (tag_size > 0)
     {
@@ -431,7 +415,7 @@ _gnutls_compressed2ciphertext (gnutls_session_t session,
    */
   ret =
     _gnutls_auth_cipher_encrypt_tag (&params->write.cipher_state,
-      cipher_data, length_to_encrypt, tag_ptr, tag_size, compressed.size);
+      cipher_data, length_to_encrypt, tag_ptr, tag_size, compressed->size);
   if (ret < 0)
     return gnutls_assert_val(ret);
 
@@ -443,11 +427,12 @@ _gnutls_compressed2ciphertext (gnutls_session_t session,
  * Returns the actual compressed packet size.
  */
 static int
-_gnutls_ciphertext2compressed (gnutls_session_t session,
-                               opaque * compress_data,
-                               int compress_size,
-                               gnutls_datum_t ciphertext, uint8_t type,
-                               record_parameters_st * params, uint64* sequence)
+ciphertext_to_compressed (gnutls_session_t session,
+                          gnutls_datum_t *ciphertext, 
+                          opaque * compress_data,
+                          int compress_size,
+                          uint8_t type, record_parameters_st * params, 
+                          uint64* sequence)
 {
   uint8_t tag[MAX_HASH_SIZE];
   uint8_t pad;
@@ -478,28 +463,28 @@ _gnutls_ciphertext2compressed (gnutls_session_t session,
           if (params->read.IV.data == NULL || params->read.IV.size != 4)
             return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
           
-          if (ciphertext.size < tag_size+AEAD_EXPLICIT_DATA_SIZE)
+          if (ciphertext->size < tag_size+AEAD_EXPLICIT_DATA_SIZE)
             return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
 
           memcpy(nonce, params->read.IV.data, AEAD_IMPLICIT_DATA_SIZE);
-          memcpy(&nonce[AEAD_IMPLICIT_DATA_SIZE], ciphertext.data, AEAD_EXPLICIT_DATA_SIZE);
+          memcpy(&nonce[AEAD_IMPLICIT_DATA_SIZE], ciphertext->data, AEAD_EXPLICIT_DATA_SIZE);
           
           _gnutls_auth_cipher_setiv(&params->read.cipher_state, nonce, AEAD_EXPLICIT_DATA_SIZE+AEAD_IMPLICIT_DATA_SIZE);
 
-          ciphertext.data += AEAD_EXPLICIT_DATA_SIZE;
-          ciphertext.size -= AEAD_EXPLICIT_DATA_SIZE;
+          ciphertext->data += AEAD_EXPLICIT_DATA_SIZE;
+          ciphertext->size -= AEAD_EXPLICIT_DATA_SIZE;
           
-          length_to_decrypt = ciphertext.size - tag_size;
+          length_to_decrypt = ciphertext->size - tag_size;
         }
       else
         {
-          if (ciphertext.size < tag_size)
+          if (ciphertext->size < tag_size)
             return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
   
-          length_to_decrypt = ciphertext.size;
+          length_to_decrypt = ciphertext->size;
         }
 
-      length = ciphertext.size - tag_size;
+      length = ciphertext->size - tag_size;
 
       /* Pass the type, version, length and compressed through
        * MAC.
@@ -512,12 +497,12 @@ _gnutls_ciphertext2compressed (gnutls_session_t session,
 
       if ((ret =
            _gnutls_auth_cipher_decrypt (&params->read.cipher_state,
-             ciphertext.data, length_to_decrypt)) < 0)
+             ciphertext->data, length_to_decrypt)) < 0)
         return gnutls_assert_val(ret);
 
       break;
     case CIPHER_BLOCK:
-      if (ciphertext.size < MAX(blocksize, tag_size) || (ciphertext.size % blocksize != 0))
+      if (ciphertext->size < MAX(blocksize, tag_size) || (ciphertext->size % blocksize != 0))
         return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
 
       /* ignore the IV in TLS 1.1+
@@ -525,12 +510,12 @@ _gnutls_ciphertext2compressed (gnutls_session_t session,
       if (explicit_iv)
         {
           _gnutls_auth_cipher_setiv(&params->read.cipher_state,
-            ciphertext.data, blocksize);
+            ciphertext->data, blocksize);
 
-          ciphertext.size -= blocksize;
-          ciphertext.data += blocksize;
+          ciphertext->size -= blocksize;
+          ciphertext->data += blocksize;
 
-          if (ciphertext.size == 0)
+          if (ciphertext->size == 0)
             {
               gnutls_assert ();
               return GNUTLS_E_DECRYPTION_FAILED;
@@ -544,32 +529,32 @@ _gnutls_ciphertext2compressed (gnutls_session_t session,
        */
       if ((ret =
            _gnutls_cipher_decrypt (&params->read.cipher_state.cipher,
-             ciphertext.data, ciphertext.size)) < 0)
+             ciphertext->data, ciphertext->size)) < 0)
         return gnutls_assert_val(ret);
 
-      pad = ciphertext.data[ciphertext.size - 1] + 1;   /* pad */
+      pad = ciphertext->data[ciphertext->size - 1] + 1;   /* pad */
       
-      if ((int) pad > (int) ciphertext.size - tag_size)
+      if ((int) pad > (int) ciphertext->size - tag_size)
         {
           gnutls_assert ();
           _gnutls_record_log
             ("REC[%p]: Short record length %d > %d - %d (under attack?)\n",
-             session, pad, ciphertext.size, tag_size);
+             session, pad, ciphertext->size, tag_size);
           /* We do not fail here. We check below for the
            * the pad_failed. If zero means success.
            */
           pad_failed = GNUTLS_E_DECRYPTION_FAILED;
         }
 
-      length = ciphertext.size - tag_size - pad;
+      length = ciphertext->size - tag_size - pad;
 
       /* Check the pading bytes (TLS 1.x)
        */
       if (ver != GNUTLS_SSL3 && pad_failed == 0)
         for (i = 2; i < pad; i++)
           {
-            if (ciphertext.data[ciphertext.size - i] !=
-                ciphertext.data[ciphertext.size - 1])
+            if (ciphertext->data[ciphertext->size - i] !=
+                ciphertext->data[ciphertext->size - 1])
               pad_failed = GNUTLS_E_DECRYPTION_FAILED;
           }
 
@@ -583,7 +568,7 @@ _gnutls_ciphertext2compressed (gnutls_session_t session,
         make_preamble (UINT64DATA(*sequence), type,
                        length, ver, preamble);
       _gnutls_auth_cipher_add_auth (&params->read.cipher_state, preamble, preamble_size);
-      _gnutls_auth_cipher_add_auth (&params->read.cipher_state, ciphertext.data, length);
+      _gnutls_auth_cipher_add_auth (&params->read.cipher_state, ciphertext->data, length);
 
       break;
     default:
@@ -602,7 +587,7 @@ _gnutls_ciphertext2compressed (gnutls_session_t session,
 
   /* HMAC was not the same. 
    */
-  if (memcmp (tag, &ciphertext.data[length], tag_size) != 0)
+  if (memcmp (tag, &ciphertext->data[length], tag_size) != 0)
     return gnutls_assert_val(GNUTLS_E_DECRYPTION_FAILED);
 
   /* copy the decrypted stuff to compress_data.
@@ -610,8 +595,8 @@ _gnutls_ciphertext2compressed (gnutls_session_t session,
   if (compress_size < length)
     return gnutls_assert_val(GNUTLS_E_DECOMPRESSION_FAILED);
 
-  if (compress_data != ciphertext.data)
-    memcpy (compress_data, ciphertext.data, length);
+  if (compress_data != ciphertext->data)
+    memcpy (compress_data, ciphertext->data, length);
 
   return length;
 }
diff --git a/lib/gnutls_compress.c b/lib/gnutls_compress.c
index 52d4a15..e7a5114 100644
--- a/lib/gnutls_compress.c
+++ b/lib/gnutls_compress.c
@@ -32,57 +32,6 @@
 #include <algorithms.h>
 #include <gnutls/gnutls.h>
 
-/* These functions allocate the return value internally
- */
-int
-_gnutls_m_plaintext2compressed (gnutls_session_t session,
-                                gnutls_datum_t * compressed,
-                                const gnutls_datum_t * plaintext,
-                                const record_parameters_st * params)
-{
-  int size;
-  opaque *data;
-
-  size =
-    _gnutls_compress (params->write.compression_state,
-                      plaintext->data, plaintext->size, &data,
-                      MAX_RECORD_SEND_SIZE(session) + EXTRA_COMP_SIZE);
-  if (size < 0)
-    {
-      gnutls_assert ();
-      return GNUTLS_E_COMPRESSION_FAILED;
-    }
-  compressed->data = data;
-  compressed->size = size;
-
-  return 0;
-}
-
-int
-_gnutls_m_compressed2plaintext (gnutls_session_t session,
-                                gnutls_datum_t * plain,
-                                const gnutls_datum_t * compressed,
-                                const record_parameters_st * params)
-{
-  int size;
-  opaque *data;
-
-  size =
-    _gnutls_decompress (params->read.compression_state,
-                        compressed->data, compressed->size, &data,
-                        MAX_RECORD_RECV_SIZE(session));
-  if (size < 0)
-    {
-      gnutls_assert ();
-      return GNUTLS_E_DECOMPRESSION_FAILED;
-    }
-  plain->data = data;
-  plain->size = size;
-
-  return 0;
-}
-
-
 /* Compression Section */
 #define GNUTLS_COMPRESSION_ENTRY(name, id, wb, ml, cl)	\
   { #name, name, id, wb, ml, cl}
@@ -397,7 +346,7 @@ _gnutls_comp_deinit (comp_hd_t handle, int d)
 
 int
 _gnutls_compress (comp_hd_t handle, const opaque * plain,
-                  size_t plain_size, opaque ** compressed,
+                  size_t plain_size, opaque * compressed,
                   size_t max_comp_size)
 {
   int compressed_size = GNUTLS_E_COMPRESSION_FAILED;
@@ -419,32 +368,19 @@ _gnutls_compress (comp_hd_t handle, const opaque * plain,
         z_stream *zhandle;
         int err;
 
-        size = (plain_size + plain_size) + 10;
-        *compressed = gnutls_malloc (size);
-        if (*compressed == NULL)
-          {
-            gnutls_assert ();
-            return GNUTLS_E_MEMORY_ERROR;
-          }
-
         zhandle = handle->handle;
 
         zhandle->next_in = (Bytef *) plain;
         zhandle->avail_in = plain_size;
-        zhandle->next_out = (Bytef *) * compressed;
-        zhandle->avail_out = size;
+        zhandle->next_out = (Bytef *) compressed;
+        zhandle->avail_out = max_comp_size;
 
         err = deflate (zhandle, Z_SYNC_FLUSH);
-
         if (err != Z_OK || zhandle->avail_in != 0)
-          {
-            gnutls_assert ();
-            gnutls_free (*compressed);
-            *compressed = NULL;
-            return GNUTLS_E_COMPRESSION_FAILED;
-          }
+          return gnutls_assert_val(GNUTLS_E_COMPRESSION_FAILED);
 
-        compressed_size = size - zhandle->avail_out;
+
+        compressed_size = max_comp_size - zhandle->avail_out;
         break;
       }
 #endif
@@ -458,13 +394,6 @@ _gnutls_compress (comp_hd_t handle, const opaque * plain,
                      (float) ((float) compressed_size / (float) plain_size));
 #endif
 
-  if ((size_t) compressed_size > max_comp_size)
-    {
-      gnutls_free (*compressed);
-      *compressed = NULL;
-      return GNUTLS_E_COMPRESSION_FAILED;
-    }
-
   return compressed_size;
 }
 
@@ -472,12 +401,12 @@ _gnutls_compress (comp_hd_t handle, const opaque * plain,
 
 int
 _gnutls_decompress (comp_hd_t handle, opaque * compressed,
-                    size_t compressed_size, opaque ** plain,
-                    size_t max_record_size)
+                    size_t compressed_size, opaque * plain,
+                    size_t max_plain_size)
 {
   int plain_size = GNUTLS_E_DECOMPRESSION_FAILED;
 
-  if (compressed_size > max_record_size + EXTRA_COMP_SIZE)
+  if (compressed_size > max_plain_size + EXTRA_COMP_SIZE)
     {
       gnutls_assert ();
       return GNUTLS_E_DECOMPRESSION_FAILED;
@@ -499,51 +428,21 @@ _gnutls_decompress (comp_hd_t handle, opaque * compressed,
       {
         uLongf out_size;
         z_stream *zhandle;
-        int cur_pos;
         int err;
 
-        *plain = NULL;
-        out_size = compressed_size + compressed_size;
-        plain_size = 0;
-
         zhandle = handle->handle;
 
         zhandle->next_in = (Bytef *) compressed;
         zhandle->avail_in = compressed_size;
 
-        cur_pos = 0;
-
-        do
-          {
-            out_size += 512;
-            *plain = gnutls_realloc_fast (*plain, out_size);
-            if (*plain == NULL)
-              {
-                gnutls_assert ();
-                return GNUTLS_E_MEMORY_ERROR;
-              }
-
-            zhandle->next_out = (Bytef *) (*plain + cur_pos);
-            zhandle->avail_out = out_size - cur_pos;
-
-            err = inflate (zhandle, Z_SYNC_FLUSH);
-
-            cur_pos = out_size - zhandle->avail_out;
-
-          }
-        while ((err == Z_BUF_ERROR && zhandle->avail_out == 0
-                && out_size < max_record_size)
-               || (err == Z_OK && zhandle->avail_in != 0));
+        zhandle->next_out = (Bytef *) plain;
+        zhandle->avail_out = max_plain_size;
+        err = inflate (zhandle, Z_SYNC_FLUSH);
 
         if (err != Z_OK)
-          {
-            gnutls_assert ();
-            gnutls_free (*plain);
-            *plain = NULL;
-            return GNUTLS_E_DECOMPRESSION_FAILED;
-          }
+          return gnutls_assert_val(GNUTLS_E_DECOMPRESSION_FAILED);
 
-        plain_size = out_size - zhandle->avail_out;
+        plain_size = max_plain_size - zhandle->avail_out;
         break;
       }
 #endif
@@ -552,13 +451,5 @@ _gnutls_decompress (comp_hd_t handle, opaque * compressed,
       return GNUTLS_E_INTERNAL_ERROR;
     }                           /* switch */
 
-  if ((size_t) plain_size > max_record_size)
-    {
-      gnutls_assert ();
-      gnutls_free (*plain);
-      *plain = NULL;
-      return GNUTLS_E_DECOMPRESSION_FAILED;
-    }
-
   return plain_size;
 }
diff --git a/lib/gnutls_compress.h b/lib/gnutls_compress.h
index 2bc88c5..7f3545c 100644
--- a/lib/gnutls_compress.h
+++ b/lib/gnutls_compress.h
@@ -22,15 +22,6 @@
 #ifndef GNUTLS_COMPRESS_H
 #define GNUTLS_COMPRESS_H
 
-int _gnutls_m_plaintext2compressed (gnutls_session_t session,
-                                    gnutls_datum_t * compressed,
-                                    const gnutls_datum_t * plaintext,
-                                    const record_parameters_st * params);
-int _gnutls_m_compressed2plaintext (gnutls_session_t session,
-                                    gnutls_datum_t * plain,
-                                    const gnutls_datum_t * compressed,
-                                    const record_parameters_st * params);
-
 /* Algorithm handling. */
 int _gnutls_supported_compression_methods (gnutls_session_t session,
                                            uint8_t * comp, size_t max_comp);
@@ -54,10 +45,10 @@ comp_hd_t _gnutls_comp_init (gnutls_compression_method_t, int d);
 void _gnutls_comp_deinit (comp_hd_t handle, int d);
 
 int _gnutls_decompress (comp_hd_t handle, opaque * compressed,
-                        size_t compressed_size, opaque ** plain,
-                        size_t max_record_size);
+                        size_t compressed_size, opaque * plain,
+                        size_t max_plain_size);
 int _gnutls_compress (comp_hd_t, const opaque * plain, size_t plain_size,
-                      opaque ** compressed, size_t max_comp_size);
+                      opaque * compressed, size_t max_comp_size);
 
 struct gnutls_compression_entry
 {
diff --git a/lib/gnutls_record.c b/lib/gnutls_record.c
index 22e4923..4ff2951 100644
--- a/lib/gnutls_record.c
+++ b/lib/gnutls_record.c
@@ -986,7 +986,10 @@ begin:
   if (bufel == NULL)
     return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
 
-  decrypted = _mbuffer_alloc(record.length+EXTRA_COMP_SIZE, record.length+EXTRA_COMP_SIZE);
+  /* We allocate the maximum possible to allow few compressed bytes to expand to a
+   * full record.
+   */
+  decrypted = _mbuffer_alloc(MAX_RECORD_RECV_SIZE(session), MAX_RECORD_RECV_SIZE(session));
   if (decrypted == NULL)
     return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
 
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 63ae665..7ed9d25 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -58,7 +58,7 @@ noinst_LTLIBRARIES = libutils.la
 libutils_la_SOURCES = utils.h utils.c
 
 ctests = simple gc set_pkcs12_cred certder certuniqueid mpi		\
-	certificate_set_x509_crl dn parse_ca moredn mini		\
+	certificate_set_x509_crl dn parse_ca moredn mini mini-deflate	\
 	hostname-check cve-2008-4989 pkcs12_s2k chainverify crq_key_id	\
 	x509sign-verify cve-2009-1415 cve-2009-1416 crq_apis		\
 	init_roundtrip pkcs12_s2k_pem dn2 mini-eagain			\
diff --git a/tests/eagain-common.h b/tests/eagain-common.h
index c55e97c..07d5148 100644
--- a/tests/eagain-common.h
+++ b/tests/eagain-common.h
@@ -32,6 +32,9 @@
       ret = gnutls_record_send (c, msg, msglen); \
     } \
   while(ret == GNUTLS_E_AGAIN); \
+  \
+  if (ret < 0) fail ("client send error: %s\n", gnutls_strerror (ret)); \
+  \
   do \
     { \
       do \
@@ -54,6 +57,7 @@
           ns = gnutls_record_send (server, msg, msglen); \
         } \
       while (ns == GNUTLS_E_AGAIN); \
+      if (ns < 0) fail ("server send error: %s\n", gnutls_strerror (ret)); \
       do \
         { \
           ret = gnutls_record_recv (client, buf, buflen); \
@@ -81,6 +85,7 @@
               ns = gnutls_record_send (client, buf, msglen); \
             } \
           while (ns == GNUTLS_E_AGAIN); \
+          if (ns < 0) fail ("client send error: %s\n", gnutls_strerror (ret)); \
           transferred += ret; \
           if (debug) \
             fputs (".", stdout); \
diff --git a/tests/mini-deflate.c b/tests/mini-deflate.c
new file mode 100644
index 0000000..4edd4db
--- /dev/null
+++ b/tests/mini-deflate.c
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2008, 2010 Free Software Foundation, Inc.
+ *
+ * Author: Simon Josefsson
+ *
+ * This file is part of GnuTLS.
+ *
+ * GnuTLS is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuTLS is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GnuTLS; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <gnutls/gnutls.h>
+#include "eagain-common.h"
+
+#include "utils.h"
+
+static void
+tls_log_func (int level, const char *str)
+{
+  fprintf (stderr, "|<%d>| %s", level, str);
+}
+
+#define MAX_BUF 6*1024
+#define MSG "Hello TLS, and Hello and Hello and Hello"
+
+void
+doit (void)
+{
+  /* Server stuff. */
+  gnutls_anon_server_credentials_t s_anoncred;
+  const gnutls_datum_t p3 = { (char *) pkcs3, strlen (pkcs3) };
+  static gnutls_dh_params_t dh_params;
+  gnutls_session_t server;
+  int sret = GNUTLS_E_AGAIN;
+  /* Client stuff. */
+  gnutls_anon_client_credentials_t c_anoncred;
+  gnutls_session_t client;
+  int cret = GNUTLS_E_AGAIN;
+  /* Need to enable anonymous KX specifically. */
+  char buffer[MAX_BUF + 1];
+  ssize_t ns;
+  int ret, transferred = 0, msglen;
+
+  /* General init. */
+  gnutls_global_init ();
+  gnutls_global_set_log_function (tls_log_func);
+  if (debug)
+    gnutls_global_set_log_level (4711);
+
+  /* Init server */
+  gnutls_anon_allocate_server_credentials (&s_anoncred);
+  gnutls_dh_params_init (&dh_params);
+  gnutls_dh_params_import_pkcs3 (dh_params, &p3, GNUTLS_X509_FMT_PEM);
+  gnutls_anon_set_server_dh_params (s_anoncred, dh_params);
+  gnutls_init (&server, GNUTLS_SERVER);
+  gnutls_priority_set_direct (server, "NONE:+VERS-TLS-ALL:+CIPHER-ALL:+MAC-ALL:+SIGN-ALL:+COMP-DEFLATE:+ANON-DH", NULL);
+  gnutls_credentials_set (server, GNUTLS_CRD_ANON, s_anoncred);
+  gnutls_dh_set_prime_bits (server, 1024);
+  gnutls_transport_set_push_function (server, server_push);
+  gnutls_transport_set_pull_function (server, server_pull);
+  gnutls_transport_set_ptr (server, (gnutls_transport_ptr_t)server);
+
+  /* Init client */
+  gnutls_anon_allocate_client_credentials (&c_anoncred);
+  gnutls_init (&client, GNUTLS_CLIENT);
+  gnutls_priority_set_direct (client, "NONE:+VERS-TLS-ALL:+CIPHER-ALL:+MAC-ALL:+SIGN-ALL:+COMP-DEFLATE:+ANON-DH", NULL);
+  gnutls_credentials_set (client, GNUTLS_CRD_ANON, c_anoncred);
+  gnutls_transport_set_push_function (client, client_push);
+  gnutls_transport_set_pull_function (client, client_pull);
+  gnutls_transport_set_ptr (client, (gnutls_transport_ptr_t)client);
+
+  HANDSHAKE(client, server);
+
+  if (debug)
+    success ("Handshake established\n");
+
+  msglen = strlen(MSG);
+  TRANSFER(client, server, MSG, msglen, buffer, MAX_BUF);
+  if (debug)
+    fputs ("\n", stdout);
+
+  gnutls_bye (client, GNUTLS_SHUT_RDWR);
+  gnutls_bye (server, GNUTLS_SHUT_RDWR);
+
+  gnutls_deinit (client);
+  gnutls_deinit (server);
+
+  gnutls_anon_free_client_credentials (c_anoncred);
+  gnutls_anon_free_server_credentials (s_anoncred);
+
+  gnutls_dh_params_deinit (dh_params);
+
+  gnutls_global_deinit ();
+}
-- 
1.7.2.5
openSUSE Build Service is sponsored by