diff --git a/httplib.h b/httplib.h index 32e7880c..c8aa168b 100644 --- a/httplib.h +++ b/httplib.h @@ -834,7 +834,9 @@ inline from_chars_result from_chars(const char *first, const char *last, inline bool parse_port(const char *s, size_t len, int &port) { int val = 0; auto r = from_chars(s, s + len, val); - if (r.ec != std::errc{} || val < 1 || val > 65535) { return false; } + if (r.ec != std::errc{} || r.ptr != s + len || val < 1 || val > 65535) { + return false; + } port = val; return true; } diff --git a/test/test.cc b/test/test.cc index fbba9bd3..21952987 100644 --- a/test/test.cc +++ b/test/test.cc @@ -3754,6 +3754,34 @@ TEST(RedirectToDifferentPort, OverflowPortNumber) { EXPECT_FALSE(res); } +TEST(RedirectToDifferentPort, TrailingCharactersInPort) { + Server svr; + auto port = svr.bind_to_any_port(HOST); + svr.Get("/redir", [&](const Request & /*req*/, Response &res) { + // The server's own port followed by junk must not be followed + res.set_redirect("http://" + std::string(HOST) + ":" + + std::to_string(port) + "junk/target"); + }); + svr.Get("/target", [&](const Request & /*req*/, Response &res) { + res.set_content("target", "text/plain"); + }); + + auto thread = std::thread([&]() { svr.listen_after_bind(); }); + auto se = detail::scope_exit([&] { + svr.stop(); + thread.join(); + ASSERT_FALSE(svr.is_running()); + }); + + svr.wait_until_ready(); + + Client cli(HOST, port); + cli.set_follow_location(true); + + auto res = cli.Get("/redir"); + EXPECT_FALSE(res); +} + TEST(RedirectFromPageWithContent, Redirect) { Server svr; @@ -13848,6 +13876,11 @@ TEST(HostAndPortPropertiesTest, PortOutOfRange) { ASSERT_FALSE(cli.is_valid()); } +TEST(HostAndPortPropertiesTest, TrailingCharactersInPort) { + httplib::Client cli("http://www.google.com:80abc"); + ASSERT_FALSE(cli.is_valid()); +} + #ifdef CPPHTTPLIB_SSL_ENABLED TEST(HostAndPortPropertiesTest, SSL) { httplib::SSLClient cli("www.google.com");