From dd7ed38c90f05547d698a7984e71c32dfe5fff2a Mon Sep 17 00:00:00 2001 From: Ali MJ Al-Nasrawy Date: Mon, 9 Mar 2020 21:15:09 +0300 Subject: [PATCH] ChunkedDecodingStreamFilter: be aware of segments See GH-1582 Report the correct bytesProcessed_ taking into account getDelagate()->getBytesProcessed() Also, rewrite to avoid using goto or modifying for-loop variables. --- src/ChunkedDecodingStreamFilter.cc | 43 +++++++++++++++++------------- 1 file changed, 25 insertions(+), 18 deletions(-) diff --git a/src/ChunkedDecodingStreamFilter.cc b/src/ChunkedDecodingStreamFilter.cc index 4e3a0e59..f619f380 100644 --- a/src/ChunkedDecodingStreamFilter.cc +++ b/src/ChunkedDecodingStreamFilter.cc @@ -84,10 +84,31 @@ ChunkedDecodingStreamFilter::transform(const std::shared_ptr& out, const unsigned char* inbuf, size_t inlen) { ssize_t outlen = 0; - size_t i; bytesProcessed_ = 0; - for (i = 0; i < inlen; ++i) { - unsigned char c = inbuf[i]; + while (bytesProcessed_ < inlen) { + if (state_ == CHUNKS_COMPLETE) { + break; + } + if (state_ == CHUNK) { + int64_t readlen = std::min(chunkRemaining_, + static_cast(inlen - bytesProcessed_)); + outlen += getDelegate()->transform(out, segment, inbuf + bytesProcessed_, + readlen); + int64_t processedlen = getDelegate()->getBytesProcessed(); + bytesProcessed_ += processedlen; + chunkRemaining_ -= processedlen; + if (chunkRemaining_ == 0) { + state_ = PREV_CHUNK_CR; + } + if (processedlen < readlen) { + // segment download finished + break; + } + continue; + } + // The following states consume single char + unsigned char c = inbuf[bytesProcessed_]; + bytesProcessed_++; switch (state_) { case PREV_CHUNK_SIZE: if (util::isHexDigit(c)) { @@ -136,17 +157,6 @@ ChunkedDecodingStreamFilter::transform(const std::shared_ptr& out, "missing LF at the end of chunk size"); } break; - case CHUNK: { - int64_t readlen = - std::min(chunkRemaining_, static_cast(inlen - i)); - outlen += getDelegate()->transform(out, segment, inbuf + i, readlen); - chunkRemaining_ -= readlen; - i += readlen - 1; - if (chunkRemaining_ == 0) { - state_ = PREV_CHUNK_CR; - } - break; - } case PREV_CHUNK_CR: if (c == '\r') { state_ = PREV_CHUNK_LF; @@ -203,15 +213,12 @@ ChunkedDecodingStreamFilter::transform(const std::shared_ptr& out, "missing LF at the end of chunks"); } break; - case CHUNKS_COMPLETE: - goto fin; default: // unreachable assert(0); } } -fin: - bytesProcessed_ += i; + return outlen; }