diff options
author | Daniel Stenberg <daniel@haxx.se> | 2023-05-18 00:31:17 +0200 |
---|---|---|
committer | Daniel Stenberg <daniel@haxx.se> | 2023-05-18 00:31:17 +0200 |
commit | a2815af63a3ab1bfcdff4acc4269c0e7d05e96e8 (patch) | |
tree | 9416c77de3424c5bdfa9351b93c3392a6003dffa /lib/urlapi.c | |
parent | a9f8fe28481fef7c28d85b4a12a3a35521408eaf (diff) | |
download | curl-bagder/url-digits-hostname.tar.gz |
urlapi: allow numerical parts in the host namebagder/url-digits-hostname
It can only be an IPv4 address if the last part is all digits, otherwise
it is a host name.
Extended test 1560 accordingly.
Reported-by: Pavel Kalyugin
Fixes #11129
Diffstat (limited to 'lib/urlapi.c')
-rw-r--r-- | lib/urlapi.c | 57 |
1 files changed, 56 insertions, 1 deletions
diff --git a/lib/urlapi.c b/lib/urlapi.c index 83e4ceda3..4c2d01b1b 100644 --- a/lib/urlapi.c +++ b/lib/urlapi.c @@ -34,6 +34,7 @@ #include "inet_ntop.h" #include "strdup.h" #include "idn.h" +#include "curl_memrchr.h" /* The last 3 #include files should be in this order */ #include "curl_printf.h" @@ -656,6 +657,54 @@ static CURLUcode hostname_check(struct Curl_URL *u, char *hostname, #define HOST_IPV4 2 #define HOST_IPV6 3 +static bool finetld(const char *c, size_t len) +{ + const char *ldot; + const char *end = &c[len]; + int i; + + for(i = 0; i < 2; i++) { + ldot = memrchr(c, '.', len); + if(!ldot) + ldot = c; + else { + ldot++; + if(!*ldot) { + /* this is a trailing dot, we rather want the one before */ + len--; + end = &c[len]; + /* now loop */ + continue; + } + } + break; + } + + /* this is the last part of the host name, if not only digits it is a + host name, otherwise a bad IPv4 address */ + if(*ldot == '0') { + /* hex or octal */ + + ldot++; + if(Curl_raw_tolower(*ldot) == 'x') + /* hex */ + ldot++; + else { + /* octal */ + while(*ldot && ISOCTAL(*ldot)) + ldot++; + } + while(*ldot && ISXDIGIT(*ldot)) + ldot++; + } + else { + /* decimal */ + while(*ldot && ISDIGIT(*ldot)) + ldot++; + } + return (ldot != end) ? TRUE : FALSE; +} + static int ipv4_normalize(struct dynbuf *host) { bool done = FALSE; @@ -667,12 +716,15 @@ static int ipv4_normalize(struct dynbuf *host) if(*c == '[') return HOST_IPV6; + if(finetld(c, Curl_dyn_len(host))) + return HOST_NAME; + while(!done) { char *endp; unsigned long l; if(!ISDIGIT(*c)) /* most importantly this doesn't allow a leading plus or minus */ - return n ? HOST_BAD : HOST_NAME; + return HOST_BAD; l = strtoul(c, &endp, 0); parts[n] = l; @@ -793,6 +845,9 @@ static CURLUcode parse_authority(struct Curl_URL *u, if(result) goto out; + if(!Curl_dyn_len(host)) + return CURLUE_NO_HOST; + switch(ipv4_normalize(host)) { case HOST_IPV4: break; |