svn commit: r1935935 - httpd/httpd/trunk/modules/proxy/balancers
[email protected] Mon, 06 Jul 2026 11:51:32 -0000
| Newsgroups | gmane.comp.apache.cvs |
|---|---|
| Message-ID | <178333869221.419591.18427628335172446179@svn03-he-fi> |
Author: jorton
Date: Mon Jul 6 11:51:31 2026
New Revision: 1935935
Log:
* modules/proxy/balancers/mod_lbmethod_heartbeat.c (hb_parse_int):
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
Modified:
httpd/httpd/trunk/modules/proxy/balancers/mod_lbmethod_heartbeat.c
Modified: httpd/httpd/trunk/modules/proxy/balancers/mod_lbmethod_heartbeat.c
==============================================================================
--- httpd/httpd/trunk/modules/proxy/balancers/mod_lbmethod_heartbeat.c Mon Jul 6 11:37:03 2026 (r1935934)
+++ httpd/httpd/trunk/modules/proxy/balancers/mod_lbmethod_heartbeat.c Mon Jul 6 11:51:31 2026 (r1935935)
@@ -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(
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_
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_
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;
}
}