From 169d185ae17a6672cc1faf47f426c39c0e525a80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Chlup?= Date: Thu, 12 Feb 2026 17:30:34 +0100 Subject: [PATCH 1/3] Improve parsing of time for certain parameters --- native/mod_manager/mod_manager.c | 34 ++++++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/native/mod_manager/mod_manager.c b/native/mod_manager/mod_manager.c index 1f524df1..597fca98 100644 --- a/native/mod_manager/mod_manager.c +++ b/native/mod_manager/mod_manager.c @@ -41,6 +41,10 @@ #define STYPBIG "SYNTAX: Type field too big" #define SALIBIG "SYNTAX: Alias field too big" #define SCONBIG "SYNTAX: Context field too big" +#define SFLUBAD "SYNTAX: Flushwait field has bad value" +#define SPNGBAD "SYNTAX: Ping field has bad value" +#define STTLBAD "SYNTAX: TTL field has bad value" +#define STIMBAD "SYNTAX: Timeout field has bad value" #define SALIBAD "SYNTAX: Alias without Context" #define SCONBAD "SYNTAX: Context without Alias" #define NOCONAL "SYNTAX: No Context and Alias in APP command" @@ -1098,6 +1102,8 @@ static char *process_config_balancer(const request_rec *r, const char *key, char static char *process_config_node(const char *key, char *val, nodeinfo_t *nodeinfo, int *errtype) { + apr_interval_time_t time; + if (strcasecmp(key, "JVMRoute") == 0) { if (strlen(val) >= sizeof(nodeinfo->mess.JVMRoute)) { *errtype = TYPESYNTAX; @@ -1159,19 +1165,39 @@ static char *process_config_node(const char *key, char *val, nodeinfo_t *nodeinf } } if (strcasecmp(key, "flushwait") == 0) { - nodeinfo->mess.flushwait = atoi(val) * 1000; + if (ap_timeout_parameter_parse(val, &time, "ms") != APR_SUCCESS) { + *errtype = TYPESYNTAX; + return SFLUBAD; + } else { + nodeinfo->mess.flushwait = time; + } } if (strcasecmp(key, "ping") == 0) { - nodeinfo->mess.ping = apr_time_from_sec(atoi(val)); + if (ap_timeout_parameter_parse(val, &time, "s") != APR_SUCCESS) { + *errtype = TYPESYNTAX; + return SPNGBAD; + } else { + nodeinfo->mess.ping = time; + } } if (strcasecmp(key, "smax") == 0) { nodeinfo->mess.smax = atoi(val); } if (strcasecmp(key, "ttl") == 0) { - nodeinfo->mess.ttl = apr_time_from_sec(atoi(val)); + if (ap_timeout_parameter_parse(val, &time, "s") != APR_SUCCESS) { + *errtype = TYPESYNTAX; + return STTLBAD; + } else { + nodeinfo->mess.ttl = time; + } } if (strcasecmp(key, "Timeout") == 0) { - nodeinfo->mess.timeout = apr_time_from_sec(atoi(val)); + if (ap_timeout_parameter_parse(val, &time, "s") != APR_SUCCESS) { + *errtype = TYPESYNTAX; + return STIMBAD; + } else { + nodeinfo->mess.timeout = time; + } } return NULL; From 175bc9eefb728409017717f35183334b8c52b1bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Chlup?= Date: Thu, 12 Feb 2026 17:32:46 +0100 Subject: [PATCH 2/3] Tweak encoding processing --- native/mod_manager/mod_manager.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/native/mod_manager/mod_manager.c b/native/mod_manager/mod_manager.c index 597fca98..6eb93910 100644 --- a/native/mod_manager/mod_manager.c +++ b/native/mod_manager/mod_manager.c @@ -2616,7 +2616,9 @@ static apr_status_t decodeenc(char **ptr) val = 0; while (NULL != ptr[val]) { if (ptr[val][0] == '\0') { - return APR_SUCCESS; /* special case for no characters */ + /* special case for no characters */ + val++; + continue; } for (i = 0, j = 0; ptr[val][i] != '\0'; i++, j++) { /* decode it if not already done */ From c2d524e22484d8b2e9e034fc8bf9382a95245d3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Chlup?= Date: Mon, 16 Feb 2026 11:16:36 +0100 Subject: [PATCH 3/3] test-perl: Add tests for CONFIG temporal parameters --- .../t/mod_proxy_cluster/config_time_params.t | 115 ++++++++++++++++++ 1 file changed, 115 insertions(+) create mode 100644 test-perl/t/mod_proxy_cluster/config_time_params.t diff --git a/test-perl/t/mod_proxy_cluster/config_time_params.t b/test-perl/t/mod_proxy_cluster/config_time_params.t new file mode 100644 index 00000000..c392f326 --- /dev/null +++ b/test-perl/t/mod_proxy_cluster/config_time_params.t @@ -0,0 +1,115 @@ +# Before 'make install' is performed this script should be runnable with +# 'make test'. After 'make install' it should work as 'perl Apache-ModProxyCluster.t' +######################### + +use strict; +use warnings; + +use Apache::Test; +use Apache::TestUtil; +use Apache::TestConfig; +use Apache::TestRequest 'GET'; +use ModProxyCluster; + +plan tests => 30; + +Apache::TestRequest::module("mpc_test_host"); +my $hostport = Apache::TestRequest::hostport(); + +my $url = "http://$hostport/"; +my $resp = GET $url; + +ok $resp->is_success; + +################################ +### Check the default values ### +################################ +$resp = CMD 'CONFIG', $url, ( JVMRoute => 'test-time' ); + +ok $resp->is_success; +ok ($resp->content eq ""); + +$resp = CMD 'DUMP', $url; + +ok $resp->is_success; +my %p = parse_response 'DUMP', $resp->content; + +ok (@{$p{Nodes}} == 1); +my $node = shift @{$p{Nodes}}; +ok ($node->{JVMRoute} eq 'test-time'); + +ok($node->{flushwait} == 10); +ok($node->{ttl} == 60); +ok($node->{ping} == 10); +ok($node->{timeout} == 0); + +# Clean after yourself +CMD 'REMOVE-APP', "$url/*", ( JVMRoute => 'test-time' ); + +################################## +### Check custom valid values ### +################################## +$resp = CMD 'CONFIG', $url, ( JVMRoute => 'test-time', flushwait => 25, ttl => 30, ping => 65, timeout => 10 ); + +ok $resp->is_success; +ok ($resp->content eq ""); + +$resp = CMD 'DUMP', $url; + +ok $resp->is_success; +%p = parse_response 'DUMP', $resp->content; + +$node = shift @{$p{Nodes}}; +ok ($node->{JVMRoute} eq 'test-time'); + +ok($node->{flushwait} == 25); +ok($node->{ttl} == 30); +ok($node->{ping} == 65); +ok($node->{timeout} == 10); + +# Clean after yourself +CMD 'REMOVE-APP', "$url/*", ( JVMRoute => 'test-time' ); +sleep 25; # to have enough time for the removal + +################################# +### Check some invalid values ### +################################# +$resp = CMD 'CONFIG', $url, ( JVMRoute => 'test-time', flushwait => -30 ); +ok $resp->is_error; + +$resp = CMD 'DUMP', $url; +ok $resp->is_success; +%p = parse_response 'DUMP', $resp->content; +ok (@{$p{Nodes}} == 0); + +$resp = CMD 'CONFIG', $url, ( JVMRoute => 'test-time', ttl => -1000 ); +ok $resp->is_error; + +$resp = CMD 'DUMP', $url; +ok $resp->is_success; +%p = parse_response 'DUMP', $resp->content; +ok (@{$p{Nodes}} == 0); + +$resp = CMD 'CONFIG', $url, ( JVMRoute => 'test-time', ping => -300 ); +ok $resp->is_error; + +$resp = CMD 'DUMP', $url; +ok $resp->is_success; +%p = parse_response 'DUMP', $resp->content; +ok (@{$p{Nodes}} == 0); + +$resp = CMD 'CONFIG', $url, ( JVMRoute => 'test-time', timeout => -10 ); +ok $resp->is_error; + +$resp = CMD 'DUMP', $url; +ok $resp->is_success; +%p = parse_response 'DUMP', $resp->content; +ok (@{$p{Nodes}} == 0); + + +END { + # Clean after yourself even with failure + CMD 'REMOVE-APP', "$url/*", ( JVMRoute => 'test-time' ); + sleep 25; +} +