diff --git a/lib/urlapi.c b/lib/urlapi.c index 8151da9591..1799625ffd 100644 --- a/lib/urlapi.c +++ b/lib/urlapi.c @@ -253,12 +253,18 @@ CURLUcode Curl_junkscan(const char *url, size_t *urllen, bool allowspace) * Parse the login details (username, password and options) from the URL and * strip them out of the hostname * + * @unittest 1675 */ -static CURLUcode parse_hostname_login(struct Curl_URL *u, - const char *login, - size_t len, - unsigned int flags, - size_t *offset) /* to the hostname */ +UNITTEST CURLUcode parse_hostname_login(struct Curl_URL *u, + const char *login, + size_t len, + unsigned int flags, + size_t *hostname_offset); +UNITTEST CURLUcode parse_hostname_login(struct Curl_URL *u, + const char *login, + size_t len, + unsigned int flags, + size_t *hostname_offset) { CURLUcode ures = CURLUE_OK; CURLcode result; @@ -278,7 +284,7 @@ static CURLUcode parse_hostname_login(struct Curl_URL *u, DEBUGASSERT(login); - *offset = 0; + *hostname_offset = 0; ptr = memchr(login, '@', len); if(!ptr) goto out; @@ -326,7 +332,7 @@ static CURLUcode parse_hostname_login(struct Curl_URL *u, } /* the hostname starts at this offset */ - *offset = ptr - login; + *hostname_offset = ptr - login; return CURLUE_OK; out: @@ -334,9 +340,9 @@ out: curlx_free(userp); curlx_free(passwdp); curlx_free(optionsp); - u->user = NULL; - u->password = NULL; - u->options = NULL; + curlx_safefree(u->user); + curlx_safefree(u->password); + curlx_safefree(u->options); return ures; } diff --git a/tests/unit/unit1675.c b/tests/unit/unit1675.c index ad5e92a25e..f7a965e38a 100644 --- a/tests/unit/unit1675.c +++ b/tests/unit/unit1675.c @@ -383,5 +383,64 @@ loop_end: } #endif /* !CURL_DISABLE_HTTP */ + /* Test parse_hostname_login */ + { + struct Curl_URL u; + int fails = 0; + unsigned int i; + struct test { + CURLUcode uc; + const char *in; + const char *scheme; + unsigned int flags; + const char *user; + const char *password; + const char *options; + size_t offset; + }; + const struct test tests[] = { + { CURLUE_OK, "foo:bar@host", NULL, 0, "foo", "bar", "o", 8 }, + { CURLUE_OK, "foo:bar;abc@host", "imap", 0, "foo", "bar", "abc", 12 }, + { CURLUE_OK, "foo:bar;abc@host", NULL, 0, "foo", "bar;abc", "o", 12 }, + { CURLUE_USER_NOT_ALLOWED, "foo:bar@host", NULL, CURLU_DISALLOW_USER, + NULL, NULL, NULL, 0 }, + { CURLUE_OK, "host", NULL, 0, NULL, NULL, NULL, 0 }, + }; + + for(i = 0; i < CURL_ARRAYSIZE(tests); i++) { + CURLUcode uc; + size_t offset = 0; + memset(&u, 0, sizeof(u)); + u.scheme = CURL_UNCONST(tests[i].scheme); + u.user = curlx_strdup("u"); + u.password = curlx_strdup("p"); + u.options = curlx_strdup("o"); + uc = parse_hostname_login(&u, tests[i].in, strlen(tests[i].in), + tests[i].flags, &offset); + if(uc != tests[i].uc || + !!u.user != !!tests[i].user || + (u.user && tests[i].user && + strcmp(u.user, tests[i].user)) || + !!u.password != !!tests[i].password || + (u.password && tests[i].password && + strcmp(u.password, tests[i].password)) || + !!u.options != !!tests[i].options || + (u.options && tests[i].options && + strcmp(u.options, tests[i].options)) || + offset != tests[i].offset) { + curl_mfprintf(stderr, "%d: parse_hostname_login('%s') host failed:" + " expected '%d/%s/%s/%s/%zu', got '%d/%s/%s/%s/%zu'\n", + i, tests[i].in, (int)tests[i].uc, tests[i].user, + tests[i].password, tests[i].options, tests[i].offset, + (int)uc, u.user, u.password, u.options, offset); + fails++; + } + curlx_safefree(u.user); + curlx_safefree(u.password); + curlx_safefree(u.options); + } + abort_if(fails, "parse_hostname_login tests failed"); + } + UNITTEST_END_SIMPLE }