]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
lib: let the max filesize option stop too big transfers too
authorDaniel Stenberg <daniel@haxx.se>
Sat, 23 Sep 2023 09:20:00 +0000 (11:20 +0200)
committerDaniel Stenberg <daniel@haxx.se>
Sat, 23 Sep 2023 09:20:20 +0000 (11:20 +0200)
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

13 files changed:
docs/cmdline-opts/max-filesize.d
docs/libcurl/opts/CURLOPT_MAXFILESIZE.3
docs/libcurl/opts/CURLOPT_MAXFILESIZE_LARGE.3
lib/c-hyper.c
lib/file.c
lib/ldap.c
lib/mqtt.c
lib/progress.c
lib/progress.h
lib/smb.c
lib/telnet.c
lib/tftp.c
lib/transfer.c

index ada730d92662900abf13817222008b586c5b38e6..7541a27127d709005dabae51c6a5f2dcf19c8129 100644 (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.
index f4b024047f1c8efcdf816c1c2610e9fd79bab02c..c1ff168693b6647b23a609173156452f214e05f5 100644 (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
index 7e37fca92a3d0697845682cf9f0d4943105f7fa2..c40989e7609da689dfdb296d2bcb87caff93ef5f 100644 (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
index 47dadfe4ce52e06c1bf57fa224cf34d74c45323d..c558955c9d4cbd9b815dd17af529def69c68717e 100644 (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;
 }
 
index c751e8861a99b77e4f5c5f1ca8bd0e4e0a8ad8a3..ffa9fb76d06fc1b966d1ca8a43d80a1718babe9e 100644 (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;
index 33a4dea0a8bcf24603b8ef8138a109ba53254926..239d3fbf011e27bd97e4ec8101836b810b2e935b 100644 (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)
index eb53560f9ac9d85b5b530f589f7ee65dbfb16255..5cb2d24110973946e6b861fac7ae3346f74eae81 100644 (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 */
 
index 6092b782c70d75082433515446135752de22db86..e783a9c86dfa3d2c75283462469597cd7b673a15 100644 (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;
 }
 
 /*
index 0049cd04bee77c532023694a0a19c578d8ec82de..fc39e34d200c944af3af7622518914e6f81d92a3 100644 (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);
index afcc99de245908b1e8aad45f2ac4aefb8868a943..32c5137a44f9060ba9f2e490eec20e1415b61bbd 100644 (file)
--- a/lib/smb.c
+++ b/lib/smb.c
@@ -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;
 
index 850f88c1eccb6720eeba3358aeb1ef8b294a1b90..836e255c9d6304e07412893089e10e84ac3cced4 100644 (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;
index 8ed1b887b4d217cd77d2cd68ab54a661c7597cf8..e78140d520394a960eb312b70ae930029d0e0791 100644 (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:
index d0602b8753bc097b8e71820201fabfedcb7ceda7..4c9ff0aa845add791af5f4e02d7131a9fcd27647 100644 (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 */