Skip to content

mod_proxy_balancer: test coverage for #628 (strict balancer-manager numeric parsing) - #782

Open
notroj wants to merge 4 commits into
apache:trunkfrom
notroj:pr628-testing
Open

notroj wants to merge 4 commits into
apache:trunkfrom
notroj:pr628-testing

Conversation

@notroj

@notroj notroj commented Oct 1, 2026

Copy link
Copy Markdown
Collaborator

Test coverage for #628, which replaces atoi()/atof() in the balancer-manager
parameter handling with range-checked parsing. The branch is a new pyhttpd
test that fails on trunk, followed by the two commits from #628 applied as-is,
after which it passes.

Analysis by @claude:

Evaluation. All 14 atoi()/atof() sites in
balancer_process_balancer_worker() are replaced with apr_strtoi64()/strtod()
wrappers rejecting trailing garbage, ERANGE and out-of-range values. Static
helpers, no MMN impact, minimal; 2.4.x has identical code so it backports cleanly.

The semantic fix is more than "hardening": ap_proxy_set_wstatus() treats any
nonzero as set, so atoi("junk") == 0 used to clear a worker flag and "2"
used to set one. Garbage silently mutated state; it is now ignored.

Worth noting on the PR, none blocking:

  • strtod("nan") still passes balancer_parse_lbfactor() — NaN compares false
    against both bounds, so (int)NaN is UB. Pre-existing with atof(), but the
    PR claims strictness and leaves this open ("inf" is rejected correctly).
  • Boundary nuance: 100.004 was accepted before (int-truncated to 10000) and is
    now rejected (10000.4 > 10000). Harmless; range-checking the truncated value
    would be exactly equivalent.
  • Rejections are silent (no log) — pre-existing style.

Proof. test/modules/proxy/test_07_balancer_manager.py drives the manager's
real path (POST + Referer + pinned nonce, state read back from the ?xml=1
view). Case 001 is a positive control, since the handler silently drops
parameters on any nonce/Referer problem.

Before (3 failed, 30 passed):

w_status_D=2 was accepted as 'set': ['Init', 'Dis']
w_status_D=junk cleared the flag: ['Init', 'Ok']
w_lf=1.5junk was applied: {'http://127.0.0.1:5002': (['Init','Ok'], '1.50'),
                           'http://localhost:5002':  (['Init','Ok'], '1.00')}

After both #628 commits cherry-picked unchanged: 33 passed, no regressions.

Two gotchas the test documents: recalc_factors() pins a single member's load
factor to 100, so w_lf is only observable with two members; and a second
member on the same host:port is shared with the first worker, so it must differ
in hostname.

🤖 Generated with Claude Code

notroj and others added 4 commits October 2, 2026 10:21
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
GitHub: PR apache#628
  the request with a single recv() as before.
  (TCPFaker._process): Use it.

* test/modules/proxy/test_05_uwsgi.py (_UWSGIFaker._read_request): Read
  the whole uwsgi packet as framed by its header; a single recv() returns
  only the first 4096 bytes on Windows, failing the length check.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
(cherry picked from commit a2e5a2c)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants