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(); CURLU *uh = curl_url();
if(uh) { if(uh) {
char *updated; char *updated;
if(curl_url_set(uh, CURLUPART_URL, per->this_url, CURLUcode uerr;
CURLU_GUESS_SCHEME)) { uerr = curl_url_set(uh, CURLUPART_URL, per->this_url,
result = CURLE_FAILED_INIT; CURLU_GUESS_SCHEME);
if(uerr) {
result = urlerr_cvt(uerr);
errorf(global, "(%d) Could not parse the URL, " errorf(global, "(%d) Could not parse the URL, "
"failed to set query\n", result); "failed to set query\n", result);
config->synthetic_error = TRUE; 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 { else {
Curl_safefree(per->this_url); /* free previous URL */ uerr = curl_url_set(uh, CURLUPART_QUERY, q, CURLU_APPENDQUERY);
per->this_url = updated; /* use our new URL instead! */ 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); curl_url_cleanup(uh);
if(result) if(result)

View File

@ -71,22 +71,43 @@ bool stdin_upload(const char *uploadfile)
!strcmp(uploadfile, ".")) ? TRUE : FALSE; !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. * 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 * 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 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(); CURLU *uh = curl_url();
char *path = NULL; char *path = NULL;
if(uh) { if(uh) {
char *ptr; char *ptr;
if(curl_url_set(uh, CURLUPART_URL, *inurlp, uerr = curl_url_set(uh, CURLUPART_URL, *inurlp,
CURLU_GUESS_SCHEME|CURLU_NON_SUPPORT_SCHEME)) CURLU_GUESS_SCHEME|CURLU_NON_SUPPORT_SCHEME);
if(uerr) {
result = urlerr_cvt(uerr);
goto fail; 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; goto fail;
}
ptr = strrchr(path, '/'); ptr = strrchr(path, '/');
if(!ptr || !*++ptr) { if(!ptr || !*++ptr) {
@ -111,7 +132,6 @@ CURLcode add_file_name_to_url(CURL *curl, char **inurlp, const char *filename)
if(encfile) { if(encfile) {
char *newpath; char *newpath;
char *newurl; char *newurl;
CURLUcode uerr;
if(ptr) if(ptr)
/* there is a trailing slash on the path */ /* there is a trailing slash on the path */
newpath = aprintf("%s%s", path, encfile); 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; goto fail;
uerr = curl_url_set(uh, CURLUPART_PATH, newpath, 0); uerr = curl_url_set(uh, CURLUPART_PATH, newpath, 0);
free(newpath); free(newpath);
if(uerr) if(uerr) {
result = urlerr_cvt(uerr);
goto fail; 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; goto fail;
}
free(*inurlp); free(*inurlp);
*inurlp = newurl; *inurlp = newurl;
result = CURLE_OK; result = CURLE_OK;
@ -153,32 +178,35 @@ CURLcode get_url_file_name(char **filename, const char *url)
const char *pc, *pc2; const char *pc, *pc2;
CURLU *uh = curl_url(); CURLU *uh = curl_url();
char *path = NULL; char *path = NULL;
CURLUcode uerr;
if(!uh) if(!uh)
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
*filename = NULL; *filename = NULL;
if(!curl_url_set(uh, CURLUPART_URL, url, CURLU_GUESS_SCHEME) && uerr = curl_url_set(uh, CURLUPART_URL, url, CURLU_GUESS_SCHEME);
!curl_url_get(uh, CURLUPART_PATH, &path, 0)) { if(!uerr) {
curl_url_cleanup(uh); uerr = curl_url_get(uh, CURLUPART_PATH, &path, 0);
if(!uerr) {
curl_url_cleanup(uh);
pc = strrchr(path, '/'); pc = strrchr(path, '/');
pc2 = strrchr(pc ? pc + 1 : path, '\\'); pc2 = strrchr(pc ? pc + 1 : path, '\\');
if(pc2) if(pc2)
pc = pc2; pc = pc2;
if(pc) if(pc)
/* duplicate the string beyond the slash */ /* duplicate the string beyond the slash */
pc++; pc++;
else else
/* no slash => empty string */ /* no slash => empty string */
pc = ""; pc = "";
*filename = strdup(pc); *filename = strdup(pc);
curl_free(path); curl_free(path);
if(!*filename) if(!*filename)
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
#if defined(MSDOS) || defined(WIN32) #if defined(MSDOS) || defined(WIN32)
{ {
@ -191,25 +219,26 @@ CURLcode get_url_file_name(char **filename, const char *url)
} }
#endif /* MSDOS || WIN32 */ #endif /* MSDOS || WIN32 */
/* in case we built debug enabled, we allow an environment variable /* 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 * named CURL_TESTDIR to prefix the given file name to put it into a
* specific directory * specific directory
*/ */
#ifdef DEBUGBUILD #ifdef DEBUGBUILD
{ {
char *tdir = curlx_getenv("CURL_TESTDIR"); char *tdir = curlx_getenv("CURL_TESTDIR");
if(tdir) { if(tdir) {
char *alt = aprintf("%s/%s", tdir, *filename); char *alt = aprintf("%s/%s", tdir, *filename);
Curl_safefree(*filename); Curl_safefree(*filename);
*filename = alt; *filename = alt;
curl_free(tdir); curl_free(tdir);
if(!*filename) if(!*filename)
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
}
} }
}
#endif #endif
return CURLE_OK; return CURLE_OK;
}
} }
curl_url_cleanup(uh); 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 get_url_file_name(char **filename, const char *url);
CURLcode urlerr_cvt(CURLUcode ucode);
#endif /* HEADER_CURL_TOOL_OPERHLP_H */ #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 \ test1440 test1441 test1442 test1443 test1444 test1445 test1446 test1447 \
test1448 test1449 test1450 test1451 test1452 test1453 test1454 test1455 \ test1448 test1449 test1450 test1451 test1452 test1453 test1454 test1455 \
test1456 test1457 test1458 test1459 test1460 test1461 test1462 test1463 \ 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 \ test1500 test1501 test1502 test1503 test1504 test1505 test1506 test1507 \
test1508 test1509 test1510 test1511 test1512 test1513 test1514 test1515 \ 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>