mirror of
https://github.com/curl/curl.git
synced 2026-05-14 20:36:20 +03:00
tool_formparse: tool2curlparts is no longer recursive
It could otherwise trigger a stack overflow in extreme cases Reported-by: Andrew Nesbit Closes #21518
This commit is contained in:
parent
74bc655bdf
commit
98d818cf2b
1 changed files with 81 additions and 49 deletions
|
|
@ -251,71 +251,103 @@ static int tool_mime_stdin_seek(void *instream, curl_off_t offset, int whence)
|
|||
|
||||
/* Translate an internal mime tree into a libcurl mime tree. */
|
||||
|
||||
#define MAX_FORMPARTS 100000 /* arbitrarily picked */
|
||||
|
||||
static CURLcode tool2curlparts(CURL *curl, struct tool_mime *m,
|
||||
curl_mime *mime)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
curl_mimepart *part = NULL;
|
||||
curl_mime *submime = NULL;
|
||||
const char *filename = NULL;
|
||||
struct tool_mime *curr;
|
||||
struct tool_mime **nodes = NULL;
|
||||
int count;
|
||||
int i;
|
||||
|
||||
if(m) {
|
||||
result = tool2curlparts(curl, m->prev, mime);
|
||||
if(!result) {
|
||||
part = curl_mime_addpart(mime);
|
||||
if(!part)
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
if(!m)
|
||||
return CURLE_OK;
|
||||
|
||||
for(curr = m, count = 0; curr; curr = curr->prev) {
|
||||
if(count > MAX_FORMPARTS)
|
||||
return CURLE_BAD_FUNCTION_ARGUMENT;
|
||||
count++;
|
||||
}
|
||||
|
||||
nodes = curlx_malloc(sizeof(struct tool_mime *) * count);
|
||||
if(!nodes)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
/* populate array from the end to the beginning */
|
||||
curr = m;
|
||||
for(i = count - 1; i >= 0; i--) {
|
||||
nodes[i] = curr;
|
||||
curr = curr->prev;
|
||||
}
|
||||
|
||||
for(i = 0; i < count; i++) {
|
||||
struct tool_mime *node = nodes[i];
|
||||
curl_mimepart *part = NULL;
|
||||
curl_mime *submime = NULL;
|
||||
const char *filename = node->filename;
|
||||
|
||||
part = curl_mime_addpart(mime);
|
||||
if(!part) {
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
break;
|
||||
}
|
||||
if(!result) {
|
||||
filename = m->filename;
|
||||
switch(m->kind) {
|
||||
case TOOLMIME_PARTS:
|
||||
result = tool2curlmime(curl, m, &submime);
|
||||
if(!result) {
|
||||
result = curl_mime_subparts(part, submime);
|
||||
if(result)
|
||||
curl_mime_free(submime);
|
||||
}
|
||||
break;
|
||||
|
||||
case TOOLMIME_DATA:
|
||||
result = curl_mime_data(part, m->data, CURL_ZERO_TERMINATED);
|
||||
break;
|
||||
|
||||
case TOOLMIME_FILE:
|
||||
case TOOLMIME_FILEDATA:
|
||||
result = curl_mime_filedata(part, m->data);
|
||||
if(!result && m->kind == TOOLMIME_FILEDATA && !filename)
|
||||
result = curl_mime_filename(part, NULL);
|
||||
break;
|
||||
|
||||
case TOOLMIME_STDIN:
|
||||
if(!filename)
|
||||
filename = "-";
|
||||
FALLTHROUGH();
|
||||
case TOOLMIME_STDINDATA:
|
||||
result = curl_mime_data_cb(part, m->size,
|
||||
tool_mime_stdin_read,
|
||||
tool_mime_stdin_seek,
|
||||
NULL, m);
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Other cases not possible in this context. */
|
||||
break;
|
||||
switch(node->kind) {
|
||||
case TOOLMIME_PARTS:
|
||||
result = tool2curlmime(curl, node, &submime);
|
||||
if(!result) {
|
||||
result = curl_mime_subparts(part, submime);
|
||||
if(result)
|
||||
curl_mime_free(submime);
|
||||
}
|
||||
break;
|
||||
|
||||
case TOOLMIME_DATA:
|
||||
result = curl_mime_data(part, node->data, CURL_ZERO_TERMINATED);
|
||||
break;
|
||||
|
||||
case TOOLMIME_FILE:
|
||||
case TOOLMIME_FILEDATA:
|
||||
result = curl_mime_filedata(part, node->data);
|
||||
if(!result && node->kind == TOOLMIME_FILEDATA && !filename)
|
||||
result = curl_mime_filename(part, NULL);
|
||||
break;
|
||||
|
||||
case TOOLMIME_STDIN:
|
||||
if(!filename)
|
||||
filename = "-";
|
||||
FALLTHROUGH();
|
||||
case TOOLMIME_STDINDATA:
|
||||
result = curl_mime_data_cb(part, node->size,
|
||||
tool_mime_stdin_read,
|
||||
tool_mime_stdin_seek,
|
||||
NULL, node);
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Other cases not possible in this context. */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Common part configuration */
|
||||
if(!result && filename)
|
||||
result = curl_mime_filename(part, filename);
|
||||
if(!result)
|
||||
result = curl_mime_type(part, m->type);
|
||||
result = curl_mime_type(part, node->type);
|
||||
if(!result)
|
||||
result = curl_mime_headers(part, m->headers, 0);
|
||||
result = curl_mime_headers(part, node->headers, 0);
|
||||
if(!result)
|
||||
result = curl_mime_encoder(part, m->encoder);
|
||||
result = curl_mime_encoder(part, node->encoder);
|
||||
if(!result)
|
||||
result = curl_mime_name(part, m->name);
|
||||
result = curl_mime_name(part, node->name);
|
||||
|
||||
if(result)
|
||||
break;
|
||||
}
|
||||
|
||||
curlx_free(nodes);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue