url: make parse_login_details use memdup0

Also make the user and password arguments mandatory, since all code
paths in libcurl used them anyway.

Adapted unit test case 1620 to the new rules.

Closes #13584
This commit is contained in:
Daniel Stenberg 2024-05-10 15:32:57 +02:00
parent fa9a564942
commit 0e37b42dc9
No known key found for this signature in database
GPG Key ID: 5CC908FDB71E12C2
2 changed files with 42 additions and 61 deletions

View File

@ -2568,14 +2568,15 @@ out:
*
* Parameters:
*
* login [in] - The login string.
* len [in] - The length of the login string.
* userp [in/out] - The address where a pointer to newly allocated memory
* login [in] - login string.
* len [in] - length of the login string.
* userp [in/out] - address where a pointer to newly allocated memory
* holding the user will be stored upon completion.
* passwdp [in/out] - The address where a pointer to newly allocated memory
* passwdp [in/out] - address where a pointer to newly allocated memory
* holding the password will be stored upon completion.
* optionsp [in/out] - The address where a pointer to newly allocated memory
* holding the options will be stored upon completion.
* optionsp [in/out] - OPTIONAL address where a pointer to newly allocated
* memory holding the options will be stored upon
* completion.
*
* Returns CURLE_OK on success.
*/
@ -2583,19 +2584,19 @@ CURLcode Curl_parse_login_details(const char *login, const size_t len,
char **userp, char **passwdp,
char **optionsp)
{
CURLcode result = CURLE_OK;
char *ubuf = NULL;
char *pbuf = NULL;
char *obuf = NULL;
const char *psep = NULL;
const char *osep = NULL;
size_t ulen;
size_t plen;
size_t olen;
DEBUGASSERT(userp);
DEBUGASSERT(passwdp);
/* Attempt to find the password separator */
if(passwdp)
psep = memchr(login, ':', len);
psep = memchr(login, ':', len);
/* Attempt to find the options separator */
if(optionsp)
@ -2607,64 +2608,40 @@ CURLcode Curl_parse_login_details(const char *login, const size_t len,
(osep ? (size_t)(osep - login) : len));
plen = (psep ?
(osep && osep > psep ? (size_t)(osep - psep) :
(size_t)(login + len - psep)) - 1 : 0);
(size_t)(login + len - psep)) - 1 : 0);
olen = (osep ?
(psep && psep > osep ? (size_t)(psep - osep) :
(size_t)(login + len - osep)) - 1 : 0);
(size_t)(login + len - osep)) - 1 : 0);
/* Allocate the user portion buffer, which can be zero length */
if(userp) {
ubuf = malloc(ulen + 1);
if(!ubuf)
result = CURLE_OUT_OF_MEMORY;
}
/* Clone the user portion buffer, which can be zero length */
ubuf = Curl_memdup0(login, ulen);
if(!ubuf)
goto error;
/* Allocate the password portion buffer */
if(!result && passwdp && psep) {
pbuf = malloc(plen + 1);
if(!pbuf) {
free(ubuf);
result = CURLE_OUT_OF_MEMORY;
}
/* Clone the password portion buffer */
if(psep) {
pbuf = Curl_memdup0(&psep[1], plen);
if(!pbuf)
goto error;
}
/* Allocate the options portion buffer */
if(!result && optionsp && olen) {
obuf = malloc(olen + 1);
if(!obuf) {
free(pbuf);
free(ubuf);
result = CURLE_OUT_OF_MEMORY;
if(optionsp) {
char *obuf = NULL;
if(olen) {
obuf = Curl_memdup0(&osep[1], olen);
if(!obuf)
goto error;
}
*optionsp = obuf;
}
if(!result) {
/* Store the user portion if necessary */
if(ubuf) {
memcpy(ubuf, login, ulen);
ubuf[ulen] = '\0';
Curl_safefree(*userp);
*userp = ubuf;
}
/* Store the password portion if necessary */
if(pbuf) {
memcpy(pbuf, psep + 1, plen);
pbuf[plen] = '\0';
Curl_safefree(*passwdp);
*passwdp = pbuf;
}
/* Store the options portion if necessary */
if(obuf) {
memcpy(obuf, osep + 1, olen);
obuf[olen] = '\0';
Curl_safefree(*optionsp);
*optionsp = obuf;
}
}
return result;
*userp = ubuf;
*passwdp = pbuf;
return CURLE_OK;
error:
free(ubuf);
free(pbuf);
return CURLE_OUT_OF_MEMORY;
}
/*************************************************************

View File

@ -46,6 +46,8 @@ UNITTEST_START
struct Curl_easy *empty;
const char *hostname = "hostname";
enum dupstring i;
char *userstr = NULL;
char *passwdstr = NULL;
bool async = FALSE;
bool protocol_connect = FALSE;
@ -73,10 +75,12 @@ UNITTEST_START
rc = Curl_init_do(empty, empty->conn);
fail_unless(rc == CURLE_OK, "Curl_init_do() failed");
rc = Curl_parse_login_details(
hostname, strlen(hostname), NULL, NULL, NULL);
rc = Curl_parse_login_details(hostname, strlen(hostname),
&userstr, &passwdstr, NULL);
fail_unless(rc == CURLE_OK,
"Curl_parse_login_details() failed");
free(userstr);
free(passwdstr);
Curl_freeset(empty);
for(i = (enum dupstring)0; i < STRING_LAST; i++) {