Skip to content

Commit 1d58eb0

Browse files
dfandrichbch
authored andcommittedJul 19, 2023
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 curl#10130 Closes curl#10414
1 parent ca311b8 commit 1d58eb0

File tree

5 files changed

+117
-51
lines changed

5 files changed

+117
-51
lines changed
 

‎src/tool_operate.c

+15-10
Original file line numberDiff line numberDiff line change
@@ -1209,21 +1209,26 @@ static CURLcode single_transfer(struct GlobalConfig *global,
12091209
CURLU *uh = curl_url();
12101210
if(uh) {
12111211
char *updated;
1212-
if(curl_url_set(uh, CURLUPART_URL, per->this_url,
1213-
CURLU_GUESS_SCHEME)) {
1214-
result = CURLE_FAILED_INIT;
1212+
CURLUcode uerr;
1213+
uerr = curl_url_set(uh, CURLUPART_URL, per->this_url,
1214+
CURLU_GUESS_SCHEME);
1215+
if(uerr) {
1216+
result = urlerr_cvt(uerr);
12151217
errorf(global, "(%d) Could not parse the URL, "
12161218
"failed to set query\n", result);
12171219
config->synthetic_error = TRUE;
12181220
}
1219-
else if(curl_url_set(uh, CURLUPART_QUERY, q, CURLU_APPENDQUERY) ||
1220-
curl_url_get(uh, CURLUPART_URL, &updated,
1221-
CURLU_GUESS_SCHEME)) {
1222-
result = CURLE_OUT_OF_MEMORY;
1223-
}
12241221
else {
1225-
Curl_safefree(per->this_url); /* free previous URL */
1226-
per->this_url = updated; /* use our new URL instead! */
1222+
uerr = curl_url_set(uh, CURLUPART_QUERY, q, CURLU_APPENDQUERY);
1223+
if(!uerr)
1224+
uerr = curl_url_get(uh, CURLUPART_URL, &updated,
1225+
CURLU_GUESS_SCHEME);
1226+
if(uerr)
1227+
result = urlerr_cvt(uerr);
1228+
else {
1229+
Curl_safefree(per->this_url); /* free previous URL */
1230+
per->this_url = updated; /* use our new URL instead! */
1231+
}
12271232
}
12281233
curl_url_cleanup(uh);
12291234
if(result)

‎src/tool_operhlp.c

+69-40
Original file line numberDiff line numberDiff line change
@@ -71,22 +71,43 @@ bool stdin_upload(const char *uploadfile)
7171
!strcmp(uploadfile, ".")) ? TRUE : FALSE;
7272
}
7373

74+
/* Convert a CURLUcode into a CURLcode */
75+
CURLcode urlerr_cvt(CURLUcode ucode)
76+
{
77+
if(ucode == CURLUE_OUT_OF_MEMORY)
78+
return CURLE_OUT_OF_MEMORY;
79+
else if(ucode == CURLUE_UNSUPPORTED_SCHEME)
80+
return CURLE_UNSUPPORTED_PROTOCOL;
81+
else if(ucode == CURLUE_LACKS_IDN)
82+
return CURLE_NOT_BUILT_IN;
83+
else if(ucode == CURLUE_BAD_HANDLE)
84+
return CURLE_BAD_FUNCTION_ARGUMENT;
85+
return CURLE_URL_MALFORMAT;
86+
}
87+
7488
/*
7589
* Adds the file name to the URL if it doesn't already have one.
7690
* url will be freed before return if the returned pointer is different
7791
*/
7892
CURLcode add_file_name_to_url(CURL *curl, char **inurlp, const char *filename)
7993
{
80-
CURLcode result = CURLE_OUT_OF_MEMORY;
94+
CURLcode result = CURLE_URL_MALFORMAT;
95+
CURLUcode uerr;
8196
CURLU *uh = curl_url();
8297
char *path = NULL;
8398
if(uh) {
8499
char *ptr;
85-
if(curl_url_set(uh, CURLUPART_URL, *inurlp,
86-
CURLU_GUESS_SCHEME|CURLU_NON_SUPPORT_SCHEME))
100+
uerr = curl_url_set(uh, CURLUPART_URL, *inurlp,
101+
CURLU_GUESS_SCHEME|CURLU_NON_SUPPORT_SCHEME);
102+
if(uerr) {
103+
result = urlerr_cvt(uerr);
87104
goto fail;
88-
if(curl_url_get(uh, CURLUPART_PATH, &path, 0))
105+
}
106+
uerr = curl_url_get(uh, CURLUPART_PATH, &path, 0);
107+
if(uerr) {
108+
result = urlerr_cvt(uerr);
89109
goto fail;
110+
}
90111

91112
ptr = strrchr(path, '/');
92113
if(!ptr || !*++ptr) {
@@ -111,7 +132,6 @@ CURLcode add_file_name_to_url(CURL *curl, char **inurlp, const char *filename)
111132
if(encfile) {
112133
char *newpath;
113134
char *newurl;
114-
CURLUcode uerr;
115135
if(ptr)
116136
/* there is a trailing slash on the path */
117137
newpath = aprintf("%s%s", path, encfile);
@@ -125,10 +145,15 @@ CURLcode add_file_name_to_url(CURL *curl, char **inurlp, const char *filename)
125145
goto fail;
126146
uerr = curl_url_set(uh, CURLUPART_PATH, newpath, 0);
127147
free(newpath);
128-
if(uerr)
148+
if(uerr) {
149+
result = urlerr_cvt(uerr);
129150
goto fail;
130-
if(curl_url_get(uh, CURLUPART_URL, &newurl, CURLU_DEFAULT_SCHEME))
151+
}
152+
uerr = curl_url_get(uh, CURLUPART_URL, &newurl, CURLU_DEFAULT_SCHEME);
153+
if(uerr) {
154+
result = urlerr_cvt(uerr);
131155
goto fail;
156+
}
132157
free(*inurlp);
133158
*inurlp = newurl;
134159
result = CURLE_OK;
@@ -153,32 +178,35 @@ CURLcode get_url_file_name(char **filename, const char *url)
153178
const char *pc, *pc2;
154179
CURLU *uh = curl_url();
155180
char *path = NULL;
181+
CURLUcode uerr;
156182

157183
if(!uh)
158184
return CURLE_OUT_OF_MEMORY;
159185

160186
*filename = NULL;
161187

162-
if(!curl_url_set(uh, CURLUPART_URL, url, CURLU_GUESS_SCHEME) &&
163-
!curl_url_get(uh, CURLUPART_PATH, &path, 0)) {
164-
curl_url_cleanup(uh);
188+
uerr = curl_url_set(uh, CURLUPART_URL, url, CURLU_GUESS_SCHEME);
189+
if(!uerr) {
190+
uerr = curl_url_get(uh, CURLUPART_PATH, &path, 0);
191+
if(!uerr) {
192+
curl_url_cleanup(uh);
165193

166-
pc = strrchr(path, '/');
167-
pc2 = strrchr(pc ? pc + 1 : path, '\\');
168-
if(pc2)
169-
pc = pc2;
194+
pc = strrchr(path, '/');
195+
pc2 = strrchr(pc ? pc + 1 : path, '\\');
196+
if(pc2)
197+
pc = pc2;
170198

171-
if(pc)
172-
/* duplicate the string beyond the slash */
173-
pc++;
174-
else
175-
/* no slash => empty string */
176-
pc = "";
199+
if(pc)
200+
/* duplicate the string beyond the slash */
201+
pc++;
202+
else
203+
/* no slash => empty string */
204+
pc = "";
177205

178-
*filename = strdup(pc);
179-
curl_free(path);
180-
if(!*filename)
181-
return CURLE_OUT_OF_MEMORY;
206+
*filename = strdup(pc);
207+
curl_free(path);
208+
if(!*filename)
209+
return CURLE_OUT_OF_MEMORY;
182210

183211
#if defined(MSDOS) || defined(WIN32)
184212
{
@@ -191,25 +219,26 @@ CURLcode get_url_file_name(char **filename, const char *url)
191219
}
192220
#endif /* MSDOS || WIN32 */
193221

194-
/* in case we built debug enabled, we allow an environment variable
195-
* named CURL_TESTDIR to prefix the given file name to put it into a
196-
* specific directory
197-
*/
222+
/* in case we built debug enabled, we allow an environment variable
223+
* named CURL_TESTDIR to prefix the given file name to put it into a
224+
* specific directory
225+
*/
198226
#ifdef DEBUGBUILD
199-
{
200-
char *tdir = curlx_getenv("CURL_TESTDIR");
201-
if(tdir) {
202-
char *alt = aprintf("%s/%s", tdir, *filename);
203-
Curl_safefree(*filename);
204-
*filename = alt;
205-
curl_free(tdir);
206-
if(!*filename)
207-
return CURLE_OUT_OF_MEMORY;
227+
{
228+
char *tdir = curlx_getenv("CURL_TESTDIR");
229+
if(tdir) {
230+
char *alt = aprintf("%s/%s", tdir, *filename);
231+
Curl_safefree(*filename);
232+
*filename = alt;
233+
curl_free(tdir);
234+
if(!*filename)
235+
return CURLE_OUT_OF_MEMORY;
236+
}
208237
}
209-
}
210238
#endif
211-
return CURLE_OK;
239+
return CURLE_OK;
240+
}
212241
}
213242
curl_url_cleanup(uh);
214-
return CURLE_URL_MALFORMAT;
243+
return urlerr_cvt(uerr);
215244
}

‎src/tool_operhlp.h

+2
Original file line numberDiff line numberDiff line change
@@ -37,4 +37,6 @@ CURLcode add_file_name_to_url(CURL *curl, char **inurlp, const char *filename);
3737

3838
CURLcode get_url_file_name(char **filename, const char *url);
3939

40+
CURLcode urlerr_cvt(CURLUcode ucode);
41+
4042
#endif /* HEADER_CURL_TOOL_OPERHLP_H */

‎tests/data/Makefile.inc

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

‎tests/data/test1469

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<testcase>
2+
<info>
3+
<keywords>
4+
FTP
5+
URL
6+
FAILURE
7+
</keywords>
8+
</info>
9+
10+
# Client-side
11+
<client>
12+
<server>
13+
none
14+
</server>
15+
<name>
16+
Space in FTP upload URL
17+
</name>
18+
<command>
19+
"ftp://%HOSTIP:%NOLISTENPORT/%TESTNUMBER%/with space/" -T log/irrelevant-file
20+
</command>
21+
</client>
22+
23+
# Verify data after the test has been "shot"
24+
<verify>
25+
# 3 == CURLE_URL_MALFORMAT
26+
<errorcode>
27+
3
28+
</errorcode>
29+
</verify>
30+
</testcase>

0 commit comments

Comments
 (0)
Please sign in to comment.