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
This commit is contained in:
davidalo 2023-12-07 20:28:41 +01:00 committed by GitHub
parent f14accb7b6
commit e426a38c3e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 26 additions and 2 deletions

View file

@ -1989,8 +1989,12 @@ void read_file(const std::string &path, std::string &out);
std::string trim_copy(const std::string &s); std::string trim_copy(const std::string &s);
void split(const char *b, const char *e, char d, void split(const char *b, const char *e, char d,
std::function<void(const char *, const char *)> fn);
void split(const char *b, const char *e, char d, size_t m,
std::function<void(const char *, const char *)> fn); std::function<void(const char *, const char *)> fn);
bool process_client_socket(socket_t sock, time_t read_timeout_sec, bool process_client_socket(socket_t sock, time_t read_timeout_sec,
time_t read_timeout_usec, time_t write_timeout_sec, time_t read_timeout_usec, time_t write_timeout_sec,
time_t write_timeout_usec, 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, inline void split(const char *b, const char *e, char d,
std::function<void(const char *, const char *)> fn) { std::function<void(const char *, const char *)> fn) {
return split(b, e, d, std::numeric_limits<size_t>::max(), fn);
}
inline void split(const char *b, const char *e, char d, size_t m,
std::function<void(const char *, const char *)> fn) {
size_t i = 0; size_t i = 0;
size_t beg = 0; size_t beg = 0;
size_t count = 1;
while (e ? (b + i < e) : (b[i] != '\0')) { 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); auto r = trim(b, e, beg, i);
if (r.first < r.second) { fn(&b[r.first], &b[r.second]); } if (r.first < r.second) { fn(&b[r.first], &b[r.second]); }
beg = i + 1; beg = i + 1;
count++;
} }
i++; i++;
} }
@ -5804,7 +5815,7 @@ inline bool Server::parse_request_line(const char *s, Request &req) const {
size_t count = 0; 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) { [&](const char *b, const char *e) {
switch (count) { switch (count) {
case 0: case 0:

View file

@ -1847,6 +1847,11 @@ protected:
return true; 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", .Get("/with-range",
[&](const Request & /*req*/, Response &res) { [&](const Request & /*req*/, Response &res) {
res.set_content("abcdefg", "text/plain"); res.set_content("abcdefg", "text/plain");
@ -3352,6 +3357,14 @@ TEST_F(ServerTest, GetStreamedChunkedWithGzip2) {
EXPECT_EQ(std::string("123456789"), res->body); 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) { TEST(GzipDecompressor, ChunkedDecompression) {
std::string data; std::string data;
for (size_t i = 0; i < 32 * 1024; ++i) { for (size_t i = 0; i < 32 * 1024; ++i) {