openssl_strerror_r: Fix handling of GNU strerror_r
[openssl.git] / ssl / record / ssl3_buffer.c
index 8a2a6e473da6e4bb441145136f5101e215456f6d..53bd4cb190d0e7b0c8edc204e1ba11b1c5a3748b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the OpenSSL license (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -60,26 +60,30 @@ int ssl3_setup_read_buffer(SSL *s)
 #endif
         if (b->default_len > len)
             len = b->default_len;
-        if ((p = OPENSSL_malloc(len)) == NULL)
-            goto err;
+        if ((p = OPENSSL_malloc(len)) == NULL) {
+            /*
+             * We've got a malloc failure, and we're still initialising buffers.
+             * We assume we're so doomed that we won't even be able to send an
+             * alert.
+             */
+            SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_SSL3_SETUP_READ_BUFFER,
+                     ERR_R_MALLOC_FAILURE);
+            return 0;
+        }
         b->buf = p;
         b->len = len;
     }
 
     RECORD_LAYER_set_packet(&s->rlayer, &(b->buf[0]));
     return 1;
-
- err:
-    SSLerr(SSL_F_SSL3_SETUP_READ_BUFFER, ERR_R_MALLOC_FAILURE);
-    return 0;
 }
 
-int ssl3_setup_write_buffer(SSL *s, unsigned int numwpipes, size_t len)
+int ssl3_setup_write_buffer(SSL *s, size_t numwpipes, size_t len)
 {
     unsigned char *p;
     size_t align = 0, headerlen;
     SSL3_BUFFER *wb;
-    unsigned int currpipe;
+    size_t currpipe;
 
     s->rlayer.numwpipes = numwpipes;
 
@@ -93,7 +97,7 @@ int ssl3_setup_write_buffer(SSL *s, unsigned int numwpipes, size_t len)
         align = (-SSL3_RT_HEADER_LENGTH) & (SSL3_ALIGN_PAYLOAD - 1);
 #endif
 
-        len = s->max_send_fragment
+        len = ssl_get_max_send_fragment(s)
             + SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD + headerlen + align;
 #ifndef OPENSSL_NO_COMP
         if (ssl_allow_compression(s))
@@ -105,36 +109,52 @@ int ssl3_setup_write_buffer(SSL *s, unsigned int numwpipes, size_t len)
 
     wb = RECORD_LAYER_get_wbuf(&s->rlayer);
     for (currpipe = 0; currpipe < numwpipes; currpipe++) {
-        if (wb[currpipe].buf == NULL) {
-            if ((p = OPENSSL_malloc(len)) == NULL) {
+        SSL3_BUFFER *thiswb = &wb[currpipe];
+
+        if (thiswb->buf != NULL && thiswb->len != len) {
+            OPENSSL_free(thiswb->buf);
+            thiswb->buf = NULL;         /* force reallocation */
+        }
+
+        if (thiswb->buf == NULL) {
+            p = OPENSSL_malloc(len);
+            if (p == NULL) {
                 s->rlayer.numwpipes = currpipe;
-                goto err;
+                /*
+                 * We've got a malloc failure, and we're still initialising
+                 * buffers. We assume we're so doomed that we won't even be able
+                 * to send an alert.
+                 */
+                SSLfatal(s, SSL_AD_NO_ALERT,
+                         SSL_F_SSL3_SETUP_WRITE_BUFFER, ERR_R_MALLOC_FAILURE);
+                return 0;
             }
-            wb[currpipe].buf = p;
-            wb[currpipe].len = len;
+            memset(thiswb, 0, sizeof(SSL3_BUFFER));
+            thiswb->buf = p;
+            thiswb->len = len;
         }
     }
 
     return 1;
-
- err:
-    SSLerr(SSL_F_SSL3_SETUP_WRITE_BUFFER, ERR_R_MALLOC_FAILURE);
-    return 0;
 }
 
 int ssl3_setup_buffers(SSL *s)
 {
-    if (!ssl3_setup_read_buffer(s))
+    if (!ssl3_setup_read_buffer(s)) {
+        /* SSLfatal() already called */
         return 0;
-    if (!ssl3_setup_write_buffer(s, 1, 0))
+    }
+    if (!ssl3_setup_write_buffer(s, 1, 0)) {
+        /* SSLfatal() already called */
         return 0;
+    }
     return 1;
 }
 
 int ssl3_release_write_buffer(SSL *s)
 {
     SSL3_BUFFER *wb;
-    unsigned int pipes;
+    size_t pipes;
 
     pipes = s->rlayer.numwpipes;
     while (pipes > 0) {