diff options
Diffstat (limited to 'crypto/http/http_client.c')
-rw-r--r-- | crypto/http/http_client.c | 30 |
1 files changed, 23 insertions, 7 deletions
diff --git a/crypto/http/http_client.c b/crypto/http/http_client.c index 9f4555280c..08e726013c 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, |