Create BIO_write_ex() which handles size_t arguments
authorMatt Caswell <matt@openssl.org>
Thu, 20 Oct 2016 14:18:39 +0000 (15:18 +0100)
committerMatt Caswell <matt@openssl.org>
Fri, 28 Oct 2016 08:48:54 +0000 (09:48 +0100)
Also extend BIO_METHOD to be able to supply an implementation for the new
BIO_write_ex function.

Reviewed-by: Richard Levitte <levitte@openssl.org>
26 files changed:
crypto/asn1/bio_asn1.c
crypto/bio/bf_buff.c
crypto/bio/bf_lbuf.c
crypto/bio/bf_nbio.c
crypto/bio/bf_null.c
crypto/bio/bio_err.c
crypto/bio/bio_lib.c
crypto/bio/bio_meth.c
crypto/bio/bss_acpt.c
crypto/bio/bss_bio.c
crypto/bio/bss_conn.c
crypto/bio/bss_dgram.c
crypto/bio/bss_fd.c
crypto/bio/bss_file.c
crypto/bio/bss_log.c
crypto/bio/bss_mem.c
crypto/bio/bss_null.c
crypto/bio/bss_sock.c
crypto/evp/bio_b64.c
crypto/evp/bio_enc.c
crypto/evp/bio_md.c
crypto/evp/bio_ok.c
include/internal/bio.h
include/openssl/bio.h
ssl/bio_ssl.c
util/libcrypto.num

index d270b3313d0f05e19bc9f36759488a046eea04ec..3d3f8e4c1ef310fbaf1673647b6ae3e5053b0854 100644 (file)
@@ -78,6 +78,8 @@ static int asn1_bio_setup_ex(BIO *b, BIO_ASN1_BUF_CTX *ctx,
 static const BIO_METHOD methods_asn1 = {
     BIO_TYPE_ASN1,
     "asn1",
+    /* TODO: Convert to new style write function */
+    bwrite_conv,
     asn1_bio_write,
     /* TODO: Convert to new style read function */
     bread_conv,
index fc0b8fa648f8bcfca73fb5b7d4c6140ad43edcda..7a730954889dadf456bc7968928149a8d8c2bc93 100644 (file)
@@ -25,6 +25,8 @@ static long buffer_callback_ctrl(BIO *h, int cmd, bio_info_cb *fp);
 static const BIO_METHOD methods_buffer = {
     BIO_TYPE_BUFFER,
     "buffer",
+    /* TODO: Convert to new style write function */
+    bwrite_conv,
     buffer_write,
     /* TODO: Convert to new style read function */
     bread_conv,
index c3b1a1ff3ebad8a2ff529470cae71da711ce8f35..0cee526bfde7c865dfad2e01e2b2c91a2c56d5b4 100644 (file)
@@ -30,6 +30,8 @@ static long linebuffer_callback_ctrl(BIO *h, int cmd, bio_info_cb *fp);
 static const BIO_METHOD methods_linebuffer = {
     BIO_TYPE_LINEBUFFER,
     "linebuffer",
+    /* TODO: Convert to new style write function */
+    bwrite_conv,
     linebuffer_write,
     /* TODO: Convert to new style read function */
     bread_conv,
index 32698432c603e9caea7c76d886144eef0968c6fe..1d98a942f37109aed8755a3059c7754c6747d8f3 100644 (file)
@@ -34,6 +34,8 @@ typedef struct nbio_test_st {
 static const BIO_METHOD methods_nbiof = {
     BIO_TYPE_NBIO_TEST,
     "non-blocking IO test filter",
+    /* TODO: Convert to new style write function */
+    bwrite_conv,
     nbiof_write,
     /* TODO: Convert to new style read function */
     bread_conv,
index ed7bd98d750ee82f8f75b641907327f179629206..ff2a04ccd8179226b78ef7069f3b7f082f4cc155 100644 (file)
@@ -27,6 +27,8 @@ static long nullf_callback_ctrl(BIO *h, int cmd, bio_info_cb *fp);
 static const BIO_METHOD methods_nullf = {
     BIO_TYPE_NULL_FILTER,
     "NULL filter",
+    /* TODO: Convert to new style write function */
+    bwrite_conv,
     nullf_write,
     /* TODO: Convert to new style read function */
     bread_conv,
index 21f7b4c0b98d496d69e69f463cc2d86d471484b3..68399aa54a1d42d4f1fef61f33a2289c3460a126 100644 (file)
@@ -50,6 +50,7 @@ static ERR_STRING_DATA BIO_str_functs[] = {
     {ERR_FUNC(BIO_F_BIO_SOCK_INFO), "BIO_sock_info"},
     {ERR_FUNC(BIO_F_BIO_SOCK_INIT), "BIO_sock_init"},
     {ERR_FUNC(BIO_F_BIO_WRITE), "BIO_write"},
+    {ERR_FUNC(BIO_F_BIO_WRITE_EX), "BIO_write_ex"},
     {ERR_FUNC(BIO_F_BUFFER_CTRL), "buffer_ctrl"},
     {ERR_FUNC(BIO_F_CONN_CTRL), "conn_ctrl"},
     {ERR_FUNC(BIO_F_CONN_STATE), "conn_state"},
index c3633f255f0c8b9af8f45f971aca7a38af8266fb..a2cbbfd7a07cc900cbfcae5715171d3bac45358c 100644 (file)
@@ -284,35 +284,54 @@ int BIO_read_ex(BIO *b, void *out, size_t outl, size_t *read)
 
 int BIO_write(BIO *b, const void *in, int inl)
 {
-    int i;
-    long (*cb) (BIO *, int, const char *, int, long, long);
+    size_t written;
+    int ret;
+
+    if (inl < 0)
+        return 0;
+
+    ret = BIO_write_ex(b, in, (size_t)inl, &written);
+
+    if (ret > 0) {
+        /* *written should always be <= inl */
+        ret = (int)written;
+    }
+
+    return ret;
+}
+
+int BIO_write_ex(BIO *b, const void *in, size_t inl, size_t *written)
+{
+    int ret;
 
     if (b == NULL)
         return (0);
 
-    cb = b->callback;
     if ((b->method == NULL) || (b->method->bwrite == NULL)) {
-        BIOerr(BIO_F_BIO_WRITE, BIO_R_UNSUPPORTED_METHOD);
+        BIOerr(BIO_F_BIO_WRITE_EX, BIO_R_UNSUPPORTED_METHOD);
         return (-2);
     }
 
-    if ((cb != NULL) &&
-        ((i = (int)cb(b, BIO_CB_WRITE, in, inl, 0L, 1L)) <= 0))
-        return (i);
+    if ((b->callback != NULL || b->callback_ex != NULL) &&
+        ((ret = bio_call_callback(b, BIO_CB_WRITE, in, inl, 0, 0L, 1L, written,
+                                  NULL)) <= 0))
+        return ret;
 
     if (!b->init) {
-        BIOerr(BIO_F_BIO_WRITE, BIO_R_UNINITIALIZED);
-        return (-2);
+        BIOerr(BIO_F_BIO_WRITE_EX, BIO_R_UNINITIALIZED);
+        return -2;
     }
 
-    i = b->method->bwrite(b, in, inl);
+    ret = b->method->bwrite(b, in, inl, written);
 
-    if (i > 0)
-        b->num_write += (uint64_t)i;
+    if (ret > 0)
+        b->num_write += (uint64_t)*written;
 
-    if (cb != NULL)
-        i = (int)cb(b, BIO_CB_WRITE | BIO_CB_RETURN, in, inl, 0L, (long)i);
-    return (i);
+    if (b->callback != NULL || b->callback_ex != NULL)
+        ret = bio_call_callback(b, BIO_CB_WRITE | BIO_CB_RETURN, in, inl, 0,
+                                0L, ret, written, NULL);
+
+    return ret;
 }
 
 int BIO_puts(BIO *b, const char *in)
index c10f8d01d1fa960c7a5c471664192de1a7610576..7b4c340cdf34266ec6e28310f871fc9cc28d8111 100644 (file)
@@ -50,13 +50,48 @@ void BIO_meth_free(BIO_METHOD *biom)
 }
 
 int (*BIO_meth_get_write(BIO_METHOD *biom)) (BIO *, const char *, int)
+{
+    return biom->bwrite_old;
+}
+
+int (*BIO_meth_get_write_ex(BIO_METHOD *biom)) (BIO *, const char *, size_t,
+                                                size_t *)
 {
     return biom->bwrite;
 }
 
+/* Conversion for old style bwrite to new style */
+int bwrite_conv(BIO *bio, const char *in, size_t inl, size_t *written)
+{
+    int ret;
+
+    if (inl > INT_MAX)
+        return 0;
+
+    ret = bio->method->bwrite_old(bio, in, (int)inl);
+
+    if (ret <= 0) {
+        *written = 0;
+        return ret;
+    }
+
+    *written = (size_t)ret;
+
+    return 1;
+}
+
 int BIO_meth_set_write(BIO_METHOD *biom,
                        int (*bwrite) (BIO *, const char *, int))
 {
+    biom->bwrite_old = bwrite;
+    biom->bwrite = bwrite_conv;
+    return 1;
+}
+
+int BIO_meth_set_write_ex(BIO_METHOD *biom,
+                       int (*bwrite) (BIO *, const char *, size_t, size_t *))
+{
+    biom->bwrite_old = NULL;
     biom->bwrite = bwrite;
     return 1;
 }
@@ -102,6 +137,7 @@ int BIO_meth_set_read(BIO_METHOD *biom,
 int BIO_meth_set_read_ex(BIO_METHOD *biom,
                          int (*bread) (BIO *, char *, size_t, size_t *))
 {
+    biom->bread_old = NULL;
     biom->bread = bread;
     return 1;
 }
index 5151ff61c60718bfa0ceddcbfe3660871b02e213..e490fcdf73712355b8357b84edf4dd618dcefa2f 100644 (file)
@@ -54,6 +54,8 @@ static void BIO_ACCEPT_free(BIO_ACCEPT *a);
 static const BIO_METHOD methods_acceptp = {
     BIO_TYPE_ACCEPT,
     "socket accept",
+    /* TODO: Convert to new style write function */
+    bwrite_conv,
     acpt_write,
     /* TODO: Convert to new style read function */
     bread_conv,
index ce775601f04b9e640e6864ce5bd280b371592fc8..9fa47600c9fe504343071f1572087e2b54f79a75 100644 (file)
@@ -39,6 +39,8 @@ static void bio_destroy_pair(BIO *bio);
 static const BIO_METHOD methods_biop = {
     BIO_TYPE_BIO,
     "BIO pair",
+    /* TODO: Convert to new style write function */
+    bwrite_conv,
     bio_write,
     /* TODO: Convert to new style read function */
     bread_conv,
index eff3f68144c5ec3380f65b7f6a76c52c9d3ef2c2..ddbc8967f6e93b7dc3ebf02cc673036d6fcee4b7 100644 (file)
@@ -58,6 +58,8 @@ void BIO_CONNECT_free(BIO_CONNECT *a);
 static const BIO_METHOD methods_connectp = {
     BIO_TYPE_CONNECT,
     "socket connect",
+    /* TODO: Convert to new style write function */
+    bwrite_conv,
     conn_write,
     /* TODO: Convert to new style read function */
     bread_conv,
index 6e5d482774aa0b38ec112115b5d476f6db305e81..89936ff17729e19b2978e223ef322ee66ad84999 100644 (file)
@@ -73,6 +73,8 @@ static void get_current_time(struct timeval *t);
 static const BIO_METHOD methods_dgramp = {
     BIO_TYPE_DGRAM,
     "datagram socket",
+    /* TODO: Convert to new style write function */
+    bwrite_conv,
     dgram_write,
     /* TODO: Convert to new style read function */
     bread_conv,
index 78bbfd6f3bead7935d63f2f8a84258a7cdd8db3b..0f003cd89b29c01e01aa47e118e3f2f3e26c31d1 100644 (file)
@@ -59,6 +59,8 @@ int BIO_fd_should_retry(int s);
 
 static const BIO_METHOD methods_fdp = {
     BIO_TYPE_FD, "file descriptor",
+    /* TODO: Convert to new style write function */
+    bwrite_conv,
     fd_write,
     /* TODO: Convert to new style read function */
     bread_conv,
index 00684ae640e8d62370b56f445cd5081188ca7c7b..87a6f396bd421e2cf67f523ff0c1ab6d507a576f 100644 (file)
@@ -51,6 +51,8 @@ static int file_free(BIO *data);
 static const BIO_METHOD methods_filep = {
     BIO_TYPE_FILE,
     "FILE pointer",
+    /* TODO: Convert to new style write function */
+    bwrite_conv,
     file_write,
     /* TODO: Convert to new style read function */
     bread_conv,
index f262cc9d18c22f4f4256c39baf9aa3639b0ef59e..963371ed256966082e4172da501a27b5fd7d948b 100644 (file)
@@ -86,6 +86,8 @@ static void xcloselog(BIO *bp);
 
 static const BIO_METHOD methods_slg = {
     BIO_TYPE_MEM, "syslog",
+    /* TODO: Convert to new style write function */
+    bwrite_conv,
     slg_write,
     NULL,
     NULL,
index 81f7fc6d9ebd9f968ca3cec78b63cf1431442468..38ffb1025d636883e32ac0a7e353aaabd06cf565 100644 (file)
@@ -26,6 +26,8 @@ static int mem_buf_sync(BIO *h);
 static const BIO_METHOD mem_method = {
     BIO_TYPE_MEM,
     "memory buffer",
+    /* TODO: Convert to new style write function */
+    bwrite_conv,
     mem_write,
     /* TODO: Convert to new style read function */
     bread_conv,
@@ -41,6 +43,8 @@ static const BIO_METHOD mem_method = {
 static const BIO_METHOD secmem_method = {
     BIO_TYPE_MEM,
     "secure memory buffer",
+    /* TODO: Convert to new style write function */
+    bwrite_conv,
     mem_write,
     /* TODO: Convert to new style read function */
     bread_conv,
index 90c9ee161805b8b3b155135d2ada6ec0add6eeba..d197a609bd1154b020bdb78af560a91ec46363bb 100644 (file)
@@ -22,6 +22,8 @@ static int null_free(BIO *data);
 static const BIO_METHOD null_method = {
     BIO_TYPE_NULL,
     "NULL",
+    /* TODO: Convert to new style write function */
+    bwrite_conv,
     null_write,
     /* TODO: Convert to new style read function */
     bread_conv,
index 42f0f90b65d9d05104b0da1848c3fff4465a7a70..c47b160bb075b913038952c20b2422a4d190e435 100644 (file)
@@ -38,6 +38,8 @@ int BIO_sock_should_retry(int s);
 static const BIO_METHOD methods_sockp = {
     BIO_TYPE_SOCKET,
     "socket",
+    /* TODO: Convert to new style write function */
+    bwrite_conv,
     sock_write,
     /* TODO: Convert to new style read function */
     bread_conv,
index 2647be023328d7c7a24c78bc4f115a5f56b5ef4f..4f0e19eed3434250dbec14544dcb2410c80f75a6 100644 (file)
@@ -48,6 +48,8 @@ typedef struct b64_struct {
 
 static const BIO_METHOD methods_b64 = {
     BIO_TYPE_BASE64, "base64 encoding",
+    /* TODO: Convert to new style write function */
+    bwrite_conv,
     b64_write,
     /* TODO: Convert to new style read function */
     bread_conv,
index fff3e2735e17176bf908d8c3a6946430fa0e3902..7d596e0f4810a8d8bb02cddb9664c141741c0d7c 100644 (file)
@@ -47,6 +47,8 @@ typedef struct enc_struct {
 
 static const BIO_METHOD methods_enc = {
     BIO_TYPE_CIPHER, "cipher",
+    /* TODO: Convert to new style write function */
+    bwrite_conv,
     enc_write,
     /* TODO: Convert to new style read function */
     bread_conv,
index 7c61d0f3c0a9fd6db67ffa5932c54488e90c61ba..c9e38583d2f3d0625bd4b1cff75b2ec016eaefe2 100644 (file)
@@ -33,6 +33,8 @@ static long md_callback_ctrl(BIO *h, int cmd, bio_info_cb *fp);
 
 static const BIO_METHOD methods_md = {
     BIO_TYPE_MD, "message digest",
+    /* TODO: Convert to new style write function */
+    bwrite_conv,
     md_write,
     /* TODO: Convert to new style read function */
     bread_conv,
index 0a15680c4bbdbc673bf11831e0ddef66ba44c911..47228465c5c3b2918c9baced5bdad682c004c17e 100644 (file)
@@ -109,6 +109,8 @@ typedef struct ok_struct {
 
 static const BIO_METHOD methods_ok = {
     BIO_TYPE_CIPHER, "reliable",
+    /* TODO: Convert to new style write function */
+    bwrite_conv,
     ok_write,
     /* TODO: Convert to new style read function */
     bread_conv,
index f840bcd32c42888c45ccb20e13e9401653f82fca..e1fe62af3e70c13dd3b6363d95bfb1b695e1b266 100644 (file)
@@ -12,7 +12,8 @@
 struct bio_method_st {
     int type;
     const char *name;
-    int (*bwrite) (BIO *, const char *, int);
+    int (*bwrite) (BIO *, const char *, size_t, size_t *);
+    int (*bwrite_old) (BIO *, const char *, int);
     int (*bread) (BIO *, char *, size_t, size_t *);
     int (*bread_old) (BIO *, char *, int);
     int (*bputs) (BIO *, const char *);
@@ -28,4 +29,5 @@ void bio_cleanup(void);
 
 
 /* Old style to new style BIO_METHOD conversion functions */
+int bwrite_conv(BIO *bio, const char *in, size_t inl, size_t *written);
 int bread_conv(BIO *bio, char *out, size_t outl, size_t *read);
index b4b1e0acbc0c6d110c5dbcc91e6d9311bca541fb..d04946cfa5d95fda00472c88ae5cf7bde3642f34 100644 (file)
@@ -556,6 +556,7 @@ int BIO_read(BIO *b, void *data, int len);
 int BIO_read_ex(BIO *b, void *out, size_t outl, size_t *read);
 int BIO_gets(BIO *bp, char *buf, int size);
 int BIO_write(BIO *b, const void *data, int len);
+int BIO_write_ex(BIO *b, const void *in, size_t inl, size_t *written);
 int BIO_puts(BIO *bp, const char *buf);
 int BIO_indent(BIO *b, int indent, int max);
 long BIO_ctrl(BIO *bp, int cmd, long larg, void *parg);
@@ -743,8 +744,12 @@ __bio_h__attr__((__format__(__printf__, 3, 0)));
 BIO_METHOD *BIO_meth_new(int type, const char *name);
 void BIO_meth_free(BIO_METHOD *biom);
 int (*BIO_meth_get_write(BIO_METHOD *biom)) (BIO *, const char *, int);
+int (*BIO_meth_get_write_ex(BIO_METHOD *biom)) (BIO *, const char *, size_t,
+                                                size_t *);
 int BIO_meth_set_write(BIO_METHOD *biom,
                        int (*write) (BIO *, const char *, int));
+int BIO_meth_set_write_ex(BIO_METHOD *biom,
+                       int (*bwrite) (BIO *, const char *, size_t, size_t *));
 int (*BIO_meth_get_read(BIO_METHOD *biom)) (BIO *, char *, int);
 int (*BIO_meth_get_read_ex(BIO_METHOD *biom)) (BIO *, char *, size_t, size_t *);
 int BIO_meth_set_read(BIO_METHOD *biom,
@@ -812,6 +817,7 @@ int ERR_load_BIO_strings(void);
 # define BIO_F_BIO_SOCK_INFO                              141
 # define BIO_F_BIO_SOCK_INIT                              112
 # define BIO_F_BIO_WRITE                                  113
+# define BIO_F_BIO_WRITE_EX                               119
 # define BIO_F_BUFFER_CTRL                                114
 # define BIO_F_CONN_CTRL                                  127
 # define BIO_F_CONN_STATE                                 115
index 59a04a39951564c078e5666d04f1dad5435cc975..e06c580871ee12207c08b3b2a26948c4daa8a977 100644 (file)
@@ -16,7 +16,7 @@
 #include <openssl/err.h>
 #include "ssl_locl.h"
 
-static int ssl_write(BIO *h, const char *buf, int num);
+static int ssl_write(BIO *h, const char *buf, size_t num, size_t *written);
 static int ssl_read(BIO *b, char *out, size_t outl, size_t *read);
 static int ssl_puts(BIO *h, const char *str);
 static long ssl_ctrl(BIO *h, int cmd, long arg1, void *arg2);
@@ -36,6 +36,7 @@ typedef struct bio_ssl_st {
 static const BIO_METHOD methods_sslp = {
     BIO_TYPE_SSL, "ssl",
     ssl_write,
+    NULL,
     ssl_read,
     NULL,
     ssl_puts,
@@ -106,13 +107,15 @@ static int ssl_read(BIO *b, char *out, size_t outl, size_t *read)
         return -1;
 
     ret = SSL_read(ssl, out, outl);
+    if (ret > 0)
+        *read = ret;
 
     switch (SSL_get_error(ssl, ret)) {
     case SSL_ERROR_NONE:
         if (ret <= 0)
             break;
         if (sb->renegotiate_count > 0) {
-            sb->byte_count += ret;
+            sb->byte_count += *read;
             if (sb->byte_count > sb->renegotiate_count) {
                 sb->byte_count = 0;
                 sb->num_renegotiates++;
@@ -159,15 +162,10 @@ static int ssl_read(BIO *b, char *out, size_t outl, size_t *read)
 
     BIO_set_retry_reason(b, retry_reason);
 
-    if (ret < 0)
-        return ret;
-
-    *read = (size_t)ret;
-
-    return 1;
+    return ret;
 }
 
-static int ssl_write(BIO *b, const char *out, int outl)
+static int ssl_write(BIO *b, const char *out, size_t outl, size_t *written)
 {
     int ret, r = 0;
     int retry_reason = 0;
@@ -181,9 +179,9 @@ static int ssl_write(BIO *b, const char *out, int outl)
 
     BIO_clear_retry_flags(b);
 
-    /*
-     * ret=SSL_do_handshake(ssl); if (ret > 0)
-     */
+    if (outl > INT_MAX)
+        return 0;
+
     ret = SSL_write(ssl, out, outl);
 
     switch (SSL_get_error(ssl, ret)) {
@@ -230,6 +228,12 @@ static int ssl_write(BIO *b, const char *out, int outl)
     }
 
     BIO_set_retry_reason(b, retry_reason);
+
+    if (ret > 0) {
+        *written = ret;
+        ret = 1;
+    }
+
     return ret;
 }
 
index 0b7917b9f220623ed818a1631da753464236c5a2..e04580c4859d9fa1f4c9dd69ca92a474dadc119b 100644 (file)
@@ -4213,3 +4213,6 @@ BIO_set_callback_ex                     4163      1_1_1   EXIST::FUNCTION:
 BIO_get_callback_ex                     4164   1_1_1   EXIST::FUNCTION:
 BIO_meth_set_read_ex                    4165   1_1_1   EXIST::FUNCTION:
 BIO_meth_get_read_ex                    4166   1_1_1   EXIST::FUNCTION:
+BIO_write_ex                            4167   1_1_1   EXIST::FUNCTION:
+BIO_meth_get_write_ex                   4168   1_1_1   EXIST::FUNCTION:
+BIO_meth_set_write_ex                   4169   1_1_1   EXIST::FUNCTION: