From 889041f05f0c4351f811f2ab0c0c3d92116316d7 Mon Sep 17 00:00:00 2001 From: Scott Graham Date: Tue, 17 Apr 2018 22:02:24 -0700 Subject: [PATCH] Don't fail chunked read if buffer not yet filled --- httplib.h | 6 ++---- test/test.cc | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/httplib.h b/httplib.h index b5cc85d..c7a5efc 100644 --- a/httplib.h +++ b/httplib.h @@ -817,10 +817,8 @@ bool read_content_chunked(Stream& strm, std::string& out) auto chunk_len = std::stoi(reader.ptr(), 0, 16); while (chunk_len > 0){ - std::string chunk(chunk_len, 0); - - auto n = strm.read(&chunk[0], chunk_len); - if (n <= 0) { + std::string chunk; + if (!read_content_with_length(strm, chunk, chunk_len, nullptr)) { return false; } diff --git a/test/test.cc b/test/test.cc index 19151e9..88a0202 100644 --- a/test/test.cc +++ b/test/test.cc @@ -295,6 +295,10 @@ protected: .post("/chunked", [&](const Request& req, Response& /*res*/) { EXPECT_EQ(req.body, "dechunked post body"); }) + .post("/largechunked", [&](const Request& req, Response& /*res*/) { + std::string expected(6 * 30 * 1024u, 'a'); + EXPECT_EQ(req.body, expected); + }) .post("/multipart", [&](const Request& req, Response& /*res*/) { EXPECT_EQ(5u, req.files.size()); ASSERT_TRUE(!req.has_file("???")); @@ -690,6 +694,37 @@ TEST_F(ServerTest, CaseInsensitiveTransferEncoding) EXPECT_EQ(200, res->status); } +TEST_F(ServerTest, LargeChunkedPost) { + Request req; + req.method = "POST"; + req.path = "/largechunked"; + + std::string host_and_port; + host_and_port += HOST; + host_and_port += ":"; + host_and_port += std::to_string(PORT); + + req.headers.emplace("Host", host_and_port.c_str()); + req.headers.emplace("Accept", "*/*"); + req.headers.emplace("User-Agent", "cpp-httplib/0.1"); + req.headers.emplace("Content-Type", "text/plain"); + req.headers.emplace("Content-Length", "0"); + req.headers.emplace("Transfer-Encoding", "chunked"); + + std::string long_string(30 * 1024u, 'a'); + std::string chunk = "7800\r\n" + long_string + "\r\n"; + + // Attempt to make a large enough post to exceed OS buffers, to test that + // the server handles short reads if the full chunk data isn't available. + req.body = chunk + chunk + chunk + chunk + chunk + chunk + "0\r\n\r\n"; + + auto res = std::make_shared(); + auto ret = cli_.send(req, *res); + + ASSERT_TRUE(ret); + EXPECT_EQ(200, res->status); +} + TEST_F(ServerTest, GetMethodRemoteAddr) { auto res = cli_.get("/remote_addr");