Преглед изворни кода

Reject trailing characters in URL port numbers (#2593)

parse_port checked only the error code of from_chars, which stops at
the first non-digit, so http://host:80abc was accepted as port 80, and
a redirect Location with such a port was followed. RFC 3986 defines
port as *DIGIT. Require the whole string to be consumed, as #2590 does
for quality values.
KBS пре 5 дана
родитељ
комит
10aadd57f7
2 измењених фајлова са 36 додато и 1 уклоњено
  1. 3 1
      httplib.h
  2. 33 0
      test/test.cc

+ 3 - 1
httplib.h

@@ -834,7 +834,9 @@ inline from_chars_result<double> 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;
 }

+ 33 - 0
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");