tool_operate: Fix error codes on bad URL & OOM

curl would erroneously report CURLE_OUT_OF_MEMORY in some cases instead
of CURLE_URL_MALFORMAT. In other cases, it would erroneously return
CURLE_URL_MALFORMAT instead of CURLE_OUT_OF_MEMORY.  Add a test case to
test the former condition.

Fixes #10130
Closes #10414
This commit is contained in:
Dan Fandrich 2023-02-04 16:05:35 -08:00 committed by Daniel Stenberg
parent a0adda4b47
commit 349c5391f2
No known key found for this signature in database
GPG Key ID: 5CC908FDB71E12C2
5 changed files with 117 additions and 51 deletions

View File

@ -1209,21 +1209,26 @@ static CURLcode single_transfer(struct GlobalConfig *global,
CURLU *uh = curl_url();
if(uh) {
char *updated;
if(curl_url_set(uh, CURLUPART_URL, per->this_url,
CURLU_GUESS_SCHEME)) {
result = CURLE_FAILED_INIT;
CURLUcode uerr;
uerr = curl_url_set(uh, CURLUPART_URL, per->this_url,
CURLU_GUESS_SCHEME);
if(uerr) {
result = urlerr_cvt(uerr);
errorf(global, "(%d) Could not parse the URL, "
"failed to set query\n", result);
config->synthetic_error = TRUE;
}
else if(curl_url_set(uh, CURLUPART_QUERY, q, CURLU_APPENDQUERY) ||
curl_url_get(uh, CURLUPART_URL, &updated,
CURLU_GUESS_SCHEME)) {
result = CURLE_OUT_OF_MEMORY;
}
else {
Curl_safefree(per->this_url); /* free previous URL */
per->this_url = updated; /* use our new URL instead! */
uerr = curl_url_set(uh, CURLUPART_QUERY, q, CURLU_APPENDQUERY);
if(!uerr)
uerr = curl_url_get(uh, CURLUPART_URL, &updated,
CURLU_GUESS_SCHEME);
if(uerr)
result = urlerr_cvt(uerr);
else {
Curl_safefree(per->this_url); /* free previous URL */
per->this_url = updated; /* use our new URL instead! */
}
}
curl_url_cleanup(uh);
if(result)

View File

@ -71,22 +71,43 @@ bool stdin_upload(const char *uploadfile)
!strcmp(uploadfile, ".")) ? TRUE : FALSE;
}
/* Convert a CURLUcode into a CURLcode */
CURLcode urlerr_cvt(CURLUcode ucode)
{
if(ucode == CURLUE_OUT_OF_MEMORY)
return CURLE_OUT_OF_MEMORY;
else if(ucode == CURLUE_UNSUPPORTED_SCHEME)
return CURLE_UNSUPPORTED_PROTOCOL;
else if(ucode == CURLUE_LACKS_IDN)
return CURLE_NOT_BUILT_IN;
else if(ucode == CURLUE_BAD_HANDLE)
return CURLE_BAD_FUNCTION_ARGUMENT;
return CURLE_URL_MALFORMAT;
}
/*
* Adds the file name to the URL if it doesn't already have one.
* url will be freed before return if the returned pointer is different
*/
CURLcode add_file_name_to_url(CURL *curl, char **inurlp, const char *filename)
{
CURLcode result = CURLE_OUT_OF_MEMORY;
CURLcode result = CURLE_URL_MALFORMAT;
CURLUcode uerr;
CURLU *uh = curl_url();
char *path = NULL;
if(uh) {
char *ptr;
if(curl_url_set(uh, CURLUPART_URL, *inurlp,
CURLU_GUESS_SCHEME|CURLU_NON_SUPPORT_SCHEME))
uerr = curl_url_set(uh, CURLUPART_URL, *inurlp,
CURLU_GUESS_SCHEME|CURLU_NON_SUPPORT_SCHEME);
if(uerr) {
result = urlerr_cvt(uerr);
goto fail;
if(curl_url_get(uh, CURLUPART_PATH, &path, 0))
}
uerr = curl_url_get(uh, CURLUPART_PATH, &path, 0);
if(uerr) {
result = urlerr_cvt(uerr);
goto fail;
}
ptr = strrchr(path, '/');
if(!ptr || !*++ptr) {
@ -111,7 +132,6 @@ CURLcode add_file_name_to_url(CURL *curl, char **inurlp, const char *filename)
if(encfile) {
char *newpath;
char *newurl;
CURLUcode uerr;
if(ptr)
/* there is a trailing slash on the path */
newpath = aprintf("%s%s", path, encfile);
@ -125,10 +145,15 @@ CURLcode add_file_name_to_url(CURL *curl, char **inurlp, const char *filename)
goto fail;
uerr = curl_url_set(uh, CURLUPART_PATH, newpath, 0);
free(newpath);
if(uerr)
if(uerr) {
result = urlerr_cvt(uerr);
goto fail;
if(curl_url_get(uh, CURLUPART_URL, &newurl, CURLU_DEFAULT_SCHEME))
}
uerr = curl_url_get(uh, CURLUPART_URL, &newurl, CURLU_DEFAULT_SCHEME);
if(uerr) {
result = urlerr_cvt(uerr);
goto fail;
}
free(*inurlp);
*inurlp = newurl;
result = CURLE_OK;
@ -153,32 +178,35 @@ CURLcode get_url_file_name(char **filename, const char *url)
const char *pc, *pc2;
CURLU *uh = curl_url();
char *path = NULL;
CURLUcode uerr;
if(!uh)
return CURLE_OUT_OF_MEMORY;
*filename = NULL;
if(!curl_url_set(uh, CURLUPART_URL, url, CURLU_GUESS_SCHEME) &&
!curl_url_get(uh, CURLUPART_PATH, &path, 0)) {
curl_url_cleanup(uh);
uerr = curl_url_set(uh, CURLUPART_URL, url, CURLU_GUESS_SCHEME);
if(!uerr) {
uerr = curl_url_get(uh, CURLUPART_PATH, &path, 0);
if(!uerr) {
curl_url_cleanup(uh);
pc = strrchr(path, '/');
pc2 = strrchr(pc ? pc + 1 : path, '\\');
if(pc2)
pc = pc2;
pc = strrchr(path, '/');
pc2 = strrchr(pc ? pc + 1 : path, '\\');
if(pc2)
pc = pc2;
if(pc)
/* duplicate the string beyond the slash */
pc++;
else
/* no slash => empty string */
pc = "";
if(pc)
/* duplicate the string beyond the slash */
pc++;
else
/* no slash => empty string */
pc = "";
*filename = strdup(pc);
curl_free(path);
if(!*filename)
return CURLE_OUT_OF_MEMORY;
*filename = strdup(pc);
curl_free(path);
if(!*filename)
return CURLE_OUT_OF_MEMORY;
#if defined(MSDOS) || defined(WIN32)
{
@ -191,25 +219,26 @@ CURLcode get_url_file_name(char **filename, const char *url)
}
#endif /* MSDOS || WIN32 */
/* in case we built debug enabled, we allow an environment variable
* named CURL_TESTDIR to prefix the given file name to put it into a
* specific directory
*/
/* in case we built debug enabled, we allow an environment variable
* named CURL_TESTDIR to prefix the given file name to put it into a
* specific directory
*/
#ifdef DEBUGBUILD
{
char *tdir = curlx_getenv("CURL_TESTDIR");
if(tdir) {
char *alt = aprintf("%s/%s", tdir, *filename);
Curl_safefree(*filename);
*filename = alt;
curl_free(tdir);
if(!*filename)
return CURLE_OUT_OF_MEMORY;
{
char *tdir = curlx_getenv("CURL_TESTDIR");
if(tdir) {
char *alt = aprintf("%s/%s", tdir, *filename);
Curl_safefree(*filename);
*filename = alt;
curl_free(tdir);
if(!*filename)
return CURLE_OUT_OF_MEMORY;
}
}
}
#endif
return CURLE_OK;
return CURLE_OK;
}
}
curl_url_cleanup(uh);
return CURLE_URL_MALFORMAT;
return urlerr_cvt(uerr);
}

View File

@ -37,4 +37,6 @@ CURLcode add_file_name_to_url(CURL *curl, char **inurlp, const char *filename);
CURLcode get_url_file_name(char **filename, const char *url);
CURLcode urlerr_cvt(CURLUcode ucode);
#endif /* HEADER_CURL_TOOL_OPERHLP_H */

View File

@ -185,7 +185,7 @@ test1432 test1433 test1434 test1435 test1436 test1437 test1438 test1439 \
test1440 test1441 test1442 test1443 test1444 test1445 test1446 test1447 \
test1448 test1449 test1450 test1451 test1452 test1453 test1454 test1455 \
test1456 test1457 test1458 test1459 test1460 test1461 test1462 test1463 \
test1464 test1465 test1466 test1467 test1468 \
test1464 test1465 test1466 test1467 test1468 test1469 \
\
test1500 test1501 test1502 test1503 test1504 test1505 test1506 test1507 \
test1508 test1509 test1510 test1511 test1512 test1513 test1514 test1515 \

30
tests/data/test1469 Normal file
View File

@ -0,0 +1,30 @@
<testcase>
<info>
<keywords>
FTP
URL
FAILURE
</keywords>
</info>
# Client-side
<client>
<server>
none
</server>
<name>
Space in FTP upload URL
</name>
<command>
"ftp://%HOSTIP:%NOLISTENPORT/%TESTNUMBER%/with space/" -T log/irrelevant-file
</command>
</client>
# Verify data after the test has been "shot"
<verify>
# 3 == CURLE_URL_MALFORMAT
<errorcode>
3
</errorcode>
</verify>
</testcase>