diff options
author | Josh Brobst <josh@brob.st> | 2022-12-31 14:41:44 -0500 |
---|---|---|
committer | Daniel Stenberg <daniel@haxx.se> | 2023-01-02 00:06:15 +0100 |
commit | aa6e7a1f45d3d82ceaf58534bcc5ac409abbd0a0 (patch) | |
tree | 82d775741cfd423cfe63d31ecebc0e8775b8e517 /lib | |
parent | fc9f22b46ece93ce60f73fa2e767fef92e48a79f (diff) | |
download | curl-aa6e7a1f45d3d82ceaf58534bcc5ac409abbd0a0.tar.gz |
http: decode transfer encoding first
The unencoding stack is added to as Transfer-Encoding and
Content-Encoding fields are encountered with no distinction between the
two, meaning the stack will be incorrect if, e.g., the message has both
fields and a non-chunked Transfer-Encoding comes first. This commit
fixes this by ordering the stack with transfer encodings first.
Reviewed-by: Patrick Monnerat
Closes #10187
Diffstat (limited to 'lib')
-rw-r--r-- | lib/content_encoding.c | 39 | ||||
-rw-r--r-- | lib/content_encoding.h | 5 |
2 files changed, 31 insertions, 13 deletions
diff --git a/lib/content_encoding.c b/lib/content_encoding.c index bfc13e254..1a90e40ea 100644 --- a/lib/content_encoding.c +++ b/lib/content_encoding.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2023, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -977,7 +977,8 @@ static const struct content_encoding error_encoding = { static struct contenc_writer * new_unencoding_writer(struct Curl_easy *data, const struct content_encoding *handler, - struct contenc_writer *downstream) + struct contenc_writer *downstream, + int order) { struct contenc_writer *writer; @@ -987,6 +988,7 @@ new_unencoding_writer(struct Curl_easy *data, if(writer) { writer->handler = handler; writer->downstream = downstream; + writer->order = order; if(handler->init_writer(data, writer)) { free(writer); writer = NULL; @@ -1042,10 +1044,11 @@ static const struct content_encoding *find_encoding(const char *name, /* Set-up the unencoding stack from the Content-Encoding header value. * See RFC 7231 section 3.1.2.2. */ CURLcode Curl_build_unencoding_stack(struct Curl_easy *data, - const char *enclist, int maybechunked) + const char *enclist, int is_transfer) { struct SingleRequest *k = &data->req; int counter = 0; + unsigned int order = is_transfer? 2: 1; do { const char *name; @@ -1062,7 +1065,7 @@ CURLcode Curl_build_unencoding_stack(struct Curl_easy *data, namelen = enclist - name + 1; /* Special case: chunked encoding is handled at the reader level. */ - if(maybechunked && namelen == 7 && strncasecompare(name, "chunked", 7)) { + if(is_transfer && namelen == 7 && strncasecompare(name, "chunked", 7)) { k->chunk = TRUE; /* chunks coming our way. */ Curl_httpchunk_init(data); /* init our chunky engine. */ } @@ -1071,7 +1074,8 @@ CURLcode Curl_build_unencoding_stack(struct Curl_easy *data, struct contenc_writer *writer; if(!k->writer_stack) { - k->writer_stack = new_unencoding_writer(data, &client_encoding, NULL); + k->writer_stack = new_unencoding_writer(data, &client_encoding, + NULL, 0); if(!k->writer_stack) return CURLE_OUT_OF_MEMORY; @@ -1086,10 +1090,23 @@ CURLcode Curl_build_unencoding_stack(struct Curl_easy *data, return CURLE_BAD_CONTENT_ENCODING; } /* Stack the unencoding stage. */ - writer = new_unencoding_writer(data, encoding, k->writer_stack); - if(!writer) - return CURLE_OUT_OF_MEMORY; - k->writer_stack = writer; + if(order >= k->writer_stack->order) { + writer = new_unencoding_writer(data, encoding, + k->writer_stack, order); + if(!writer) + return CURLE_OUT_OF_MEMORY; + k->writer_stack = writer; + } + else { + struct contenc_writer *w = k->writer_stack; + while(w->downstream && order < w->downstream->order) + w = w->downstream; + writer = new_unencoding_writer(data, encoding, + w->downstream, order); + if(!writer) + return CURLE_OUT_OF_MEMORY; + w->downstream = writer; + } } } while(*enclist); @@ -1099,11 +1116,11 @@ CURLcode Curl_build_unencoding_stack(struct Curl_easy *data, #else /* Stubs for builds without HTTP. */ CURLcode Curl_build_unencoding_stack(struct Curl_easy *data, - const char *enclist, int maybechunked) + const char *enclist, int is_transfer) { (void) data; (void) enclist; - (void) maybechunked; + (void) is_transfer; return CURLE_NOT_BUILT_IN; } diff --git a/lib/content_encoding.h b/lib/content_encoding.h index 3c278cf72..4433b48f3 100644 --- a/lib/content_encoding.h +++ b/lib/content_encoding.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2023, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -28,6 +28,7 @@ struct contenc_writer { const struct content_encoding *handler; /* Encoding handler. */ struct contenc_writer *downstream; /* Downstream writer. */ + unsigned int order; /* Ordering within writer stack. */ }; /* Content encoding writer. */ @@ -46,7 +47,7 @@ struct content_encoding { CURLcode Curl_build_unencoding_stack(struct Curl_easy *data, - const char *enclist, int maybechunked); + const char *enclist, int is_transfer); CURLcode Curl_unencode_write(struct Curl_easy *data, struct contenc_writer *writer, const char *buf, size_t nbytes); |