2222#include "ap_slotmem.h"
2323#include "heartbeat.h"
2424
25+ #include <errno.h>
26+ #include <limits.h>
27+
2528#ifndef LBM_HEARTBEAT_MAX_LASTSEEN
2629/* If we haven't seen a heartbeat in the last N seconds, don't count this IP
2730 * as allive.
@@ -61,6 +64,28 @@ typedef struct ctx_servers {
6164 apr_hash_t * servers ;
6265} ctx_servers_t ;
6366
67+ static int hb_parse_int (const char * val , int min , int max , int * result )
68+ {
69+ apr_int64_t parsed ;
70+ char * end = NULL ;
71+
72+ if (!val || !* val ) {
73+ return 0 ;
74+ }
75+
76+ errno = 0 ;
77+ parsed = apr_strtoi64 (val , & end , 10 );
78+ if (errno == ERANGE || end == val || * end != '\0' ) {
79+ return 0 ;
80+ }
81+ if (parsed < min || parsed > max ) {
82+ return 0 ;
83+ }
84+
85+ * result = (int )parsed ;
86+ return 1 ;
87+ }
88+
6489static void
6590argstr_to_table (apr_pool_t * p , char * str , apr_table_t * parms )
6691{
@@ -179,19 +204,31 @@ static apr_status_t readfile_heartbeats(const char *path, apr_hash_t *servers,
179204 argstr_to_table (pool , apr_pstrdup (pool , t ), hbt );
180205
181206 if ((val = apr_table_get (hbt , "busy" ))) {
182- server -> busy = atoi (val );
207+ int parsed ;
208+ if (hb_parse_int (val , 0 , INT_MAX , & parsed )) {
209+ server -> busy = parsed ;
210+ }
183211 }
184212
185213 if ((val = apr_table_get (hbt , "ready" ))) {
186- server -> ready = atoi (val );
214+ int parsed ;
215+ if (hb_parse_int (val , 0 , INT_MAX , & parsed )) {
216+ server -> ready = parsed ;
217+ }
187218 }
188219
189220 if ((val = apr_table_get (hbt , "lastseen" ))) {
190- server -> seen = atoi (val );
221+ int parsed ;
222+ if (hb_parse_int (val , 0 , INT_MAX , & parsed )) {
223+ server -> seen = parsed ;
224+ }
191225 }
192226
193227 if ((val = apr_table_get (hbt , "port" ))) {
194- server -> port = atoi (val );
228+ int parsed ;
229+ if (hb_parse_int (val , 1 , 65535 , & parsed )) {
230+ server -> port = parsed ;
231+ }
195232 }
196233
197234 if (server -> busy == 0 && server -> ready != 0 ) {
@@ -312,7 +349,13 @@ static proxy_worker *find_best_hb(proxy_balancer *balancer,
312349 if (PROXY_WORKER_IS_USABLE (* worker )) {
313350 server -> worker = * worker ;
314351 if (server -> seen < LBM_HEARTBEAT_MAX_LASTSEEN ) {
315- openslots += server -> ready ;
352+ apr_uint32_t ready = (apr_uint32_t )server -> ready ;
353+ if (ready > APR_UINT32_MAX - openslots ) {
354+ openslots = APR_UINT32_MAX ;
355+ }
356+ else {
357+ openslots += ready ;
358+ }
316359 APR_ARRAY_PUSH (up_servers , hb_server_t * ) = server ;
317360 }
318361 }
@@ -325,12 +368,20 @@ static proxy_worker *find_best_hb(proxy_balancer *balancer,
325368 pick = ap_random_pick (0 , openslots );
326369
327370 for (i = 0 ; i < up_servers -> nelts ; i ++ ) {
371+ apr_uint32_t upper ;
328372 server = APR_ARRAY_IDX (up_servers , i , hb_server_t * );
329- if (pick >= c && pick <= c + server -> ready ) {
373+ if ((apr_uint32_t )server -> ready > APR_UINT32_MAX - c ) {
374+ upper = APR_UINT32_MAX ;
375+ }
376+ else {
377+ upper = c + (apr_uint32_t )server -> ready ;
378+ }
379+
380+ if (pick >= c && pick <= upper ) {
330381 mycandidate = server -> worker ;
331382 }
332383
333- c += server -> ready ;
384+ c = upper ;
334385 }
335386 }
336387
0 commit comments