Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
openSUSE:Step:15
curl.25571
curl-CVE-2020-8285.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File curl-CVE-2020-8285.patch of Package curl.25571
From c11171033d5eb8e6514bbabd49c710e0b9885e6f Mon Sep 17 00:00:00 2001 From: Daniel Stenberg <daniel@haxx.se> Date: Sat, 28 Nov 2020 00:27:21 +0100 Subject: [PATCH] ftp: make wc_statemach loop instead of recurse --- lib/ftp.c | 202 +++++++++++++++++++++++++++--------------------------- 1 file changed, 102 insertions(+), 100 deletions(-) Index: curl-7.60.0/lib/ftp.c =================================================================== --- curl-7.60.0.orig/lib/ftp.c +++ curl-7.60.0/lib/ftp.c @@ -3787,130 +3787,133 @@ static CURLcode init_wc_data(struct conn return result; } -/* This is called recursively */ static CURLcode wc_statemach(struct connectdata *conn) { struct WildcardData * const wildcard = &(conn->data->wildcard); CURLcode result = CURLE_OK; - switch(wildcard->state) { - case CURLWC_INIT: - result = init_wc_data(conn); - if(wildcard->state == CURLWC_CLEAN) - /* only listing! */ - break; - wildcard->state = result ? CURLWC_ERROR : CURLWC_MATCHING; - break; - - case CURLWC_MATCHING: { - /* In this state is LIST response successfully parsed, so lets restore - previous WRITEFUNCTION callback and WRITEDATA pointer */ - struct ftp_wc *ftpwc = wildcard->protdata; - conn->data->set.fwrite_func = ftpwc->backup.write_function; - conn->data->set.out = ftpwc->backup.file_descriptor; - ftpwc->backup.write_function = ZERO_NULL; - ftpwc->backup.file_descriptor = NULL; - wildcard->state = CURLWC_DOWNLOADING; - - if(Curl_ftp_parselist_geterror(ftpwc->parser)) { - /* error found in LIST parsing */ - wildcard->state = CURLWC_CLEAN; - return wc_statemach(conn); - } - if(wildcard->filelist.size == 0) { - /* no corresponding file */ - wildcard->state = CURLWC_CLEAN; - return CURLE_REMOTE_FILE_NOT_FOUND; - } - return wc_statemach(conn); - } + for(;;) { + switch(wildcard->state) { + case CURLWC_INIT: + result = init_wc_data(conn); + if(wildcard->state == CURLWC_CLEAN) + /* only listing! */ + return result; + wildcard->state = result ? CURLWC_ERROR : CURLWC_MATCHING; + return result; - case CURLWC_DOWNLOADING: { - /* filelist has at least one file, lets get first one */ - struct ftp_conn *ftpc = &conn->proto.ftpc; - struct curl_fileinfo *finfo = wildcard->filelist.head->ptr; - - char *tmp_path = aprintf("%s%s", wildcard->path, finfo->filename); - if(!tmp_path) - return CURLE_OUT_OF_MEMORY; - - /* switch default "state.pathbuffer" and tmp_path, good to see - ftp_parse_url_path function to understand this trick */ - Curl_safefree(conn->data->state.pathbuffer); - conn->data->state.pathbuffer = tmp_path; - conn->data->state.path = tmp_path; - - infof(conn->data, "Wildcard - START of \"%s\"\n", finfo->filename); - if(conn->data->set.chunk_bgn) { - long userresponse; - Curl_set_in_callback(conn->data, true); - userresponse = conn->data->set.chunk_bgn( - finfo, wildcard->customptr, (int)wildcard->filelist.size); - Curl_set_in_callback(conn->data, false); - switch(userresponse) { - case CURL_CHUNK_BGN_FUNC_SKIP: - infof(conn->data, "Wildcard - \"%s\" skipped by user\n", - finfo->filename); - wildcard->state = CURLWC_SKIP; - return wc_statemach(conn); - case CURL_CHUNK_BGN_FUNC_FAIL: - return CURLE_CHUNK_FAILED; + case CURLWC_MATCHING: { + /* In this state is LIST response successfully parsed, so lets restore + previous WRITEFUNCTION callback and WRITEDATA pointer */ + struct ftp_wc *ftpwc = wildcard->protdata; + conn->data->set.fwrite_func = ftpwc->backup.write_function; + conn->data->set.out = ftpwc->backup.file_descriptor; + ftpwc->backup.write_function = ZERO_NULL; + ftpwc->backup.file_descriptor = NULL; + wildcard->state = CURLWC_DOWNLOADING; + + if(Curl_ftp_parselist_geterror(ftpwc->parser)) { + /* error found in LIST parsing */ + wildcard->state = CURLWC_CLEAN; + continue; } + if(wildcard->filelist.size == 0) { + /* no corresponding file */ + wildcard->state = CURLWC_CLEAN; + return CURLE_REMOTE_FILE_NOT_FOUND; + } + continue; } - if(finfo->filetype != CURLFILETYPE_FILE) { - wildcard->state = CURLWC_SKIP; - return wc_statemach(conn); - } + case CURLWC_DOWNLOADING: { + /* filelist has at least one file, lets get first one */ + struct ftp_conn *ftpc = &conn->proto.ftpc; + struct curl_fileinfo *finfo = wildcard->filelist.head->ptr; + struct FTP *ftp = conn->data->req.protop; + + char *tmp_path = aprintf("%s%s", wildcard->path, finfo->filename); + if(!tmp_path) + return CURLE_OUT_OF_MEMORY; + + /* switch default "state.pathbuffer" and tmp_path, good to see + ftp_parse_url_path function to understand this trick */ + Curl_safefree(conn->data->state.pathbuffer); + conn->data->state.pathbuffer = tmp_path; + conn->data->state.path = tmp_path; + + infof(conn->data, "Wildcard - START of \"%s\"\n", finfo->filename); + if(conn->data->set.chunk_bgn) { + long userresponse; + Curl_set_in_callback(conn->data, true); + userresponse = conn->data->set.chunk_bgn( + finfo, wildcard->customptr, (int)wildcard->filelist.size); + Curl_set_in_callback(conn->data, false); + switch(userresponse) { + case CURL_CHUNK_BGN_FUNC_SKIP: + infof(conn->data, "Wildcard - \"%s\" skipped by user\n", + finfo->filename); + wildcard->state = CURLWC_SKIP; + continue; + case CURL_CHUNK_BGN_FUNC_FAIL: + return CURLE_CHUNK_FAILED; + } + } - if(finfo->flags & CURLFINFOFLAG_KNOWN_SIZE) - ftpc->known_filesize = finfo->size; + if(finfo->filetype != CURLFILETYPE_FILE) { + wildcard->state = CURLWC_SKIP; + continue; + } - result = ftp_parse_url_path(conn); - if(result) - return result; + if(finfo->flags & CURLFINFOFLAG_KNOWN_SIZE) + ftpc->known_filesize = finfo->size; - /* we don't need the Curl_fileinfo of first file anymore */ - Curl_llist_remove(&wildcard->filelist, wildcard->filelist.head, NULL); + result = ftp_parse_url_path(conn); + if(result) + return result; + + /* we don't need the Curl_fileinfo of first file anymore */ + Curl_llist_remove(&wildcard->filelist, wildcard->filelist.head, NULL); + + if(wildcard->filelist.size == 0) { /* remains only one file to down. */ + wildcard->state = CURLWC_CLEAN; + /* after that will be ftp_do called once again and no transfer + will be done because of CURLWC_CLEAN state */ + return CURLE_OK; + } + return result; + } - if(wildcard->filelist.size == 0) { /* remains only one file to down. */ - wildcard->state = CURLWC_CLEAN; - /* after that will be ftp_do called once again and no transfer - will be done because of CURLWC_CLEAN state */ - return CURLE_OK; + case CURLWC_SKIP: { + if(conn->data->set.chunk_end) { + Curl_set_in_callback(conn->data, true); + conn->data->set.chunk_end(conn->data->wildcard.customptr); + Curl_set_in_callback(conn->data, false); + } + Curl_llist_remove(&wildcard->filelist, wildcard->filelist.head, NULL); + wildcard->state = (wildcard->filelist.size == 0) ? + CURLWC_CLEAN : CURLWC_DOWNLOADING; + continue; } - } break; - case CURLWC_SKIP: { - if(conn->data->set.chunk_end) { - Curl_set_in_callback(conn->data, true); - conn->data->set.chunk_end(conn->data->wildcard.customptr); - Curl_set_in_callback(conn->data, false); + case CURLWC_CLEAN: { + struct ftp_wc *ftpwc = wildcard->protdata; + result = CURLE_OK; + if(ftpwc) + result = Curl_ftp_parselist_geterror(ftpwc->parser); + + wildcard->state = result ? CURLWC_ERROR : CURLWC_DONE; + return result; } - Curl_llist_remove(&wildcard->filelist, wildcard->filelist.head, NULL); - wildcard->state = (wildcard->filelist.size == 0) ? - CURLWC_CLEAN : CURLWC_DOWNLOADING; - return wc_statemach(conn); - } - case CURLWC_CLEAN: { - struct ftp_wc *ftpwc = wildcard->protdata; - result = CURLE_OK; - if(ftpwc) - result = Curl_ftp_parselist_geterror(ftpwc->parser); - - wildcard->state = result ? CURLWC_ERROR : CURLWC_DONE; - } break; - - case CURLWC_DONE: - case CURLWC_ERROR: - case CURLWC_CLEAR: - if(wildcard->dtor) - wildcard->dtor(wildcard->protdata); - break; + case CURLWC_DONE: + case CURLWC_ERROR: + case CURLWC_CLEAR: + if(wildcard->dtor) + wildcard->dtor(wildcard->protdata); + return result; + } } - - return result; + /* UNREACHABLE */ } /***********************************************************************
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor