urlapi: have *set(PATH) prepend a slash if one is missing

Previously the code would just do that for the path when extracting the
full URL, which made a subsequent curl_url_get() of the path to
(unexpectedly) still return it without the leading path.

Amend lib1560 to verify this. Clarify the curl_url_set() docs about it.

Bug: https://curl.se/mail/lib-2023-06/0015.html
Closes #11272
Reported-by: Pedro Henrique
This commit is contained in:
Daniel Stenberg 2023-06-08 13:15:09 +02:00
parent 7d62f0d9b8
commit 3c9256c8a0
No known key found for this signature in database
GPG key ID: 5CC908FDB71E12C2
3 changed files with 112 additions and 20 deletions

View file

@ -108,6 +108,16 @@ struct setcase {
CURLUcode pcode; /* for updating parts */
};
struct setgetcase {
const char *in;
const char *set;
const char *out;
unsigned int urlflags; /* for setting the URL */
unsigned int setflags; /* for updating parts */
unsigned int getflags; /* for getting parts */
CURLUcode pcode; /* for updating parts */
};
struct testcase {
const char *in;
const char *out;
@ -747,8 +757,33 @@ static int checkurl(const char *org, const char *url, const char *out)
return 0;
}
/* 1. Set the URL
2. Set components
3. Extract all components (not URL)
*/
static const struct setgetcase setget_parts_list[] = {
{"https://example.com",
"path=get,",
"https | [11] | [12] | [13] | example.com | [15] | /get | [16] | [17]",
0, 0, 0, CURLUE_OK},
{"https://example.com",
"path=/get,",
"https | [11] | [12] | [13] | example.com | [15] | /get | [16] | [17]",
0, 0, 0, CURLUE_OK},
{"https://example.com",
"path=g e t,",
"https | [11] | [12] | [13] | example.com | [15] | /g%20e%20t | "
"[16] | [17]",
0, CURLU_URLENCODE, 0, CURLUE_OK},
{NULL, NULL, NULL, 0, 0, 0, CURLUE_OK}
};
/* !checksrc! disable SPACEBEFORECOMMA 1 */
static const struct setcase set_parts_list[] = {
{"https://example.com",
"path=get,",
"https://example.com/get",
0, 0, CURLUE_OK, CURLUE_OK},
{"https://example.com/",
"scheme=ftp+-.123,",
"ftp+-.123://example.com/",
@ -1120,6 +1155,54 @@ static int set_url(void)
return error;
}
/* 1. Set a URL
2. Set one or more parts
3. Extract and compare all parts - not the URL
*/
static int setget_parts(void)
{
int i;
int error = 0;
for(i = 0; setget_parts_list[i].set && !error; i++) {
CURLUcode rc;
CURLU *urlp = curl_url();
if(!urlp) {
error++;
break;
}
if(setget_parts_list[i].in)
rc = curl_url_set(urlp, CURLUPART_URL, setget_parts_list[i].in,
setget_parts_list[i].urlflags);
else
rc = CURLUE_OK;
if(!rc) {
char *url = NULL;
CURLUcode uc = updateurl(urlp, setget_parts_list[i].set,
setget_parts_list[i].setflags);
if(uc != setget_parts_list[i].pcode) {
fprintf(stderr, "updateurl\nin: %s\nreturned %d (expected %d)\n",
setget_parts_list[i].set, (int)uc, setget_parts_list[i].pcode);
error++;
}
if(!uc) {
if(checkparts(urlp, setget_parts_list[i].set, setget_parts_list[i].out,
setget_parts_list[i].getflags))
error++; /* add */
}
curl_free(url);
}
else if(rc != CURLUE_OK) {
fprintf(stderr, "Set parts\nin: %s\nreturned %d (expected %d)\n",
setget_parts_list[i].in, (int)rc, 0);
error++;
}
curl_url_cleanup(urlp);
}
return error;
}
static int set_parts(void)
{
int i;
@ -1593,6 +1676,9 @@ int test(char *URL)
{
(void)URL; /* not used */
if(setget_parts())
return 10;
if(get_url())
return 3;