← Commit list

7c34365cce

Viktor Szakats
Viktor Szakats
2026-06-08
SUCCESS Duration: 240s

Subject

urlapi: fix memleaks on error in `parse_hostname_login()`

Binary

No binary (build failed)

Architecture & Compiler Flags

Architecture: x86_64-linux-gnu Compiler: gcc (Ubuntu 11.4.0-1ubuntu1~22.04.3) 11.4.0

—

Build Log

(log yok)

Commit Diff GitHub →

lib/urlapi.c+16 -10
@@ -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;
}
tests/unit/unit1675.c+59 -0
@@ -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
}