urlapi: fix memleaks on error in `parse_hostname_login()`
No binary (build failed)
—
(log yok)
| @@ -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; | |
| } | |
| @@ -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 | |
| } | |