Mercurial > hg > orthanc
diff OrthancFramework/Sources/HttpClient.cpp @ 4151:8c559dd5034b
Fix possible crash in HttpClient if sending multipart body (can occur in STOW-RS)
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Wed, 19 Aug 2020 11:59:02 +0200 |
parents | bf7b9edf6b81 |
children | db38b2ad4c4a |
line wrap: on
line diff
--- a/OrthancFramework/Sources/HttpClient.cpp Wed Aug 19 11:18:55 2020 +0200 +++ b/OrthancFramework/Sources/HttpClient.cpp Wed Aug 19 11:59:02 2020 +0200 @@ -197,8 +197,8 @@ { private: HttpClient::IRequestBody* body_; - std::string sourceBuffer_; - size_t sourceBufferTransmittedSize_; + std::string pending_; + size_t pendingPos_; size_t CallbackInternal(char* curlBuffer, size_t curlBufferSize) @@ -213,65 +213,63 @@ throw OrthancException(ErrorCode_InternalError); } - // Read chunks from the body stream so as to fill the target buffer - size_t curlBufferFilledSize = 0; - size_t sourceRemainingSize = sourceBuffer_.size() - sourceBufferTransmittedSize_; - bool hasMore = true; - - while (sourceRemainingSize < curlBufferSize && hasMore) + if (pendingPos_ + curlBufferSize <= pending_.size()) + { + assert(sizeof(char) == 1); + memcpy(curlBuffer, &pending_[pendingPos_], curlBufferSize); + pendingPos_ += curlBufferSize; + return curlBufferSize; + } + else { - if (sourceRemainingSize > 0) + ChunkedBuffer buffer; + buffer.SetPendingBufferSize(curlBufferSize); + + if (pendingPos_ < pending_.size()) { - // transmit the end of current source buffer - memcpy(curlBuffer + curlBufferFilledSize, - sourceBuffer_.data() + sourceBufferTransmittedSize_, sourceRemainingSize); - - curlBufferFilledSize += sourceRemainingSize; + buffer.AddChunk(&pending_[pendingPos_], pending_.size() - pendingPos_); + } + + // Read chunks from the body stream so as to fill the target buffer + std::string chunk; + + while (buffer.GetNumBytes() < curlBufferSize && + body_->ReadNextChunk(chunk)) + { + buffer.AddChunk(chunk); } - // start filling a new source buffer - sourceBufferTransmittedSize_ = 0; - sourceBuffer_.clear(); - - hasMore = body_->ReadNextChunk(sourceBuffer_); - - sourceRemainingSize = sourceBuffer_.size(); - } + buffer.Flatten(pending_); + pendingPos_ = std::min(pending_.size(), curlBufferSize); - if (sourceRemainingSize > 0 && - curlBufferSize > curlBufferFilledSize) - { - size_t s = std::min(sourceRemainingSize, curlBufferSize - curlBufferFilledSize); + if (pendingPos_ != 0) + { + memcpy(curlBuffer, pending_.c_str(), pendingPos_); + } - memcpy(curlBuffer + curlBufferFilledSize, - sourceBuffer_.data() + sourceBufferTransmittedSize_, s); - - sourceBufferTransmittedSize_ += s; - curlBufferFilledSize += s; + return pendingPos_; } - - return curlBufferFilledSize; } public: CurlRequestBody() : body_(NULL), - sourceBufferTransmittedSize_(0) + pendingPos_(0) { } void SetBody(HttpClient::IRequestBody& body) { body_ = &body; - sourceBufferTransmittedSize_ = 0; - sourceBuffer_.clear(); + pending_.clear(); + pendingPos_ = 0; } void Clear() { body_ = NULL; - sourceBufferTransmittedSize_ = 0; - sourceBuffer_.clear(); + pending_.clear(); + pendingPos_ = 0; } bool IsValid() const