From e426a38c3e9b1ae8610fb023ba8104cb390d8520 Mon Sep 17 00:00:00 2001 From: davidalo Date: Thu, 7 Dec 2023 20:28:41 +0100 Subject: [PATCH] Fix: Query parameter including query delimiter ('?') not being parsed properly (#1713) * Fix: Query parameter including query delimiter ('?') not being parsed properly * Add details::split function with and without m argument to allow split parameters with/without counter * Revert changes in SplitTest.ParseQueryString --- httplib.h | 15 +++++++++++++-- test/test.cc | 13 +++++++++++++ 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/httplib.h b/httplib.h index 2540a7e..30e512d 100644 --- a/httplib.h +++ b/httplib.h @@ -1989,8 +1989,12 @@ void read_file(const std::string &path, std::string &out); std::string trim_copy(const std::string &s); void split(const char *b, const char *e, char d, + std::function fn); + +void split(const char *b, const char *e, char d, size_t m, std::function fn); + bool process_client_socket(socket_t sock, time_t read_timeout_sec, time_t read_timeout_usec, time_t write_timeout_sec, time_t write_timeout_usec, @@ -2473,14 +2477,21 @@ inline std::string trim_double_quotes_copy(const std::string &s) { inline void split(const char *b, const char *e, char d, std::function fn) { + return split(b, e, d, std::numeric_limits::max(), fn); +} + +inline void split(const char *b, const char *e, char d, size_t m, + std::function fn) { size_t i = 0; size_t beg = 0; + size_t count = 1; while (e ? (b + i < e) : (b[i] != '\0')) { - if (b[i] == d) { + if (b[i] == d && count < m) { auto r = trim(b, e, beg, i); if (r.first < r.second) { fn(&b[r.first], &b[r.second]); } beg = i + 1; + count++; } i++; } @@ -5804,7 +5815,7 @@ inline bool Server::parse_request_line(const char *s, Request &req) const { size_t count = 0; - detail::split(req.target.data(), req.target.data() + req.target.size(), '?', + detail::split(req.target.data(), req.target.data() + req.target.size(), '?', 2, [&](const char *b, const char *e) { switch (count) { case 0: diff --git a/test/test.cc b/test/test.cc index 4890a3a..8af6355 100644 --- a/test/test.cc +++ b/test/test.cc @@ -1847,6 +1847,11 @@ protected: return true; }); }) + .Get("/regex-with-delimiter", + [&](const Request & req, Response &res) { + ASSERT_TRUE(req.has_param("key")); + EXPECT_EQ("^(?.*(value))", req.get_param_value("key")); + }) .Get("/with-range", [&](const Request & /*req*/, Response &res) { res.set_content("abcdefg", "text/plain"); @@ -3352,6 +3357,14 @@ TEST_F(ServerTest, GetStreamedChunkedWithGzip2) { EXPECT_EQ(std::string("123456789"), res->body); } + +TEST_F(ServerTest, SplitDelimiterInPathRegex) { + auto res = cli_.Get("/regex-with-delimiter?key=^(?.*(value))"); + ASSERT_TRUE(res); + EXPECT_EQ(200, res->status); +} + + TEST(GzipDecompressor, ChunkedDecompression) { std::string data; for (size_t i = 0; i < 32 * 1024; ++i) {