From b80798c24d837d31a00d97adf567595b4b116c5e Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sat, 20 Jul 2024 17:54:44 +0200 Subject: [PATCH] getparam: make --rate accept "number of units" Do no more than 5 transfers per 15 seconds with "5/15s" or limit it to 3 transfers per 4 hours with "3/4h" etc. Previously it would always only work with a single time unit. Ref: #14242 Closes #14245 --- docs/cmdline-opts/rate.md | 4 ++++ src/tool_getparam.c | 22 ++++++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/docs/cmdline-opts/rate.md b/docs/cmdline-opts/rate.md index 49d0010b8f..6de65165d0 100644 --- a/docs/cmdline-opts/rate.md +++ b/docs/cmdline-opts/rate.md @@ -40,3 +40,7 @@ more than 1000 per second, it instead runs unrestricted. When retrying transfers, enabled with --retry, the separate retry delay logic is used and not this setting. + +Starting in version 8.10.0, you can specify number of time units in the rate +expression. Make curl do no more than 5 transfers per 15 seconds with "5/15s" +or limit it to 3 transfers per 4 hours with "3/4h". No spaces allowed. diff --git a/src/tool_getparam.c b/src/tool_getparam.c index eaa00e2068..5234502303 100644 --- a/src/tool_getparam.c +++ b/src/tool_getparam.c @@ -1244,6 +1244,20 @@ static ParameterError set_rate(struct GlobalConfig *global, if(div) { char unit = div[1]; + curl_off_t numunits; + char *endp; + + if(curlx_strtoofft(&div[1], &endp, 10, &numunits)) { + /* if it fails, there is no legit number specified */ + if(endp == &div[1]) + /* if endp did not move, accept it as a 1 */ + numunits = 1; + else + return PARAM_BAD_USE; + } + else + unit = *endp; + switch(unit) { case 's': /* per second */ numerator = 1000; @@ -1261,6 +1275,14 @@ static ParameterError set_rate(struct GlobalConfig *global, err = PARAM_BAD_USE; break; } + + if((LONG_MAX / numerator) < numunits) { + /* overflow, too large number */ + errorf(global, "too large --rate unit"); + err = PARAM_NUMBER_TOO_LARGE; + } + /* this typecast is okay based on the check above */ + numerator *= (long)numunits; } if(err)