Create BIO_read_ex() which handles size_t arguments
authorMatt Caswell <matt@openssl.org>
Mon, 5 Sep 2016 16:26:58 +0000 (17:26 +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_read function.

Reviewed-by: Richard Levitte <levitte@openssl.org>
27 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_lcl.h
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 d3cc108..d270b33 100644 (file)
@@ -79,6 +79,8 @@ static const BIO_METHOD methods_asn1 = {
     BIO_TYPE_ASN1,
     "asn1",
     asn1_bio_write,
+    /* TODO: Convert to new style read function */
+    bread_conv,
     asn1_bio_read,
     asn1_bio_puts,
     asn1_bio_gets,
index b2a387b..fc0b8fa 100644 (file)
@@ -26,6 +26,8 @@ static const BIO_METHOD methods_buffer = {
     BIO_TYPE_BUFFER,
     "buffer",
     buffer_write,
+    /* TODO: Convert to new style read function */
+    bread_conv,
     buffer_read,
     buffer_puts,
     buffer_gets,
index b3c2b5e..c3b1a1f 100644 (file)
@@ -31,6 +31,8 @@ static const BIO_METHOD methods_linebuffer = {
     BIO_TYPE_LINEBUFFER,
     "linebuffer",
     linebuffer_write,
+    /* TODO: Convert to new style read function */
+    bread_conv,
     linebuffer_read,
     linebuffer_puts,
     linebuffer_gets,
index 364d9fb..3269843 100644 (file)
@@ -35,6 +35,8 @@ static const BIO_METHOD methods_nbiof = {
     BIO_TYPE_NBIO_TEST,
     "non-blocking IO test filter",
     nbiof_write,
+    /* TODO: Convert to new style read function */
+    bread_conv,
     nbiof_read,
     nbiof_puts,
     nbiof_gets,
index 0736b3f..ed7bd98 100644 (file)
@@ -28,6 +28,8 @@ static const BIO_METHOD methods_nullf = {
     BIO_TYPE_NULL_FILTER,
     "NULL filter",
     nullf_write,
+    /* TODO: Convert to new style read function */
+    bread_conv,
     nullf_read,
     nullf_puts,
     nullf_gets,
index 98c90d6..21f7b4c 100644 (file)
@@ -44,6 +44,7 @@ static ERR_STRING_DATA BIO_str_functs[] = {
     {ERR_FUNC(BIO_F_BIO_PARSE_HOSTSERV), "BIO_parse_hostserv"},
     {ERR_FUNC(BIO_F_BIO_PUTS), "BIO_puts"},
     {ERR_FUNC(BIO_F_BIO_READ), "BIO_read"},
+    {ERR_FUNC(BIO_F_BIO_READ_EX), "BIO_read_ex"},
     {ERR_FUNC(BIO_F_BIO_SOCKET), "BIO_socket"},
     {ERR_FUNC(BIO_F_BIO_SOCKET_NBIO), "BIO_socket_nbio"},
     {ERR_FUNC(BIO_F_BIO_SOCK_INFO), "BIO_sock_info"},
index 39178cf..d46f4e7 100644 (file)
@@ -114,7 +114,8 @@ typedef struct bio_f_buffer_ctx_struct {
 struct bio_st {
     const BIO_METHOD *method;
     /* bio, mode, argp, argi, argl, ret */
-    long (*callback) (struct bio_st *, int, const char *, int, long, long);
+    BIO_callback_fn callback;
+    BIO_callback_fn_ex callback_ex;
     char *cb_arg;               /* first argument for the callback */
     int init;
     int shutdown;
index 62392c3..c3633f2 100644 (file)
@@ -142,18 +142,26 @@ void BIO_set_flags(BIO *b, int flags)
     b->flags |= flags;
 }
 
-long (*BIO_get_callback(const BIO *b)) (struct bio_st *, int, const char *,
-                                        int, long, long) {
+BIO_callback_fn BIO_get_callback(const BIO *b)
+{
     return b->callback;
 }
 
-void BIO_set_callback(BIO *b,
-                      long (*cb) (struct bio_st *, int, const char *, int,
-                                  long, long))
+void BIO_set_callback(BIO *b, BIO_callback_fn cb)
 {
     b->callback = cb;
 }
 
+BIO_callback_fn_ex BIO_get_callback_ex(const BIO *b)
+{
+    return b->callback_ex;
+}
+
+void BIO_set_callback_ex(BIO *b, BIO_callback_fn_ex cb)
+{
+    b->callback_ex = cb;
+}
+
 void BIO_set_callback_arg(BIO *b, char *arg)
 {
     b->cb_arg = arg;
@@ -174,34 +182,104 @@ int BIO_method_type(const BIO *b)
     return b->method->type;
 }
 
+static int bio_call_callback(BIO *b, int oper, const char *argp, size_t len,
+                             int argi, long argl, int inret, size_t *processed,
+                             long *lret)
+{
+    long ret;
+    int bareoper;
+
+    if (b->callback_ex != NULL) {
+        return b->callback_ex(b, oper, argp, len, argi, argl, inret, processed,
+                              lret);
+    }
+
+    /* Strip off the BIO_CB_RETURN flag */
+    bareoper = oper & ~BIO_CB_RETURN;
+    /*
+     * We have an old style callback, so we will have to do nasty casts and
+     * check for overflows.
+     */
+    if (bareoper == BIO_CB_READ || bareoper == BIO_CB_WRITE
+            || bareoper == BIO_CB_GETS) {
+        /* In this case |len| is set, and should be used instead of |argi| */
+        if (len > INT_MAX)
+            return 0;
+
+        argi = (int)len;
+
+        if (inret && (oper & BIO_CB_RETURN)) {
+            if (*processed > INT_MAX)
+                return 0;
+            inret = *processed;
+        }
+    }
+
+    ret = b->callback(b, oper, argp, argi, argl, inret);
+    if (bareoper == BIO_CB_CTRL)
+        return 1;
+
+    if (ret > INT_MAX || ret < INT_MIN)
+        return 0;
+
+    if (lret != NULL)
+        *lret = ret;
+
+    if (ret >= 0) {
+        *processed = (size_t)ret;
+        ret = 1;
+    }
+
+    return (int)ret;
+}
+
 int BIO_read(BIO *b, void *out, int outl)
 {
-    int i;
-    long (*cb) (BIO *, int, const char *, int, long, long);
+    size_t read;
+    int ret;
+
+    if (outl < 0)
+        return 0;
+
+    ret = BIO_read_ex(b, out, (size_t)outl, &read);
+
+    if (ret > 0) {
+        /* *read should always be <= outl */
+        ret = (int)read;
+    }
+
+    return ret;
+}
+
+int BIO_read_ex(BIO *b, void *out, size_t outl, size_t *read)
+{
+    int ret;
 
     if ((b == NULL) || (b->method == NULL) || (b->method->bread == NULL)) {
-        BIOerr(BIO_F_BIO_READ, BIO_R_UNSUPPORTED_METHOD);
+        BIOerr(BIO_F_BIO_READ_EX, BIO_R_UNSUPPORTED_METHOD);
         return (-2);
     }
 
-    cb = b->callback;
-    if ((cb != NULL) &&
-        ((i = (int)cb(b, BIO_CB_READ, out, outl, 0L, 1L)) <= 0))
-        return (i);
+    if ((b->callback != NULL || b->callback_ex != NULL) &&
+        ((ret = bio_call_callback(b, BIO_CB_READ, out, outl, 0, 0L, 1L, read,
+                                  NULL)) <= 0))
+        return ret;
 
     if (!b->init) {
-        BIOerr(BIO_F_BIO_READ, BIO_R_UNINITIALIZED);
-        return (-2);
+        BIOerr(BIO_F_BIO_READ_EX, BIO_R_UNINITIALIZED);
+        return -2;
     }
 
-    i = b->method->bread(b, out, outl);
+    ret = b->method->bread(b, out, outl, read);
 
-    if (i > 0)
-        b->num_read += (uint64_t)i;
+    if (ret > 0)
+        b->num_read += (uint64_t)*read;
 
-    if (cb != NULL)
-        i = (int)cb(b, BIO_CB_READ | BIO_CB_RETURN, out, outl, 0L, (long)i);
-    return (i);
+    if (b->callback != NULL || b->callback_ex != NULL)
+        ret = bio_call_callback(b, BIO_CB_READ | BIO_CB_RETURN, out, outl, 0,
+                                0L, ret, read, NULL);
+
+    return ret;
 }
 
 int BIO_write(BIO *b, const void *in, int inl)
index c5f9f7e..c10f8d0 100644 (file)
@@ -62,12 +62,45 @@ int BIO_meth_set_write(BIO_METHOD *biom,
 }
 
 int (*BIO_meth_get_read(BIO_METHOD *biom)) (BIO *, char *, int)
+{
+    return biom->bread_old;
+}
+
+int (*BIO_meth_get_read_ex(BIO_METHOD *biom)) (BIO *, char *, size_t, size_t *)
 {
     return biom->bread;
 }
 
+/* Conversion for old style bread to new style */
+int bread_conv(BIO *bio, char *out, size_t outl, size_t *read)
+{
+    int ret;
+
+    if (outl > INT_MAX)
+        return 0;
+
+    ret = bio->method->bread_old(bio, out, (int)outl);
+
+    if (ret <= 0) {
+        *read = 0;
+        return ret;
+    }
+
+    *read = (size_t)ret;
+
+    return 1;
+}
+
 int BIO_meth_set_read(BIO_METHOD *biom,
                       int (*bread) (BIO *, char *, int))
+{
+    biom->bread_old = bread;
+    biom->bread = bread_conv;
+    return 1;
+}
+
+int BIO_meth_set_read_ex(BIO_METHOD *biom,
+                         int (*bread) (BIO *, char *, size_t, size_t *))
 {
     biom->bread = bread;
     return 1;
index 6fb971a..5151ff6 100644 (file)
@@ -55,6 +55,8 @@ static const BIO_METHOD methods_acceptp = {
     BIO_TYPE_ACCEPT,
     "socket accept",
     acpt_write,
+    /* TODO: Convert to new style read function */
+    bread_conv,
     acpt_read,
     acpt_puts,
     NULL,                       /* connect_gets, */
index de34f6b..ce77560 100644 (file)
@@ -40,6 +40,8 @@ static const BIO_METHOD methods_biop = {
     BIO_TYPE_BIO,
     "BIO pair",
     bio_write,
+    /* TODO: Convert to new style read function */
+    bread_conv,
     bio_read,
     bio_puts,
     NULL /* no bio_gets */ ,
index dfd0988..eff3f68 100644 (file)
@@ -59,6 +59,8 @@ static const BIO_METHOD methods_connectp = {
     BIO_TYPE_CONNECT,
     "socket connect",
     conn_write,
+    /* TODO: Convert to new style read function */
+    bread_conv,
     conn_read,
     conn_puts,
     NULL,                       /* connect_gets, */
index 6dfcc9b..6e5d482 100644 (file)
@@ -74,6 +74,8 @@ static const BIO_METHOD methods_dgramp = {
     BIO_TYPE_DGRAM,
     "datagram socket",
     dgram_write,
+    /* TODO: Convert to new style read function */
+    bread_conv,
     dgram_read,
     dgram_puts,
     NULL,                       /* dgram_gets, */
index 1e56cb6..78bbfd6 100644 (file)
@@ -60,6 +60,8 @@ int BIO_fd_should_retry(int s);
 static const BIO_METHOD methods_fdp = {
     BIO_TYPE_FD, "file descriptor",
     fd_write,
+    /* TODO: Convert to new style read function */
+    bread_conv,
     fd_read,
     fd_puts,
     fd_gets,
index 6af2d9c..00684ae 100644 (file)
@@ -52,6 +52,8 @@ static const BIO_METHOD methods_filep = {
     BIO_TYPE_FILE,
     "FILE pointer",
     file_write,
+    /* TODO: Convert to new style read function */
+    bread_conv,
     file_read,
     file_puts,
     file_gets,
index 6cbde4d..f262cc9 100644 (file)
@@ -88,6 +88,7 @@ static const BIO_METHOD methods_slg = {
     BIO_TYPE_MEM, "syslog",
     slg_write,
     NULL,
+    NULL,
     slg_puts,
     NULL,
     slg_ctrl,
index 6dc075d..81f7fc6 100644 (file)
@@ -27,6 +27,8 @@ static const BIO_METHOD mem_method = {
     BIO_TYPE_MEM,
     "memory buffer",
     mem_write,
+    /* TODO: Convert to new style read function */
+    bread_conv,
     mem_read,
     mem_puts,
     mem_gets,
@@ -40,6 +42,8 @@ static const BIO_METHOD secmem_method = {
     BIO_TYPE_MEM,
     "secure memory buffer",
     mem_write,
+    /* TODO: Convert to new style read function */
+    bread_conv,
     mem_read,
     mem_puts,
     mem_gets,
index e5c4adc..90c9ee1 100644 (file)
@@ -23,6 +23,8 @@ static const BIO_METHOD null_method = {
     BIO_TYPE_NULL,
     "NULL",
     null_write,
+    /* TODO: Convert to new style read function */
+    bread_conv,
     null_read,
     null_puts,
     null_gets,
index 570e898..42f0f90 100644 (file)
@@ -39,6 +39,8 @@ static const BIO_METHOD methods_sockp = {
     BIO_TYPE_SOCKET,
     "socket",
     sock_write,
+    /* TODO: Convert to new style read function */
+    bread_conv,
     sock_read,
     sock_puts,
     NULL,                       /* sock_gets, */
index 32a884a..2647be0 100644 (file)
@@ -49,6 +49,8 @@ typedef struct b64_struct {
 static const BIO_METHOD methods_b64 = {
     BIO_TYPE_BASE64, "base64 encoding",
     b64_write,
+    /* TODO: Convert to new style read function */
+    bread_conv,
     b64_read,
     b64_puts,
     NULL,                       /* b64_gets, */
index 5a3beef..fff3e27 100644 (file)
@@ -48,6 +48,8 @@ typedef struct enc_struct {
 static const BIO_METHOD methods_enc = {
     BIO_TYPE_CIPHER, "cipher",
     enc_write,
+    /* TODO: Convert to new style read function */
+    bread_conv,
     enc_read,
     NULL,                       /* enc_puts, */
     NULL,                       /* enc_gets, */
index cd968ec..7c61d0f 100644 (file)
@@ -34,6 +34,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",
     md_write,
+    /* TODO: Convert to new style read function */
+    bread_conv,
     md_read,
     NULL,                       /* md_puts, */
     md_gets,
index 7974b96..0a15680 100644 (file)
@@ -110,6 +110,8 @@ typedef struct ok_struct {
 static const BIO_METHOD methods_ok = {
     BIO_TYPE_CIPHER, "reliable",
     ok_write,
+    /* TODO: Convert to new style read function */
+    bread_conv,
     ok_read,
     NULL,                       /* ok_puts, */
     NULL,                       /* ok_gets, */
index 3b6a6ac..f840bcd 100644 (file)
@@ -13,7 +13,8 @@ struct bio_method_st {
     int type;
     const char *name;
     int (*bwrite) (BIO *, const char *, int);
-    int (*bread) (BIO *, char *, int);
+    int (*bread) (BIO *, char *, size_t, size_t *);
+    int (*bread_old) (BIO *, char *, int);
     int (*bputs) (BIO *, const char *);
     int (*bgets) (BIO *, char *, int);
     long (*ctrl) (BIO *, int, long, void *);
@@ -24,3 +25,7 @@ struct bio_method_st {
 
 void bio_free_ex_data(BIO *bio);
 void bio_cleanup(void);
+
+
+/* Old style to new style BIO_METHOD conversion functions */
+int bread_conv(BIO *bio, char *out, size_t outl, size_t *read);
index 9bc941b..b4b1e0a 100644 (file)
@@ -239,8 +239,16 @@ void BIO_clear_flags(BIO *b, int flags);
 
 typedef long (*BIO_callback_fn)(BIO *b, int oper, const char *argp, int argi,
                                 long argl, long ret);
+typedef long (*BIO_callback_fn_ex)(BIO *b, int oper, const char *argp,
+                                   size_t len, int argi,
+                                   long argl, int ret, size_t *processed,
+                                   long *lret);
 BIO_callback_fn BIO_get_callback(const BIO *b);
 void BIO_set_callback(BIO *b, BIO_callback_fn callback);
+
+BIO_callback_fn_ex BIO_get_callback_ex(const BIO *b);
+void BIO_set_callback_ex(BIO *b, BIO_callback_fn_ex callback);
+
 char *BIO_get_callback_arg(const BIO *b);
 void BIO_set_callback_arg(BIO *b, char *arg);
 
@@ -545,6 +553,7 @@ int BIO_get_shutdown(BIO *a);
 void BIO_vfree(BIO *a);
 int BIO_up_ref(BIO *a);
 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_puts(BIO *bp, const char *buf);
@@ -737,8 +746,11 @@ int (*BIO_meth_get_write(BIO_METHOD *biom)) (BIO *, const char *, int);
 int BIO_meth_set_write(BIO_METHOD *biom,
                        int (*write) (BIO *, const char *, int));
 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,
                       int (*read) (BIO *, char *, int));
+int BIO_meth_set_read_ex(BIO_METHOD *biom,
+                         int (*bread) (BIO *, char *, size_t, size_t *));
 int (*BIO_meth_get_puts(BIO_METHOD *biom)) (BIO *, const char *);
 int BIO_meth_set_puts(BIO_METHOD *biom,
                       int (*puts) (BIO *, const char *));
@@ -794,6 +806,7 @@ int ERR_load_BIO_strings(void);
 # define BIO_F_BIO_PARSE_HOSTSERV                         136
 # define BIO_F_BIO_PUTS                                   110
 # define BIO_F_BIO_READ                                   111
+# define BIO_F_BIO_READ_EX                                105
 # define BIO_F_BIO_SOCKET                                 140
 # define BIO_F_BIO_SOCKET_NBIO                            142
 # define BIO_F_BIO_SOCK_INFO                              141
index 3dd09cf..59a04a3 100644 (file)
@@ -17,7 +17,7 @@
 #include "ssl_locl.h"
 
 static int ssl_write(BIO *h, const char *buf, int num);
-static int ssl_read(BIO *h, char *buf, int size);
+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);
 static int ssl_new(BIO *h);
@@ -37,6 +37,7 @@ static const BIO_METHOD methods_sslp = {
     BIO_TYPE_SSL, "ssl",
     ssl_write,
     ssl_read,
+    NULL,
     ssl_puts,
     NULL,                       /* ssl_gets, */
     ssl_ctrl,
@@ -86,7 +87,7 @@ static int ssl_free(BIO *a)
     return 1;
 }
 
-static int ssl_read(BIO *b, char *out, int outl)
+static int ssl_read(BIO *b, char *out, size_t outl, size_t *read)
 {
     int ret = 1;
     BIO_SSL *sb;
@@ -101,6 +102,9 @@ static int ssl_read(BIO *b, char *out, int outl)
 
     BIO_clear_retry_flags(b);
 
+    if (outl > INT_MAX)
+        return -1;
+
     ret = SSL_read(ssl, out, outl);
 
     switch (SSL_get_error(ssl, ret)) {
@@ -154,7 +158,13 @@ static int ssl_read(BIO *b, char *out, int outl)
     }
 
     BIO_set_retry_reason(b, retry_reason);
-    return (ret);
+
+    if (ret < 0)
+        return ret;
+
+    *read = (size_t)ret;
+
+    return 1;
 }
 
 static int ssl_write(BIO *b, const char *out, int outl)
index 21d46d2..0b7917b 100644 (file)
@@ -4208,3 +4208,8 @@ OCSP_RESPID_set_by_key                  4158      1_1_0a  EXIST::FUNCTION:OCSP
 OCSP_RESPID_match                       4159   1_1_0a  EXIST::FUNCTION:OCSP
 ASN1_ITEM_lookup                        4160   1_1_1   EXIST::FUNCTION:
 ASN1_ITEM_get                           4161   1_1_1   EXIST::FUNCTION:
+BIO_read_ex                             4162   1_1_1   EXIST::FUNCTION:
+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: