tool_cb_rea: limit rate unpause for -T . uploads

To avoid getting stuck in a busy-loop when nothing is read from stdin,
this function now checks the call rate and might enforce a short sleep
when called repeatedly without uploading anything. It is a crude
work-around to avoid a 100% busy CPU.

Reported-by: magisterquis on hackerone
Fixes #13174
Closes #13506
This commit is contained in:
Daniel Stenberg 2024-04-30 11:07:28 +02:00
parent 38593db4a0
commit 5f4aaf8b66
No known key found for this signature in database
GPG Key ID: 5CC908FDB71E12C2

View File

@ -36,6 +36,7 @@
#include "tool_operate.h"
#include "tool_util.h"
#include "tool_msgs.h"
#include "tool_sleep.h"
#include "memdebug.h" /* keep this as LAST include */
@ -124,8 +125,33 @@ int tool_readbusy_cb(void *clientp,
(void)ulnow; /* unused */
if(config->readbusy) {
config->readbusy = FALSE;
curl_easy_pause(per->curl, CURLPAUSE_CONT);
/* lame code to keep the rate down because the input might not deliver
anything, get paused again and come back here immediately */
static long rate = 500;
static struct timeval prev;
static curl_off_t ulprev;
if(ulprev == ulnow) {
/* it did not upload anything since last call */
struct timeval now = tvnow();
if(prev.tv_sec)
/* get a rolling average rate */
/* rate = rate - rate/4 + tvdiff(now, prev)/4; */
rate -= rate/4 - tvdiff(now, prev)/4;
prev = now;
}
else {
rate = 50;
ulprev = ulnow;
}
if(rate >= 50) {
/* keeps the looping down to 20 times per second in the crazy case */
config->readbusy = FALSE;
curl_easy_pause(per->curl, CURLPAUSE_CONT);
}
else
/* sleep half a period */
tool_go_sleep(25);
}
return per->noprogress? 0 : CURL_PROGRESSFUNC_CONTINUE;