diff --git a/src/ne_uri.c b/src/ne_uri.c index 68559f25..450ff226 100644 --- a/src/ne_uri.c +++ b/src/ne_uri.c @@ -94,6 +94,9 @@ /* any characters which should be path-escaped: */ #define URI_ESCAPE ((URI_GENDELIM & ~(FS)) | URI_SUBDELIM | OT | PC) +/* Maximum allowed port number. */ +#define MAX_PORT (65535) + static const unsigned short uri_chars[256] = { /* 0xXX x0 x2 x4 x6 x8 xA xC xE */ /* 0x */ OT, OT, OT, OT, OT, OT, OT, OT, OT, OT, OT, OT, OT, OT, OT, OT, @@ -220,23 +223,30 @@ int ne_uri_parse(const char *uri, ne_uri *parsed) parsed->host = ne_strndup(s, p - s); - if (p != pa && p + 1 != pa) { - p++; + /* Iff p and pa (=> path-abempty) differ, the optional port + * section is present and parsed here: */ + if (p != pa) { + unsigned int port = 0; - s = p; - /* => s = port */ + if (*p++ != ':') return -1; - while (p < pa) { - if (!(uri_lookup(*p) & URI_DIGIT)) - return -1; + /* => p = port */ - p++; - } + /* port = *DIGIT + * + * Note: port can be the empty string, in which case now: + * p == pa and port is parsed as 0, as desired. */ + while (p < pa && port <= MAX_PORT && (uri_lookup(*p) & URI_DIGIT) != 0) + port = 10*port + *p++-'0'; + + /* If p did not reach pa there was some non-digit present + * or the integer was too large, so fail. */ + if (p != pa || port > MAX_PORT) return -1; - parsed->port = atoi(s); + parsed->port = port; } - s = pa; + s = pa; /* Next, parse path-abempty */ } /* => s = path-abempty / path-absolute / path-rootless diff --git a/test/uri-tests.c b/test/uri-tests.c index 060c8952..e561f40d 100644 --- a/test/uri-tests.c +++ b/test/uri-tests.c @@ -384,6 +384,8 @@ static int failparse(void) "http://fish/[foo]/bar", "http://foo:80bar", "http://foo:80:80/bar", + "http://foo:8000000000000000000000000000000000000000000000000/bar", + "http://foo:65536/bar", NULL }; int n;