]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
ratelimit: handle counter overflows somewhat sanely
authorLennart Poettering <lennart@poettering.net>
Thu, 20 Apr 2023 08:31:44 +0000 (10:31 +0200)
committerLennart Poettering <lennart@poettering.net>
Thu, 20 Apr 2023 11:39:06 +0000 (13:39 +0200)
An overflow here (i.e. the counter reaching 2^32 within a ratelimit time
window) is not so unlikely. Let's handle this somewhat sanely
and simply stop counting, while remaining in the "limit is hit" state until
the time window has passed.

src/basic/ratelimit.c

index a0260bfe1c42e997a91c09fd0316eec02b1d8547..5675ec2f46bfea24ab7a537641aacc7c7b645d87 100644 (file)
@@ -10,7 +10,6 @@
 
 bool ratelimit_below(RateLimit *r) {
         usec_t ts;
-        bool good = false;
 
         assert(r);
 
@@ -21,22 +20,25 @@ bool ratelimit_below(RateLimit *r) {
 
         if (r->begin <= 0 ||
             usec_sub_unsigned(ts, r->begin) > r->interval) {
-                r->begin = ts;
+                r->begin = ts;  /* Start a new time window */
+                r->num = 1;     /* Reset counter */
+                return true;
+        }
 
-                /* Reset counter */
-                r->num = 0;
-                good = true;
-        } else if (r->num < r->burst)
-                good = true;
+        if (_unlikely_(r->num == UINT_MAX))
+                return false;
 
         r->num++;
-        return good;
+        return r->num <= r->burst;
 }
 
 unsigned ratelimit_num_dropped(RateLimit *r) {
         assert(r);
 
-        return r->num > r->burst ? r->num - r->burst : 0;
+        if (r->num == UINT_MAX) /* overflow, return as special case */
+                return UINT_MAX;
+
+        return LESS_BY(r->num, r->burst);
 }
 
 usec_t ratelimit_end(const RateLimit *rl) {