From 8f8035173d7c699bdc34e8376a4977aa75d6a745 Mon Sep 17 00:00:00 2001 From: Daniel Ottiger Date: Mon, 11 May 2020 11:42:04 +0200 Subject: [PATCH 1/3] add missing 'done' in write_request --- httplib.h | 5 ++++- test/test.cc | 11 +++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/httplib.h b/httplib.h index 84c8c16d92..8f8c4b2f37 100644 --- a/httplib.h +++ b/httplib.h @@ -4105,16 +4105,19 @@ inline bool Client::write_request(Stream &strm, const Request &req, if (req.content_provider) { size_t offset = 0; size_t end_offset = req.content_length; + ssize_t written_length = 0; DataSink data_sink; data_sink.write = [&](const char *d, size_t l) { - auto written_length = strm.write(d, l); + written_length = strm.write(d, l); offset += static_cast(written_length); }; data_sink.is_writable = [&](void) { return strm.is_writable(); }; + data_sink.done = [&](void) { written_length = -1; }; while (offset < end_offset) { req.content_provider(offset, end_offset - offset, data_sink); + if (written_length < 0) { return false; } } } } else { diff --git a/test/test.cc b/test/test.cc index f5ad332b7c..c4a23e5ee2 100644 --- a/test/test.cc +++ b/test/test.cc @@ -1928,6 +1928,17 @@ TEST_F(ServerTest, PutWithContentProvider) { EXPECT_EQ("PUT", res->body); } +TEST_F(ServerTest, PostWithContentProviderAbort) { + auto res = cli_.Post( + "/post", 42, + [](size_t /*offset*/, size_t /*length*/, httplib::DataSink &sink) { + sink.done(); + }, + "text/plain"); + + ASSERT_TRUE(res == nullptr); +} + #ifdef CPPHTTPLIB_ZLIB_SUPPORT TEST_F(ServerTest, PutWithContentProviderWithGzip) { cli_.set_compress(true); From ce1d05655765af838fa9490ed09d9deb679f16e8 Mon Sep 17 00:00:00 2001 From: Daniel Ottiger Date: Mon, 11 May 2020 19:27:06 +0200 Subject: [PATCH 2/3] add done as well if CPPHTTPLIB_ZLIB_SUPPORT is enabled --- httplib.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/httplib.h b/httplib.h index 8f8c4b2f37..cdb565f645 100644 --- a/httplib.h +++ b/httplib.h @@ -4142,6 +4142,7 @@ inline std::shared_ptr Client::send_with_content_provider( if (compress_) { if (content_provider) { size_t offset = 0; + ssize_t written_length = 0; DataSink data_sink; data_sink.write = [&](const char *data, size_t data_len) { @@ -4149,9 +4150,11 @@ inline std::shared_ptr Client::send_with_content_provider( offset += data_len; }; data_sink.is_writable = [&](void) { return true; }; + data_sink.done = [&](void) { written_length = -1; }; while (offset < content_length) { content_provider(offset, content_length - offset, data_sink); + if (written_length < 0) { return nullptr; } } } else { req.body = body; From 28c07a10e9115dd5e84a266e8380747a6b46af2a Mon Sep 17 00:00:00 2001 From: Daniel Ottiger Date: Mon, 11 May 2020 19:34:46 +0200 Subject: [PATCH 3/3] Fixed another potential infinite loop --- httplib.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/httplib.h b/httplib.h index cdb565f645..47b0b76a0f 100644 --- a/httplib.h +++ b/httplib.h @@ -4112,7 +4112,9 @@ inline bool Client::write_request(Stream &strm, const Request &req, written_length = strm.write(d, l); offset += static_cast(written_length); }; - data_sink.is_writable = [&](void) { return strm.is_writable(); }; + data_sink.is_writable = [&](void) { + return strm.is_writable() && written_length >= 0; + }; data_sink.done = [&](void) { written_length = -1; }; while (offset < end_offset) {