From d5ec44ca4cca9bbe6c21a1d2a94b37cba77661ff Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 15 Apr 2014 13:49:18 +0200 Subject: [PATCH] INFILESIZE: fields in UserDefined must not be changed run-time set.infilesize in this case was modified in several places, which could lead to repeated requests using the same handle to get unintendent/wrong consequences based on what the previous request did! --- lib/curl_rtmp.c | 3 ++- lib/file.c | 6 +++--- lib/ftp.c | 14 +++++++------- lib/http.c | 20 ++++++++++---------- lib/imap.c | 6 +++--- lib/multi.c | 2 ++ lib/rtsp.c | 2 +- lib/smtp.c | 8 ++++---- lib/ssh.c | 18 +++++++++--------- lib/tftp.c | 8 ++++---- lib/transfer.c | 4 ++-- lib/url.c | 13 +++++++------ lib/urldata.h | 4 +++- 13 files changed, 57 insertions(+), 51 deletions(-) diff --git a/lib/curl_rtmp.c b/lib/curl_rtmp.c index 45da35ca0..e0c24b036 100644 --- a/lib/curl_rtmp.c +++ b/lib/curl_rtmp.c @@ -5,6 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * + * Copyright (C) 2012 - 2014, Daniel Stenberg, , et al. * Copyright (C) 2010, Howard Chu, * * This software is licensed as described in the file COPYING, which @@ -240,7 +241,7 @@ static CURLcode rtmp_do(struct connectdata *conn, bool *done) return CURLE_FAILED_INIT; if(conn->data->set.upload) { - Curl_pgrsSetUploadSize(conn->data, conn->data->set.infilesize); + Curl_pgrsSetUploadSize(conn->data, conn->data->state.infilesize); Curl_setup_transfer(conn, -1, -1, FALSE, NULL, FIRSTSOCKET, NULL); } else diff --git a/lib/file.c b/lib/file.c index 043cccd47..73df42e02 100644 --- a/lib/file.c +++ b/lib/file.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2013, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2014, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -336,9 +336,9 @@ static CURLcode file_upload(struct connectdata *conn) return CURLE_WRITE_ERROR; } - if(-1 != data->set.infilesize) + if(-1 != data->state.infilesize) /* known size of data to "upload" */ - Curl_pgrsSetUploadSize(data, data->set.infilesize); + Curl_pgrsSetUploadSize(data, data->state.infilesize); /* treat the negative resume offset value as the case of "-" */ if(data->state.resume_from < 0) { diff --git a/lib/ftp.c b/lib/ftp.c index e8ac363c8..cadec10f5 100644 --- a/lib/ftp.c +++ b/lib/ftp.c @@ -507,7 +507,7 @@ static CURLcode InitiateTransfer(struct connectdata *conn) /* When we know we're uploading a specified file, we can get the file size prior to the actual upload. */ - Curl_pgrsSetUploadSize(data, data->set.infilesize); + Curl_pgrsSetUploadSize(data, data->state.infilesize); /* set the SO_SNDBUF for the secondary socket for those who need it */ Curl_sndbufset(conn->sock[SECONDARYSOCKET]); @@ -1683,10 +1683,10 @@ static CURLcode ftp_state_ul_setup(struct connectdata *conn, } } /* now, decrease the size of the read */ - if(data->set.infilesize>0) { - data->set.infilesize -= data->state.resume_from; + if(data->state.infilesize>0) { + data->state.infilesize -= data->state.resume_from; - if(data->set.infilesize <= 0) { + if(data->state.infilesize <= 0) { infof(data, "File already completely uploaded\n"); /* no data to transfer */ @@ -3382,13 +3382,13 @@ static CURLcode ftp_done(struct connectdata *conn, CURLcode status, use checking further */ ; else if(data->set.upload) { - if((-1 != data->set.infilesize) && - (data->set.infilesize != *ftp->bytecountp) && + if((-1 != data->state.infilesize) && + (data->state.infilesize != *ftp->bytecountp) && !data->set.crlf && (ftp->transfer == FTPTRANSFER_BODY)) { failf(data, "Uploaded unaligned file size (%" CURL_FORMAT_CURL_OFF_T " out of %" CURL_FORMAT_CURL_OFF_T " bytes)", - *ftp->bytecountp, data->set.infilesize); + *ftp->bytecountp, data->state.infilesize); result = CURLE_PARTIAL_FILE; } } diff --git a/lib/http.c b/lib/http.c index abcdd6ab8..fb4334966 100644 --- a/lib/http.c +++ b/lib/http.c @@ -405,8 +405,8 @@ static CURLcode http_perhapsrewind(struct connectdata *conn) expectsend = (curl_off_t)strlen(data->set.postfields); break; case HTTPREQ_PUT: - if(data->set.infilesize != -1) - expectsend = data->set.infilesize; + if(data->state.infilesize != -1) + expectsend = data->state.infilesize; break; case HTTPREQ_POST_FORM: expectsend = http->postsize; @@ -1885,7 +1885,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) else { if((conn->handler->protocol&PROTO_FAMILY_HTTP) && data->set.upload && - (data->set.infilesize == -1)) { + (data->state.infilesize == -1)) { if(conn->bits.authneg) /* don't enable chunked during auth neg */ ; @@ -2123,10 +2123,10 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) } /* now, decrease the size of the read */ - if(data->set.infilesize>0) { - data->set.infilesize -= data->state.resume_from; + if(data->state.infilesize>0) { + data->state.infilesize -= data->state.resume_from; - if(data->set.infilesize <= 0) { + if(data->state.infilesize <= 0) { failf(data, "File already completely uploaded"); return CURLE_PARTIAL_FILE; } @@ -2162,13 +2162,13 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) conn->allocptr.rangeline = aprintf("Content-Range: bytes 0-%" CURL_FORMAT_CURL_OFF_T "/%" CURL_FORMAT_CURL_OFF_T "\r\n", - data->set.infilesize - 1, data->set.infilesize); + data->state.infilesize - 1, data->state.infilesize); } else if(data->state.resume_from) { /* This is because "resume" was selected */ curl_off_t total_expected_size= - data->state.resume_from + data->set.infilesize; + data->state.resume_from + data->state.infilesize; conn->allocptr.rangeline = aprintf("Content-Range: bytes %s%" CURL_FORMAT_CURL_OFF_T "/%" CURL_FORMAT_CURL_OFF_T "\r\n", @@ -2180,7 +2180,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) append total size */ conn->allocptr.rangeline = aprintf("Content-Range: bytes %s/%" CURL_FORMAT_CURL_OFF_T "\r\n", - data->state.range, data->set.infilesize); + data->state.range, data->state.infilesize); } if(!conn->allocptr.rangeline) return CURLE_OUT_OF_MEMORY; @@ -2455,7 +2455,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) if(conn->bits.authneg) postsize = 0; else - postsize = data->set.infilesize; + postsize = data->state.infilesize; if((postsize != -1) && !data->req.upload_chunky && !Curl_checkheaders(conn, "Content-Length:")) { diff --git a/lib/imap.c b/lib/imap.c index fc162b6c8..713060352 100644 --- a/lib/imap.c +++ b/lib/imap.c @@ -775,7 +775,7 @@ static CURLcode imap_perform_append(struct connectdata *conn) } /* Check we know the size of the upload */ - if(conn->data->set.infilesize < 0) { + if(conn->data->state.infilesize < 0) { failf(conn->data, "Cannot APPEND with unknown input file size\n"); return CURLE_UPLOAD_FAILED; } @@ -787,7 +787,7 @@ static CURLcode imap_perform_append(struct connectdata *conn) /* Send the APPEND command */ result = imap_sendf(conn, "APPEND %s (\\Seen) {%" CURL_FORMAT_CURL_OFF_T "}", - mailbox, conn->data->set.infilesize); + mailbox, conn->data->state.infilesize); Curl_safefree(mailbox); @@ -1618,7 +1618,7 @@ static CURLcode imap_state_append_resp(struct connectdata *conn, int imapcode, } else { /* Set the progress upload size */ - Curl_pgrsSetUploadSize(data, data->set.infilesize); + Curl_pgrsSetUploadSize(data, data->state.infilesize); /* IMAP upload */ Curl_setup_transfer(conn, -1, -1, FALSE, NULL, FIRSTSOCKET, NULL); diff --git a/lib/multi.c b/lib/multi.c index bc932640a..7720c957a 100644 --- a/lib/multi.c +++ b/lib/multi.c @@ -404,6 +404,8 @@ CURLMcode curl_multi_add_handle(CURLM *multi_handle, /* Point to the multi's connection cache */ data->state.conn_cache = multi->conn_cache; + data->state.infilesize = data->set.filesize; + /* This adds the new entry at the 'end' of the doubly-linked circular list of SessionHandle structs to try and maintain a FIFO queue so the pipelined requests are in order. */ diff --git a/lib/rtsp.c b/lib/rtsp.c index e746fb1b1..029738d9b 100644 --- a/lib/rtsp.c +++ b/lib/rtsp.c @@ -493,7 +493,7 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done) rtspreq == RTSPREQ_GET_PARAMETER) { if(data->set.upload) { - putsize = data->set.infilesize; + putsize = data->state.infilesize; data->set.httpreq = HTTPREQ_PUT; } diff --git a/lib/smtp.c b/lib/smtp.c index d367d94b8..762a8d16a 100644 --- a/lib/smtp.c +++ b/lib/smtp.c @@ -583,8 +583,8 @@ static CURLcode smtp_perform_mail(struct connectdata *conn) } /* Calculate the optional SIZE parameter */ - if(conn->proto.smtpc.size_supported && conn->data->set.infilesize > 0) { - size = aprintf("%" CURL_FORMAT_CURL_OFF_T, data->set.infilesize); + if(conn->proto.smtpc.size_supported && conn->data->state.infilesize > 0) { + size = aprintf("%" CURL_FORMAT_CURL_OFF_T, data->state.infilesize); if(!size) { Curl_safefree(from); @@ -1356,7 +1356,7 @@ static CURLcode smtp_state_data_resp(struct connectdata *conn, int smtpcode, } else { /* Set the progress upload size */ - Curl_pgrsSetUploadSize(data, data->set.infilesize); + Curl_pgrsSetUploadSize(data, data->state.infilesize); /* SMTP upload */ Curl_setup_transfer(conn, -1, -1, FALSE, NULL, FIRSTSOCKET, NULL); @@ -1659,7 +1659,7 @@ static CURLcode smtp_done(struct connectdata *conn, CURLcode status, is "no mail data". RFC-5321, sect. 4.1.1.4. */ eob = SMTP_EOB; len = SMTP_EOB_LEN; - if(smtp->trailing_crlf || !conn->data->set.infilesize) { + if(smtp->trailing_crlf || !conn->data->state.infilesize) { eob += 2; len -= 2; } diff --git a/lib/ssh.c b/lib/ssh.c index ad6d3226e..5e18ca722 100644 --- a/lib/ssh.c +++ b/lib/ssh.c @@ -1717,17 +1717,17 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) } /* now, decrease the size of the read */ - if(data->set.infilesize > 0) { - data->set.infilesize -= data->state.resume_from; - data->req.size = data->set.infilesize; - Curl_pgrsSetUploadSize(data, data->set.infilesize); + if(data->state.infilesize > 0) { + data->state.infilesize -= data->state.resume_from; + data->req.size = data->state.infilesize; + Curl_pgrsSetUploadSize(data, data->state.infilesize); } SFTP_SEEK(sshc->sftp_handle, data->state.resume_from); } - if(data->set.infilesize > 0) { - data->req.size = data->set.infilesize; - Curl_pgrsSetUploadSize(data, data->set.infilesize); + if(data->state.infilesize > 0) { + data->req.size = data->state.infilesize; + Curl_pgrsSetUploadSize(data, data->state.infilesize); } /* upload data */ Curl_setup_transfer(conn, -1, -1, FALSE, NULL, FIRSTSOCKET, NULL); @@ -2256,7 +2256,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) } if(data->set.upload) { - if(data->set.infilesize < 0) { + if(data->state.infilesize < 0) { failf(data, "SCP requires a known file size for upload"); sshc->actualcode = CURLE_UPLOAD_FAILED; state(conn, SSH_SCP_CHANNEL_FREE); @@ -2278,7 +2278,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) */ sshc->ssh_channel = SCP_SEND(sshc->ssh_session, sftp_scp->path, data->set.new_file_perms, - data->set.infilesize); + data->state.infilesize); if(!sshc->ssh_channel) { if(libssh2_session_last_errno(sshc->ssh_session) == LIBSSH2_ERROR_EAGAIN) { diff --git a/lib/tftp.c b/lib/tftp.c index 03a84e631..d19f48029 100644 --- a/lib/tftp.c +++ b/lib/tftp.c @@ -477,8 +477,8 @@ static CURLcode tftp_send_first(tftp_state_data_t *state, tftp_event_t event) setpacketevent(&state->spacket, TFTP_EVENT_WRQ); state->conn->data->req.upload_fromhere = (char *)state->spacket.data+4; - if(data->set.infilesize != -1) - Curl_pgrsSetUploadSize(data, data->set.infilesize); + if(data->state.infilesize != -1) + Curl_pgrsSetUploadSize(data, data->state.infilesize); } else { /* If we are downloading, send an RRQ */ @@ -498,9 +498,9 @@ static CURLcode tftp_send_first(tftp_state_data_t *state, tftp_event_t event) sbytes = 4 + strlen(filename) + strlen(mode); /* add tsize option */ - if(data->set.upload && (data->set.infilesize != -1)) + if(data->set.upload && (data->state.infilesize != -1)) snprintf(buf, sizeof(buf), "%" CURL_FORMAT_CURL_OFF_T, - data->set.infilesize); + data->state.infilesize); else strcpy(buf, "0"); /* the destination is large enough */ diff --git a/lib/transfer.c b/lib/transfer.c index 46e55fbb5..c1cdde60b 100644 --- a/lib/transfer.c +++ b/lib/transfer.c @@ -926,7 +926,7 @@ static CURLcode readwrite_upload(struct SessionHandle *data, if(!data->set.crlf) { /* we're here only because FTP is in ASCII mode... bump infilesize for the LF we just added */ - data->set.infilesize++; + data->state.infilesize++; } } else @@ -967,7 +967,7 @@ static CURLcode readwrite_upload(struct SessionHandle *data, k->writebytecount += bytes_written; - if(k->writebytecount == data->set.infilesize) { + if(k->writebytecount == data->state.infilesize) { /* we have sent all data we were supposed to */ k->upload_done = TRUE; infof(data, "We are completely uploaded and fine\n"); diff --git a/lib/url.c b/lib/url.c index 409085f93..5952a9bec 100644 --- a/lib/url.c +++ b/lib/url.c @@ -485,7 +485,7 @@ CURLcode Curl_init_userdefined(struct UserDefined *set) set->convtonetwork = ZERO_NULL; set->convfromutf8 = ZERO_NULL; - set->infilesize = -1; /* we don't know any size */ + set->filesize = -1; /* we don't know the size */ set->postfieldsize = -1; /* unknown size */ set->maxredirs = -1; /* allow any amount by default */ @@ -1491,14 +1491,14 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, * If known, this should inform curl about the file size of the * to-be-uploaded file. */ - data->set.infilesize = va_arg(param, long); + data->set.filesize = va_arg(param, long); break; case CURLOPT_INFILESIZE_LARGE: /* * If known, this should inform curl about the file size of the * to-be-uploaded file. */ - data->set.infilesize = va_arg(param, curl_off_t); + data->set.filesize = va_arg(param, curl_off_t); break; case CURLOPT_LOW_SPEED_LIMIT: /* @@ -4100,16 +4100,17 @@ static CURLcode setup_connection_internals(struct connectdata *conn) { const struct Curl_handler * p; CURLcode result; + struct SessionHandle *data = conn->data; /* in some case in the multi state-machine, we go back to the CONNECT state and then a second (or third or...) call to this function will be made without doing a DISCONNECT or DONE in between (since the connection is yet in place) and therefore this function needs to first make sure there's no lingering previous data allocated. */ - Curl_free_request_state(conn->data); + Curl_free_request_state(data); - memset(&conn->data->req, 0, sizeof(struct SingleRequest)); - conn->data->req.maxdownload = -1; + memset(&data->req, 0, sizeof(struct SingleRequest)); + data->req.maxdownload = -1; conn->socktype = SOCK_STREAM; /* most of them are TCP streams */ diff --git a/lib/urldata.h b/lib/urldata.h index 16f08d30e..e62ea1930 100644 --- a/lib/urldata.h +++ b/lib/urldata.h @@ -1306,6 +1306,8 @@ struct UrlState { /* if true, force SSL connection retry (workaround for certain servers) */ bool ssl_connect_retry; + curl_off_t infilesize; /* size of file to upload, -1 means unknown. + Copied from set.filesize at start of operation */ }; @@ -1467,7 +1469,7 @@ struct UserDefined { long accepttimeout; /* in milliseconds, 0 means no timeout */ long server_response_timeout; /* in milliseconds, 0 means no timeout */ long tftp_blksize ; /* in bytes, 0 means use default */ - curl_off_t infilesize; /* size of file to upload, -1 means unknown */ + curl_off_t filesize; /* size of file to upload, -1 means unknown */ long low_speed_limit; /* bytes/second */ long low_speed_time; /* number of seconds */ curl_off_t max_send_speed; /* high speed limit in bytes/second for upload */