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!
This commit is contained in:
Daniel Stenberg 2014-04-15 13:49:18 +02:00
parent 9c941e92c4
commit d5ec44ca4c
13 changed files with 57 additions and 51 deletions

View File

@ -5,6 +5,7 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 2012 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 2010, Howard Chu, <hyc@highlandsun.com> * Copyright (C) 2010, Howard Chu, <hyc@highlandsun.com>
* *
* This software is licensed as described in the file COPYING, which * 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; return CURLE_FAILED_INIT;
if(conn->data->set.upload) { 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); Curl_setup_transfer(conn, -1, -1, FALSE, NULL, FIRSTSOCKET, NULL);
} }
else else

View File

@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * 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; return CURLE_WRITE_ERROR;
} }
if(-1 != data->set.infilesize) if(-1 != data->state.infilesize)
/* known size of data to "upload" */ /* 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 "-" */ /* treat the negative resume offset value as the case of "-" */
if(data->state.resume_from < 0) { if(data->state.resume_from < 0) {

View File

@ -507,7 +507,7 @@ static CURLcode InitiateTransfer(struct connectdata *conn)
/* When we know we're uploading a specified file, we can get the file /* When we know we're uploading a specified file, we can get the file
size prior to the actual upload. */ 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 */ /* set the SO_SNDBUF for the secondary socket for those who need it */
Curl_sndbufset(conn->sock[SECONDARYSOCKET]); 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 */ /* now, decrease the size of the read */
if(data->set.infilesize>0) { if(data->state.infilesize>0) {
data->set.infilesize -= data->state.resume_from; data->state.infilesize -= data->state.resume_from;
if(data->set.infilesize <= 0) { if(data->state.infilesize <= 0) {
infof(data, "File already completely uploaded\n"); infof(data, "File already completely uploaded\n");
/* no data to transfer */ /* no data to transfer */
@ -3382,13 +3382,13 @@ static CURLcode ftp_done(struct connectdata *conn, CURLcode status,
use checking further */ use checking further */
; ;
else if(data->set.upload) { else if(data->set.upload) {
if((-1 != data->set.infilesize) && if((-1 != data->state.infilesize) &&
(data->set.infilesize != *ftp->bytecountp) && (data->state.infilesize != *ftp->bytecountp) &&
!data->set.crlf && !data->set.crlf &&
(ftp->transfer == FTPTRANSFER_BODY)) { (ftp->transfer == FTPTRANSFER_BODY)) {
failf(data, "Uploaded unaligned file size (%" CURL_FORMAT_CURL_OFF_T failf(data, "Uploaded unaligned file size (%" CURL_FORMAT_CURL_OFF_T
" out of %" CURL_FORMAT_CURL_OFF_T " bytes)", " out of %" CURL_FORMAT_CURL_OFF_T " bytes)",
*ftp->bytecountp, data->set.infilesize); *ftp->bytecountp, data->state.infilesize);
result = CURLE_PARTIAL_FILE; result = CURLE_PARTIAL_FILE;
} }
} }

View File

@ -405,8 +405,8 @@ static CURLcode http_perhapsrewind(struct connectdata *conn)
expectsend = (curl_off_t)strlen(data->set.postfields); expectsend = (curl_off_t)strlen(data->set.postfields);
break; break;
case HTTPREQ_PUT: case HTTPREQ_PUT:
if(data->set.infilesize != -1) if(data->state.infilesize != -1)
expectsend = data->set.infilesize; expectsend = data->state.infilesize;
break; break;
case HTTPREQ_POST_FORM: case HTTPREQ_POST_FORM:
expectsend = http->postsize; expectsend = http->postsize;
@ -1885,7 +1885,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
else { else {
if((conn->handler->protocol&PROTO_FAMILY_HTTP) && if((conn->handler->protocol&PROTO_FAMILY_HTTP) &&
data->set.upload && data->set.upload &&
(data->set.infilesize == -1)) { (data->state.infilesize == -1)) {
if(conn->bits.authneg) if(conn->bits.authneg)
/* don't enable chunked during auth neg */ /* 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 */ /* now, decrease the size of the read */
if(data->set.infilesize>0) { if(data->state.infilesize>0) {
data->set.infilesize -= data->state.resume_from; data->state.infilesize -= data->state.resume_from;
if(data->set.infilesize <= 0) { if(data->state.infilesize <= 0) {
failf(data, "File already completely uploaded"); failf(data, "File already completely uploaded");
return CURLE_PARTIAL_FILE; return CURLE_PARTIAL_FILE;
} }
@ -2162,13 +2162,13 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
conn->allocptr.rangeline = conn->allocptr.rangeline =
aprintf("Content-Range: bytes 0-%" CURL_FORMAT_CURL_OFF_T aprintf("Content-Range: bytes 0-%" CURL_FORMAT_CURL_OFF_T
"/%" CURL_FORMAT_CURL_OFF_T "\r\n", "/%" 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) { else if(data->state.resume_from) {
/* This is because "resume" was selected */ /* This is because "resume" was selected */
curl_off_t total_expected_size= curl_off_t total_expected_size=
data->state.resume_from + data->set.infilesize; data->state.resume_from + data->state.infilesize;
conn->allocptr.rangeline = conn->allocptr.rangeline =
aprintf("Content-Range: bytes %s%" CURL_FORMAT_CURL_OFF_T aprintf("Content-Range: bytes %s%" CURL_FORMAT_CURL_OFF_T
"/%" CURL_FORMAT_CURL_OFF_T "\r\n", "/%" CURL_FORMAT_CURL_OFF_T "\r\n",
@ -2180,7 +2180,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
append total size */ append total size */
conn->allocptr.rangeline = conn->allocptr.rangeline =
aprintf("Content-Range: bytes %s/%" CURL_FORMAT_CURL_OFF_T "\r\n", 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) if(!conn->allocptr.rangeline)
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
@ -2455,7 +2455,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
if(conn->bits.authneg) if(conn->bits.authneg)
postsize = 0; postsize = 0;
else else
postsize = data->set.infilesize; postsize = data->state.infilesize;
if((postsize != -1) && !data->req.upload_chunky && if((postsize != -1) && !data->req.upload_chunky &&
!Curl_checkheaders(conn, "Content-Length:")) { !Curl_checkheaders(conn, "Content-Length:")) {

View File

@ -775,7 +775,7 @@ static CURLcode imap_perform_append(struct connectdata *conn)
} }
/* Check we know the size of the upload */ /* 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"); failf(conn->data, "Cannot APPEND with unknown input file size\n");
return CURLE_UPLOAD_FAILED; return CURLE_UPLOAD_FAILED;
} }
@ -787,7 +787,7 @@ static CURLcode imap_perform_append(struct connectdata *conn)
/* Send the APPEND command */ /* Send the APPEND command */
result = imap_sendf(conn, "APPEND %s (\\Seen) {%" CURL_FORMAT_CURL_OFF_T "}", 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); Curl_safefree(mailbox);
@ -1618,7 +1618,7 @@ static CURLcode imap_state_append_resp(struct connectdata *conn, int imapcode,
} }
else { else {
/* Set the progress upload size */ /* Set the progress upload size */
Curl_pgrsSetUploadSize(data, data->set.infilesize); Curl_pgrsSetUploadSize(data, data->state.infilesize);
/* IMAP upload */ /* IMAP upload */
Curl_setup_transfer(conn, -1, -1, FALSE, NULL, FIRSTSOCKET, NULL); Curl_setup_transfer(conn, -1, -1, FALSE, NULL, FIRSTSOCKET, NULL);

View File

@ -404,6 +404,8 @@ CURLMcode curl_multi_add_handle(CURLM *multi_handle,
/* Point to the multi's connection cache */ /* Point to the multi's connection cache */
data->state.conn_cache = multi->conn_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 /* 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 list of SessionHandle structs to try and maintain a FIFO queue so
the pipelined requests are in order. */ the pipelined requests are in order. */

View File

@ -493,7 +493,7 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
rtspreq == RTSPREQ_GET_PARAMETER) { rtspreq == RTSPREQ_GET_PARAMETER) {
if(data->set.upload) { if(data->set.upload) {
putsize = data->set.infilesize; putsize = data->state.infilesize;
data->set.httpreq = HTTPREQ_PUT; data->set.httpreq = HTTPREQ_PUT;
} }

View File

@ -583,8 +583,8 @@ static CURLcode smtp_perform_mail(struct connectdata *conn)
} }
/* Calculate the optional SIZE parameter */ /* Calculate the optional SIZE parameter */
if(conn->proto.smtpc.size_supported && conn->data->set.infilesize > 0) { if(conn->proto.smtpc.size_supported && conn->data->state.infilesize > 0) {
size = aprintf("%" CURL_FORMAT_CURL_OFF_T, data->set.infilesize); size = aprintf("%" CURL_FORMAT_CURL_OFF_T, data->state.infilesize);
if(!size) { if(!size) {
Curl_safefree(from); Curl_safefree(from);
@ -1356,7 +1356,7 @@ static CURLcode smtp_state_data_resp(struct connectdata *conn, int smtpcode,
} }
else { else {
/* Set the progress upload size */ /* Set the progress upload size */
Curl_pgrsSetUploadSize(data, data->set.infilesize); Curl_pgrsSetUploadSize(data, data->state.infilesize);
/* SMTP upload */ /* SMTP upload */
Curl_setup_transfer(conn, -1, -1, FALSE, NULL, FIRSTSOCKET, NULL); 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. */ is "no mail data". RFC-5321, sect. 4.1.1.4. */
eob = SMTP_EOB; eob = SMTP_EOB;
len = SMTP_EOB_LEN; len = SMTP_EOB_LEN;
if(smtp->trailing_crlf || !conn->data->set.infilesize) { if(smtp->trailing_crlf || !conn->data->state.infilesize) {
eob += 2; eob += 2;
len -= 2; len -= 2;
} }

View File

@ -1717,17 +1717,17 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
} }
/* now, decrease the size of the read */ /* now, decrease the size of the read */
if(data->set.infilesize > 0) { if(data->state.infilesize > 0) {
data->set.infilesize -= data->state.resume_from; data->state.infilesize -= data->state.resume_from;
data->req.size = data->set.infilesize; data->req.size = data->state.infilesize;
Curl_pgrsSetUploadSize(data, data->set.infilesize); Curl_pgrsSetUploadSize(data, data->state.infilesize);
} }
SFTP_SEEK(sshc->sftp_handle, data->state.resume_from); SFTP_SEEK(sshc->sftp_handle, data->state.resume_from);
} }
if(data->set.infilesize > 0) { if(data->state.infilesize > 0) {
data->req.size = data->set.infilesize; data->req.size = data->state.infilesize;
Curl_pgrsSetUploadSize(data, data->set.infilesize); Curl_pgrsSetUploadSize(data, data->state.infilesize);
} }
/* upload data */ /* upload data */
Curl_setup_transfer(conn, -1, -1, FALSE, NULL, FIRSTSOCKET, NULL); 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.upload) {
if(data->set.infilesize < 0) { if(data->state.infilesize < 0) {
failf(data, "SCP requires a known file size for upload"); failf(data, "SCP requires a known file size for upload");
sshc->actualcode = CURLE_UPLOAD_FAILED; sshc->actualcode = CURLE_UPLOAD_FAILED;
state(conn, SSH_SCP_CHANNEL_FREE); state(conn, SSH_SCP_CHANNEL_FREE);
@ -2278,7 +2278,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
*/ */
sshc->ssh_channel = sshc->ssh_channel =
SCP_SEND(sshc->ssh_session, sftp_scp->path, data->set.new_file_perms, SCP_SEND(sshc->ssh_session, sftp_scp->path, data->set.new_file_perms,
data->set.infilesize); data->state.infilesize);
if(!sshc->ssh_channel) { if(!sshc->ssh_channel) {
if(libssh2_session_last_errno(sshc->ssh_session) == if(libssh2_session_last_errno(sshc->ssh_session) ==
LIBSSH2_ERROR_EAGAIN) { LIBSSH2_ERROR_EAGAIN) {

View File

@ -477,8 +477,8 @@ static CURLcode tftp_send_first(tftp_state_data_t *state, tftp_event_t event)
setpacketevent(&state->spacket, TFTP_EVENT_WRQ); setpacketevent(&state->spacket, TFTP_EVENT_WRQ);
state->conn->data->req.upload_fromhere = state->conn->data->req.upload_fromhere =
(char *)state->spacket.data+4; (char *)state->spacket.data+4;
if(data->set.infilesize != -1) if(data->state.infilesize != -1)
Curl_pgrsSetUploadSize(data, data->set.infilesize); Curl_pgrsSetUploadSize(data, data->state.infilesize);
} }
else { else {
/* If we are downloading, send an RRQ */ /* 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); sbytes = 4 + strlen(filename) + strlen(mode);
/* add tsize option */ /* 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, snprintf(buf, sizeof(buf), "%" CURL_FORMAT_CURL_OFF_T,
data->set.infilesize); data->state.infilesize);
else else
strcpy(buf, "0"); /* the destination is large enough */ strcpy(buf, "0"); /* the destination is large enough */

View File

@ -926,7 +926,7 @@ static CURLcode readwrite_upload(struct SessionHandle *data,
if(!data->set.crlf) { if(!data->set.crlf) {
/* we're here only because FTP is in ASCII mode... /* we're here only because FTP is in ASCII mode...
bump infilesize for the LF we just added */ bump infilesize for the LF we just added */
data->set.infilesize++; data->state.infilesize++;
} }
} }
else else
@ -967,7 +967,7 @@ static CURLcode readwrite_upload(struct SessionHandle *data,
k->writebytecount += bytes_written; 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 */ /* we have sent all data we were supposed to */
k->upload_done = TRUE; k->upload_done = TRUE;
infof(data, "We are completely uploaded and fine\n"); infof(data, "We are completely uploaded and fine\n");

View File

@ -485,7 +485,7 @@ CURLcode Curl_init_userdefined(struct UserDefined *set)
set->convtonetwork = ZERO_NULL; set->convtonetwork = ZERO_NULL;
set->convfromutf8 = 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->postfieldsize = -1; /* unknown size */
set->maxredirs = -1; /* allow any amount by default */ 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 * If known, this should inform curl about the file size of the
* to-be-uploaded file. * to-be-uploaded file.
*/ */
data->set.infilesize = va_arg(param, long); data->set.filesize = va_arg(param, long);
break; break;
case CURLOPT_INFILESIZE_LARGE: case CURLOPT_INFILESIZE_LARGE:
/* /*
* If known, this should inform curl about the file size of the * If known, this should inform curl about the file size of the
* to-be-uploaded file. * to-be-uploaded file.
*/ */
data->set.infilesize = va_arg(param, curl_off_t); data->set.filesize = va_arg(param, curl_off_t);
break; break;
case CURLOPT_LOW_SPEED_LIMIT: case CURLOPT_LOW_SPEED_LIMIT:
/* /*
@ -4100,16 +4100,17 @@ static CURLcode setup_connection_internals(struct connectdata *conn)
{ {
const struct Curl_handler * p; const struct Curl_handler * p;
CURLcode result; CURLcode result;
struct SessionHandle *data = conn->data;
/* in some case in the multi state-machine, we go back to the CONNECT state /* 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 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 without doing a DISCONNECT or DONE in between (since the connection is
yet in place) and therefore this function needs to first make sure yet in place) and therefore this function needs to first make sure
there's no lingering previous data allocated. */ 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)); memset(&data->req, 0, sizeof(struct SingleRequest));
conn->data->req.maxdownload = -1; data->req.maxdownload = -1;
conn->socktype = SOCK_STREAM; /* most of them are TCP streams */ conn->socktype = SOCK_STREAM; /* most of them are TCP streams */

View File

@ -1306,6 +1306,8 @@ struct UrlState {
/* if true, force SSL connection retry (workaround for certain servers) */ /* if true, force SSL connection retry (workaround for certain servers) */
bool ssl_connect_retry; 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 accepttimeout; /* in milliseconds, 0 means no timeout */
long server_response_timeout; /* 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 */ 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_limit; /* bytes/second */
long low_speed_time; /* number of seconds */ long low_speed_time; /* number of seconds */
curl_off_t max_send_speed; /* high speed limit in bytes/second for upload */ curl_off_t max_send_speed; /* high speed limit in bytes/second for upload */