summaryrefslogtreecommitdiffstats
path: root/crypto/bio
diff options
context:
space:
mode:
authorRichard Levitte <levitte@openssl.org>2020-07-27 22:02:07 +0200
committerPauli <paul.dale@oracle.com>2020-08-01 11:51:20 +1000
commit1dbf4537738d86d8078b74c89e38b6ed0b2b1196 (patch)
tree43e414c0958f6dbd04050b1cc8deb34e39f3a74a /crypto/bio
parent3c033c5bfed214b02c0f041239d1cb8a4e27fd82 (diff)
DESERIALIZER: Make OSSL_DESERIALIZER_from_{bio,fp} use BIO_tell() / BIO_seek()
Depending on the BIO used, using BIO_reset() may lead to "interesting" results. For example, a BIO_f_buffer() on top of another BIO that handles BIO_reset() as a BIO_seek(bio, 0), the deserialization process may find itself with a file that's rewound more than expected. Therefore, OSSL_DESERIALIZER_from_{bio,fp}'s behaviour is changed to rely purely on BIO_tell() / BIO_seek(), and since BIO_s_mem() is used internally, it's changed to handle BIO_tell() and BIO_seek() better. This does currently mean that OSSL_DESERIALIZER can't be easily used with streams that don't support BIO_tell() / BIO_seek(). Fixes #12541 Reviewed-by: Paul Dale <paul.dale@oracle.com> (Merged from https://github.com/openssl/openssl/pull/12544)
Diffstat (limited to 'crypto/bio')
-rw-r--r--crypto/bio/bss_mem.c25
1 files changed, 22 insertions, 3 deletions
diff --git a/crypto/bio/bss_mem.c b/crypto/bio/bss_mem.c
index 4043043626..d9580e6d37 100644
--- a/crypto/bio/bss_mem.c
+++ b/crypto/bio/bss_mem.c
@@ -176,6 +176,7 @@ static int mem_buf_free(BIO *a)
/*
* Reallocate memory buffer if read pointer differs
+ * NOT FOR RDONLY
*/
static int mem_buf_sync(BIO *b)
{
@@ -247,12 +248,18 @@ static long mem_ctrl(BIO *b, int cmd, long num, void *ptr)
long ret = 1;
char **pptr;
BIO_BUF_MEM *bbm = (BIO_BUF_MEM *)b->ptr;
- BUF_MEM *bm;
+ BUF_MEM *bm, *bo; /* bio_mem, bio_other */
+ long off, remain;
- if (b->flags & BIO_FLAGS_MEM_RDONLY)
+ if (b->flags & BIO_FLAGS_MEM_RDONLY) {
bm = bbm->buf;
- else
+ bo = bbm->readp;
+ } else {
bm = bbm->readp;
+ bo = bbm->buf;
+ }
+ off = bm->data - bo->data;
+ remain = bm->length;
switch (cmd) {
case BIO_CTRL_RESET:
@@ -270,6 +277,18 @@ static long mem_ctrl(BIO *b, int cmd, long num, void *ptr)
}
}
break;
+ case BIO_C_FILE_SEEK:
+ if (num < 0 || num > off + remain)
+ return -1; /* Can't see outside of the current buffer */
+
+ bm->data = bo->data + num;
+ bm->length = bo->length - num;
+ bm->max = bo->max - num;
+ off = num;
+ /* FALLTHRU */
+ case BIO_C_FILE_TELL:
+ ret = off;
+ break;
case BIO_CTRL_EOF:
ret = (long)(bm->length == 0);
break;