lib: let the max filesize option stop too big transfers too

Previously it would only stop them from getting started if the size is
known to be too big then.

Update the libcurl and curl docs accordingly.

Fixes #11810
Reported-by: Elliot Killick
Assisted-by: Jay Satiro
Closes #11820
This commit is contained in:
Daniel Stenberg 2023-09-23 11:20:00 +02:00
parent 38029101e2
commit 914e49b9b7
No known key found for this signature in database
GPG Key ID: 5CC908FDB71E12C2
13 changed files with 55 additions and 15 deletions

View File

@ -18,6 +18,9 @@ A size modifier may be used. For example, Appending 'k' or 'K' counts the
number as kilobytes, 'm' or 'M' makes it megabytes, while 'g' or 'G' makes it
gigabytes. Examples: 200K, 3m and 1G. (Added in 7.58.0)
**NOTE**: The file size is not always known prior to download, and for such
files this option has no effect even if the file transfer ends up being larger
than this given limit.
**NOTE**: before curl 8.4.0, when the file size is not known prior to
download, for such files this option has no effect even if the file transfer
ends up being larger than this given limit.
Starting with curl 8.4.0, this option aborts the transfer if it reaches the
threshold during transfer.

View File

@ -41,6 +41,9 @@ transfers this option has no effect - even if the file transfer eventually
ends up being larger than this given limit.
If you want a limit above 2GB, use \fICURLOPT_MAXFILESIZE_LARGE(3)\fP.
Since 8.4.0, this option also stops ongoing transfers if they reach this
threshold.
.SH DEFAULT
None
.SH PROTOCOLS

View File

@ -40,6 +40,9 @@ returned.
The file size is not always known prior to the download start, and for such
transfers this option has no effect - even if the file transfer eventually
ends up being larger than this given limit.
Since 8.4.0, this option also stops ongoing transfers if they reach this
threshold.
.SH DEFAULT
None
.SH PROTOCOLS

View File

@ -258,7 +258,11 @@ static int hyper_body_chunk(void *userdata, const hyper_buf *chunk)
}
data->req.bytecount += len;
Curl_pgrsSetDownloadCounter(data, data->req.bytecount);
result = Curl_pgrsSetDownloadCounter(data, data->req.bytecount);
if(result) {
data->state.hresult = result;
return HYPER_ITER_BREAK;
}
return HYPER_ITER_CONTINUE;
}

View File

@ -571,7 +571,9 @@ static CURLcode file_do(struct Curl_easy *data, bool *done)
if(result)
return result;
Curl_pgrsSetDownloadCounter(data, bytecount);
result = Curl_pgrsSetDownloadCounter(data, bytecount);
if(result)
return result;
if(Curl_pgrsUpdate(data))
result = CURLE_ABORTED_BY_CALLBACK;

View File

@ -735,7 +735,9 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done)
if(result)
goto quit;
dlsize++;
Curl_pgrsSetDownloadCounter(data, dlsize);
result = Curl_pgrsSetDownloadCounter(data, dlsize);
if(result)
goto quit;
}
if(ber)

View File

@ -668,7 +668,9 @@ MQTT_SUBACK_COMING:
mq->npacket -= nread;
k->bytecount += nread;
Curl_pgrsSetDownloadCounter(data, k->bytecount);
result = Curl_pgrsSetDownloadCounter(data, k->bytecount);
if(result)
goto end;
/* if QoS is set, message contains packet id */

View File

@ -317,9 +317,16 @@ timediff_t Curl_pgrsLimitWaitTime(curl_off_t cursize,
/*
* Set the number of downloaded bytes so far.
*/
void Curl_pgrsSetDownloadCounter(struct Curl_easy *data, curl_off_t size)
CURLcode Curl_pgrsSetDownloadCounter(struct Curl_easy *data, curl_off_t size)
{
if(data->set.max_filesize && (size > data->set.max_filesize)) {
failf(data, "Exceeded the maximum allowed file size "
"(%" CURL_FORMAT_CURL_OFF_T ")",
data->set.max_filesize);
return CURLE_FILESIZE_EXCEEDED;
}
data->progress.downloaded = size;
return CURLE_OK;
}
/*

View File

@ -46,7 +46,10 @@ int Curl_pgrsDone(struct Curl_easy *data);
void Curl_pgrsStartNow(struct Curl_easy *data);
void Curl_pgrsSetDownloadSize(struct Curl_easy *data, curl_off_t size);
void Curl_pgrsSetUploadSize(struct Curl_easy *data, curl_off_t size);
void Curl_pgrsSetDownloadCounter(struct Curl_easy *data, curl_off_t size);
/* It is fine to not check the return code if 'size' is set to 0 */
CURLcode Curl_pgrsSetDownloadCounter(struct Curl_easy *data, curl_off_t size);
void Curl_pgrsSetUploadCounter(struct Curl_easy *data, curl_off_t size);
void Curl_ratelimit(struct Curl_easy *data, struct curltime now);
int Curl_pgrsUpdate(struct Curl_easy *data);

View File

@ -1049,7 +1049,12 @@ static CURLcode smb_request_state(struct Curl_easy *data, bool *done)
}
data->req.bytecount += len;
data->req.offset += len;
Curl_pgrsSetDownloadCounter(data, data->req.bytecount);
result = Curl_pgrsSetDownloadCounter(data, data->req.bytecount);
if(result) {
req->result = result;
next_state = SMB_CLOSE;
break;
}
next_state = (len < MAX_PAYLOAD_SIZE) ? SMB_CLOSE : SMB_DOWNLOAD;
break;

View File

@ -1570,8 +1570,9 @@ static CURLcode telnet_do(struct Curl_easy *data, bool *done)
}
total_dl += nread;
Curl_pgrsSetDownloadCounter(data, total_dl);
result = telrcv(data, (unsigned char *)buf, nread);
result = Curl_pgrsSetDownloadCounter(data, total_dl);
if(!result)
result = telrcv(data, (unsigned char *)buf, nread);
if(result) {
keepon = FALSE;
break;

View File

@ -1141,12 +1141,15 @@ static CURLcode tftp_receive_packet(struct Curl_easy *data)
result = Curl_client_write(data, CLIENTWRITE_BODY,
(char *)state->rpacket.data + 4,
state->rbytes-4);
if(!result) {
k->bytecount += state->rbytes-4;
result = Curl_pgrsSetDownloadCounter(data,
(curl_off_t) k->bytecount);
}
if(result) {
tftp_state_machine(state, TFTP_EVENT_ERROR);
return result;
}
k->bytecount += state->rbytes-4;
Curl_pgrsSetDownloadCounter(data, (curl_off_t) k->bytecount);
}
break;
case TFTP_EVENT_ERROR:

View File

@ -671,7 +671,9 @@ static CURLcode readwrite_data(struct Curl_easy *data,
k->bytecount += nread;
max_recv -= nread;
Curl_pgrsSetDownloadCounter(data, k->bytecount);
result = Curl_pgrsSetDownloadCounter(data, k->bytecount);
if(result)
goto out;
if(!k->chunk && (nread || k->badheader || is_empty_data)) {
/* If this is chunky transfer, it was already written */