From 243465fd556837402bff52b7bf3d59420b68a02e Mon Sep 17 00:00:00 2001 From: "Dr. David von Oheimb" Date: Fri, 1 Jul 2022 17:46:36 +0200 Subject: http_client.c: fix calculation of Content-Length in set1_content() Work around an inconsistency in the implementations of BIO_CTRL_INFO. Reviewed-by: Tomas Mraz Reviewed-by: Hugo Landau Reviewed-by: David von Oheimb (Merged from https://github.com/openssl/openssl/pull/18701) --- crypto/http/http_client.c | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) (limited to 'crypto') diff --git a/crypto/http/http_client.c b/crypto/http/http_client.c index 1a1a79ace5..b31fee8654 100644 --- a/crypto/http/http_client.c +++ b/crypto/http/http_client.c @@ -267,6 +267,7 @@ static int set1_content(OSSL_HTTP_REQ_CTX *rctx, const char *content_type, BIO *req) { long req_len; + FILE *fp = NULL; if (rctx == NULL || (req == NULL && content_type != NULL)) { ERR_raise(ERR_LIB_HTTP, ERR_R_PASSED_NULL_PARAMETER); @@ -290,14 +291,29 @@ static int set1_content(OSSL_HTTP_REQ_CTX *rctx, && BIO_printf(rctx->mem, "Content-Type: %s\r\n", content_type) <= 0) return 0; - /* streaming BIO may not support querying size */ - if (((req_len = BIO_ctrl(req, BIO_CTRL_INFO, 0, NULL)) <= 0 - || BIO_printf(rctx->mem, "Content-Length: %ld\r\n", req_len) > 0) - && BIO_up_ref(req)) { - rctx->req = req; - return 1; + /* + * BIO_CTRL_INFO yields the data length at least for memory BIOs, but for + * file-based BIOs it gives the current position, which is not what we need. + */ + if (BIO_get_fp(req, &fp) == 1) { + fseek(fp, 0, SEEK_END); + req_len = ftell(fp); + fseek(fp, 0, SEEK_SET); + } else { + req_len = BIO_ctrl(req, BIO_CTRL_INFO, 0, NULL); + /* + * Streaming BIOs likely will not support querying the size at all, + * and we assume we got a correct value if req_len > 0. + */ } - return 0; + if ((fp != NULL /* definitely correct req_len */ || req_len > 0) + && BIO_printf(rctx->mem, "Content-Length: %ld\r\n", req_len) < 0) + return 0; + + if (!BIO_up_ref(req)) + return 0; + rctx->req = req; + return 1; } int OSSL_HTTP_REQ_CTX_set1_req(OSSL_HTTP_REQ_CTX *rctx, const char *content_type, -- cgit v1.2.1