diff --git a/ext/include/opentelemetry/ext/http/common/url_parser.h b/ext/include/opentelemetry/ext/http/common/url_parser.h index 75f53ce943..bec9f06c0d 100644 --- a/ext/include/opentelemetry/ext/http/common/url_parser.h +++ b/ext/include/opentelemetry/ext/http/common/url_parser.h @@ -3,8 +3,9 @@ #pragma once -#include +#include #include +#include #include #include "opentelemetry/version.h" @@ -88,8 +89,11 @@ class UrlParser path_ = std::string("/"); // use default path if (is_port) { - port_ = static_cast( - std::stoi(std::string(url_.begin() + cpos, url_.begin() + url_.length()))); + std::string port_str( + url_.begin() + static_cast(cpos), + url_.begin() + static_cast(url_.length())); + + port_ = GetPort(port_str); } else { @@ -99,8 +103,9 @@ class UrlParser } if (is_port) { - port_ = - static_cast(std::stoi(std::string(url_.begin() + cpos, url_.begin() + pos))); + std::string port_str(url_.begin() + static_cast(cpos), + url_.begin() + static_cast(pos)); + port_ = GetPort(port_str); } else { @@ -164,6 +169,20 @@ class UrlParser return std::string::npos; } + + std::uint16_t GetPort(const std::string &s) + { + char *e = nullptr; + errno = 0; + auto port = std::strtol(s.c_str(), &e, 10); + if (e == s.c_str() || e != s.c_str() + s.size() || errno == ERANGE || port < 0 || port > 65535) + { + success_ = false; + return 0; + } + + return static_cast(port); + } }; class UrlDecoder diff --git a/ext/test/http/url_parser_test.cc b/ext/test/http/url_parser_test.cc index aceb43966a..4314735a6f 100644 --- a/ext/test/http/url_parser_test.cc +++ b/ext/test/http/url_parser_test.cc @@ -179,6 +179,41 @@ TEST(UrlParserTests, BasicTests) {"path", "/path1@bbb/path2"}, {"query", "q1=a1&q2=a2"}, {"success", "true"}}}, + {"https://https://example.com/some/path", + {{"host", "https"}, + {"port", "0"}, + {"scheme", "https"}, + {"path", "//example.com/some/path"}, + {"query", ""}, + {"success", "false"}}}, + {"https://example.com:-1/some/path", + {{"host", "example.com"}, + {"port", "0"}, + {"scheme", "https"}, + {"path", "/some/path"}, + {"query", ""}, + {"success", "false"}}}, + {"https://example.com:65536/some/path", + {{"host", "example.com"}, + {"port", "0"}, + {"scheme", "https"}, + {"path", "/some/path"}, + {"query", ""}, + {"success", "false"}}}, + {"https://example.com:80a/some/path", + {{"host", "example.com"}, + {"port", "0"}, + {"scheme", "https"}, + {"path", "/some/path"}, + {"query", ""}, + {"success", "false"}}}, + {"https://example.com:18446744073709551616/some/path", + {{"host", "example.com"}, + {"port", "0"}, + {"scheme", "https"}, + {"path", "/some/path"}, + {"query", ""}, + {"success", "false"}}}, }; for (auto &url_map : urls_map) {