|
@@ -16,6 +16,10 @@
|
|
|
// under the License.
|
|
|
|
|
|
|
|
|
+#include <ctype.h> // isalnum
|
|
|
+
|
|
|
+#include <unordered_set>
|
|
|
+
|
|
|
#include "brpc/log.h"
|
|
|
#include "brpc/details/http_parser.h" // http_parser_parse_url
|
|
|
#include "brpc/uri.h" // URI
|
|
@@ -98,6 +102,21 @@ inline const char* SplitHostAndPort(const char* host_begin,
|
|
|
return host_end;
|
|
|
}
|
|
|
|
|
|
+// valid characters in URL
|
|
|
+// https://datatracker.ietf.org/doc/html/rfc3986#section-2.1
|
|
|
+// https://datatracker.ietf.org/doc/html/rfc3986#section-2.3
|
|
|
+// https://datatracker.ietf.org/doc/html/rfc3986#section-2.4
|
|
|
+// space is not allowed by rfc3986, but allowed by brpc
|
|
|
+static bool is_valid_char(char c) {
|
|
|
+ static const std::unordered_set<char> other_valid_char = {
|
|
|
+ ':', '/', '?', '#', '[', ']', '@', '!', '$', '&',
|
|
|
+ '\'', '(', ')', '*', '+', ',', ';', '=', '-', '.',
|
|
|
+ '_', '~', '%', ' '
|
|
|
+ };
|
|
|
+
|
|
|
+ return (isalnum(c) || other_valid_char.count(c));
|
|
|
+}
|
|
|
+
|
|
|
static bool is_all_spaces(const char* p) {
|
|
|
for (; *p == ' '; ++p) {}
|
|
|
return !*p;
|
|
@@ -159,7 +178,10 @@ int URI::SetHttpURL(const char* url) {
|
|
|
if (action == URI_PARSE_BREAK) {
|
|
|
break;
|
|
|
}
|
|
|
- if (*p == ':') {
|
|
|
+ if (!is_valid_char(*p)) {
|
|
|
+ _st.set_error(EINVAL, "invalid character in url");
|
|
|
+ return -1;
|
|
|
+ } else if (*p == ':') {
|
|
|
if (p[1] == '/' && p[2] == '/' && need_scheme) {
|
|
|
need_scheme = false;
|
|
|
_scheme.assign(start, p - start);
|