]> git.ipfire.org Git - thirdparty/apache/httpd.git/commitdiff
* modules/proxy/balancers/mod_lbmethod_heartbeat.c (hb_parse_int):
authorJoe Orton <jorton@apache.org>
Mon, 6 Jul 2026 11:51:31 +0000 (11:51 +0000)
committerJoe Orton <jorton@apache.org>
Mon, 6 Jul 2026 11:51:31 +0000 (11:51 +0000)
  New helper replacing atoi() with safe integer parsing via
  apr_strtoi64, with range validation.
  (readfile_heartbeats): Use hb_parse_int for busy, ready,
  lastseen, and port fields.
  (find_best_hb): Add overflow-safe saturation arithmetic for
  openslots accumulation and the pick loop upper bound.

Submitted by: Sayed Kaif <metsw24 gmail.com>
Github: closes #629

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1935935 13f79535-47bb-0310-9956-ffa450edef68

modules/proxy/balancers/mod_lbmethod_heartbeat.c

index ef38cd92fa35074c1bd84c2faa1fc1560151f7bf..cf966d36f6783e4c542daa41370cebeeac49aa58 100644 (file)
@@ -61,6 +61,28 @@ typedef struct ctx_servers {
     apr_hash_t *servers;
 } ctx_servers_t;
 
+static int hb_parse_int(const char *val, int min, int max, int *result)
+{
+    apr_int64_t parsed;
+    char *end = NULL;
+
+    if (!val || !*val) {
+        return 0;
+    }
+
+    errno = 0;
+    parsed = apr_strtoi64(val, &end, 10);
+    if (errno == ERANGE || end == val || *end != '\0') {
+        return 0;
+    }
+    if (parsed < min || parsed > max) {
+        return 0;
+    }
+
+    *result = (int)parsed;
+    return 1;
+}
+
 static void
 argstr_to_table(apr_pool_t *p, char *str, apr_table_t *parms)
 {
@@ -179,19 +201,31 @@ static apr_status_t readfile_heartbeats(const char *path, apr_hash_t *servers,
             argstr_to_table(pool, apr_pstrdup(pool, t), hbt);
 
             if ((val = apr_table_get(hbt, "busy"))) {
-                server->busy = atoi(val);
+                int parsed;
+                if (hb_parse_int(val, 0, INT_MAX, &parsed)) {
+                    server->busy = parsed;
+                }
             }
 
             if ((val = apr_table_get(hbt, "ready"))) {
-                server->ready = atoi(val);
+                int parsed;
+                if (hb_parse_int(val, 0, INT_MAX, &parsed)) {
+                    server->ready = parsed;
+                }
             }
 
             if ((val = apr_table_get(hbt, "lastseen"))) {
-                server->seen = atoi(val);
+                int parsed;
+                if (hb_parse_int(val, 0, INT_MAX, &parsed)) {
+                    server->seen = parsed;
+                }
             }
 
             if ((val = apr_table_get(hbt, "port"))) {
-                server->port = atoi(val);
+                int parsed;
+                if (hb_parse_int(val, 1, 65535, &parsed)) {
+                    server->port = parsed;
+                }
             }
 
             if (server->busy == 0 && server->ready != 0) {
@@ -312,7 +346,13 @@ static proxy_worker *find_best_hb(proxy_balancer *balancer,
         if (PROXY_WORKER_IS_USABLE(*worker)) {
             server->worker = *worker;
             if (server->seen < LBM_HEARTBEAT_MAX_LASTSEEN) {
-                openslots += server->ready;
+                apr_uint32_t ready = (apr_uint32_t)server->ready;
+                if (ready > APR_UINT32_MAX - openslots) {
+                    openslots = APR_UINT32_MAX;
+                }
+                else {
+                    openslots += ready;
+                }
                 APR_ARRAY_PUSH(up_servers, hb_server_t *) = server;
             }
         }
@@ -325,12 +365,20 @@ static proxy_worker *find_best_hb(proxy_balancer *balancer,
         pick = ap_random_pick(0, openslots);
 
         for (i = 0; i < up_servers->nelts; i++) {
+            apr_uint32_t upper;
             server = APR_ARRAY_IDX(up_servers, i, hb_server_t *);
-            if (pick >= c && pick <= c + server->ready) {
+            if ((apr_uint32_t)server->ready > APR_UINT32_MAX - c) {
+                upper = APR_UINT32_MAX;
+            }
+            else {
+                upper = c + (apr_uint32_t)server->ready;
+            }
+
+            if (pick >= c && pick <= upper) {
                 mycandidate = server->worker;
             }
 
-            c += server->ready;
+            c = upper;
         }
     }