Hi,

HAProxy 2.4.29 was released on 2025/04/22. It added 67 new commits
after version 2.4.28.

This version catches up with the last 5 months of fixes, corresponding to
what was merged in 2.6 since 2.6.20. Again, there's nothing really
important but a lot of small stuff:

  - The H1 multiplexer was only able to handle timeouts if the client or
    server timeouts were defined, depending on the side. So, it was possible
    to ignore client-fin/server-fin and http-keep-alive/http-request
    timeouts.

  - The way to deal with too many headers in received H2. The maximum
    number of headers allowed in HEADERS frames on sending path was lower
    than on receiving path. This could lead to report sending errors while
    the message was accepted. It could be confusing. In addition, unlike
    H1, the number of headers must be limited when H2 messages are sent
    to comply to limitation imposed by the protocol. This limit was
    increased to support headers rewriting without issue.

  - On the H2 multiplexer, on server side, it was possible to send
    RST_STREAM frame for streams with unassigned ID, so before the
    formatting of the HEADERS frame, because the session was aborted during
    the connection stage. It was an issue if this happened before the H2
    PREFACE was sent because this prevent the servers to recognize it as a
    H2 connection, leading to an early connection closure. We now take care
    to not emit RST_STREAM frame in that case.

  - Four issues with the L7 retries were fixed. First, the server status was
    not adjusted at each retry, while it should be. Only the last connection
    attempt was considered. Then, the buffer used to save the request to be
    able to perform a L7 retry was released to early in some rare cases and
    the request could be lost. It is of course unexpected and this could
    lead to crash. The request state was not properly reset on L7 retry. The
    request channel flag stating some data were sent was not reset on
    retry. This could lead to consider a subsequent connection error as a L7
    error while the request was never sent. In that case too, the request
    could be lost, leading to crash. Finally, the L7 retries could be
    ignored if a server abort was detected during the request forwarding
    when the request was already in DONE state. In that case, the server
    abort must be handled on the response analysis side to be able to
    properly handle the L7 retries.

  - The reason was missing in H2 responses forwarded to H1 clients while it
    was stated in the configuration manual that HAProxy should add one that
    matched the status code. It is now fixed.

  - HAPROXY_CLI and HAPROXY_MASTER_CLI could exposed the internal sockpairs
    which should be only used for the master CLI. These internal sockpairs
    are now always hidden.

  - The SIGINT signal could be missed by HAProxy when it was started in
    background in a subshell. It is the root cause of some unexpected
    timeouts with Vtest scripts. To fix the issue, the default signal
    handler is registered for the SIGINT signal during init.

  - A weird issue was fixed about the epoll poller. Over the last two years,
    there were few reports about immediate closes spuriously happening on
    connections where network captures proved that the server had not closed
    at all (and sometimes even received the request and responded to it
    after HAProxy had closed). The logs shown that a successful connection
    was immediately reported on error after the request was sent. After
    investigations, it appeared that a EPOLLUP, or eventually a EPOLLRDHUP,
    can be reported by epool_wait() during the connect() but in
    sock_conn_check(), the connect() reports a success. So the connection
    was validated but the HUP was handled on the first receive and an error
    was reported. So, to workaround the issue, we have decided to remove
    FD_POLL_HUP flag on the FD during the connection establishment if
    FD_POLL_ERR is not reported too in sock_conn_check(). This way, the call
    to connect() is able to validate or reject the connection. At the end,
    if the HUP or RDHUP flags were valid, either connect() would report the
    error itself, or the next recv() would return 0 confirming the closure
    that the poller tried to report. EPOLL_RDHUP is only an optimization to
    save a syscall anyway, and this pattern is so rare that nobody will ever
    notice the extra call to recv(). Please note that at least one reporter
    confirmed that using poll() instead of epoll() also addressed the
    problem, so that can also be a temporary workaround for those
    discovering the problem without the ability to immediately upgrade.

  - The expiration date for the task responsible for cleaning up the server
    resolution status when outdated info were inherited from the state file
    was fixed. "hold.timeout" was initially used. But is was not accurate,
    especially because it could be set to a high value or 0. Now the
    expiration date is based on the resolver "resolve" and "retry"
    timeouts. In addition, when a resolver was woken up to process DNS
    resolutions, it was possible to trigger an infinite loop on the
    resolver's wait list because delayed resolutions were always reinserted
    at the end of this list. This led the watchdog to kill the process. By
    re-inserting them in front of the list fixed the issue.

  - an API issue in the applets could have resulted in some shutdown or
    error conditions to be missed in the future, so as a prevention it
    was fixed. Turns out, after fixing this, it uncovered a bug in the
    CLI's "_getsocks" handler that was causing an infinite loop during
    reloads, and another one in the SPOE applet where the appled would
    never shut down (neither appeared in a released version), and these
    bug were also fixed.

  - reloads that transfer listening sockets to the new worker process could
    make the older worker consume a lot of CPU for no apparent reason for
    the time it remained present. The cause was that these FDs were
    registered in epoll and when a new connection arrived to the new
    process, the old one would also be notified without being able to
    unregister it since already closed (well-known epoll pitfall). Now
    these FDs are properly unregistered after being transfered so it's
    possible that some users with long-running old processes will observe
    a lower CPU usage on these old processes.

  - a BUG_ON() could be triggered when using filters with no http_payload
    callback.

  - a bug in htx_xfer_blks() could result in occasionally transfering more
    blocks than requested on 32-bit platforms.

  - some TLSv1.3 signature algorithms were not recognized by the
    ClientHello parser which was written before TLSv1.3. The ones that
    were not correctly supported were based on RSA-PSS and would have
    resulted in presenting a possibly wrong certificate when both RSA and
    ECDSA ones were present for the same SNI.

  - disabling the send-proxy-v2 feature on a "server" line after some fields
    had been enabled in the defaults section would result in an attempt to
    send a PROXY-v1 line because the presence of any field was tested to
    decide to send the PROXY header.
  
  - a use-after-free condition was occasionally possible in Lua applets
    handling CLI keywords, causing random crashes. It was apparently
    difficult to trigger and did apparently not happen before 3.0.

  - SPOE applets could be woken in loops during stopping, thus eating a lot
    of CPU until the process stopped.
    
  - usesrc clientip would accidentally include the client's port in the
    hash calculation, resulting in a very low connection reuse ratio.

  - leading and trailing spaces are now properly trimmed from h2 header
    values. It had been observed that some rare clients keep the space
    after the comma when splitting "cookie" values, causing errors between
    haproxy and servers, so we can reasonably expect that this would
    happen with h3 too if the same clients support both protocols.

  - stick-tables could learn entries from peers with an expiration date
    further in the future than what their own expire time permits, causing
    entries resulting from a temporary misconfiguration to be very
    difficult to evict from a cluster (e.g. mistakenly write "24d" instead
    of "24h" and entries persist for 3 weeks even across reloads). Now the
    entries' expiration date will be capped to the stick table's setting.

  - the regsub converter, used to perform regex-based substitutions, would
    check the remaining room in the buffer against the initially available
    size for each replaced pattern instead of checking it against the
    remaining size. This was reported by Aleandro Prudenzano of Doyensec
    and Edoardo Geraci of Codean Labs, and was assigned CVE-2025-32464.
    The risk is quite low since such configs are quite unlikely and in the
    rare cases they will happen, the replacement will involve static
    contents, thus essentially a risk of crash.

  - a few issues on the peers section parser and config consistency checker
    possibly causing issues or even a segfault.

  - a few minor memory leaks were found in error paths (auth, _getsock)

  - FCGI would always force the status to 302 when seeing a Location
    header, possibly overwriting another status code.

  - a pending close from the server could be forwarded to the client
    despite a pending tcp-response content evaluation.

Given that 2.4 is in critical fixes status, I'd suggest 2.4 users to have
a look at it in case they estimate that they might be affected by one of
the issues fixed above, and possibly plan for an update. In any case,
please remember to at least update before reporting an issue. But so far,
no need to immediately jump on this one if what you have works well for
you.

Please find the usual URLs below :
   Site index       : https://www.haproxy.org/
   Documentation    : https://docs.haproxy.org/
   Wiki             : https://github.com/haproxy/wiki/wiki
   Discourse        : https://discourse.haproxy.org/
   Slack channel    : https://slack.haproxy.org/
   Issue tracker    : https://github.com/haproxy/haproxy/issues
   Sources          : https://www.haproxy.org/download/2.4/src/
   Git repository   : https://git.haproxy.org/git/haproxy-2.4.git/
   Git Web browsing : https://git.haproxy.org/?p=haproxy-2.4.git
   Changelog        : https://www.haproxy.org/download/2.4/src/CHANGELOG
   Dataplane API    : 
https://github.com/haproxytech/dataplaneapi/releases/latest
   Pending bugs     : https://www.haproxy.org/l/pending-bugs
   Reviewed bugs    : https://www.haproxy.org/l/reviewed-bugs
   Code reports     : https://www.haproxy.org/l/code-reports
   Latest builds    : https://www.haproxy.org/l/dev-packages

Willy
---
Complete changelog :
Amaury Denoyelle (3):
      BUG/MINOR: backend: do not overwrite srv dst address on reuse
      BUG/MINOR: h1: do not forward h2c upgrade header token
      BUG/MINOR: h2: reject extended connect for h2c protocol

Aurelien DARRAGON (8):
      DOC: lua: fix yield-dependent methods expected contexts
      BUG/MEDIUM: pattern: prevent uninitialized reads in pat_match_{str,beg}
      BUG/MINOR: stktable: fix big-endian compatiblity in smp_to_stkey()
      DOC: management: rename some last occurences from domain "dns" to 
"resolvers"
      BUG/MINOR: cfgparse/peers: fix inconsistent check for missing peer server
      BUG/MINOR: cfgparse/peers: properly handle ignored local peer case
      BUG/MEDIUM: hlua/cli: fix cli applet UAF in hlua_applet_wakeup()
      BUG/MINOR: hlua: fix invalid errmsg use in hlua_init()

Christopher Faulet (24):
      BUG/MEDIUM: resolvers: Insert a non-executed resulution in front of the 
wait list
      BUG/MEDIUM: mux-h2: Don't send RST_STREAM frame for streams with no ID
      BUG/MINOR: http_ana: Report -1 for %Tr for invalid response only
      DOC: config: Slightly improve the %Tr documentation
      BUG/MINOR: http-ana: Adjust the server status before the L7 retries
      BUG/MEDIUM: mux-h2: Increase max number of headers when encoding HEADERS 
frames
      BUG/MEDIUM: mux-h2: Check the number of headers in HEADERS frame after 
decoding
      BUG/MEDIUM: http-ana: Don't release too early the L7 buffer
      BUG/MEDIUM: sock: Remove FD_POLL_HUP during connect() if FD_POLL_ERR is 
not set
      BUG/MEDIUM: http-ana: Reset request flag about data sent to perform a L7 
retry
      BUG/MINOR: h1-htx: Use default reason if not set when formatting the 
response
      BUG/MINOR: server-state: Fix expiration date of srvrq_check tasks
      BUG/MEDIUM: mux-h1: Fix how timeouts are applied on H1 connections
      BUG/MINOR: spoe: Check the shared waiting queue to shut applets during 
stopping
      BUG/MINOR: spoe: Allow applet creation when closing the last one during 
stopping
      BUG/MEDIUM: spoe: Don't wakeup idle applets in loop during stopping
      REGTESTS: Fix truncated.vtc to send 0-CRLF
      BUG/MINOR: cli: Wait for the last ACK when FDs are xferred from the old 
worker
      BUG/MEDIUM: filters: Handle filters registered on data with no payload 
callback
      BUG/MINOR: fcgi: Don't set the status to 302 if it is already set
      BUG/MINOR: tcp-rules: Don't forward close during tcp-response content 
rules eval
      BUG/MINOR: cli: Fix memory leak on error for _getsocks command
      BUG/MINOR: cli: Fix a possible infinite loop in _getsocks()
      BUG/MINOR: stats-json: Define JSON_INT_MAX as a signed integer

Dragan Dosen (1):
      BUG/MINOR: server: fix the "server-template" prefix memory leak

Emeric Brun (2):
      BUG/MINOR: peers: fix expire learned from a peer not converted from ms to 
ticks
      BUG/MEDIUM: peers: prevent learning expiration too far in futur from 
unsync node

Ilia Shipitsin (1):
      BUG/MINOR: namespace: handle a possible strdup() failure

Lukas Tribus (1):
      DOC: option redispatch should mention persist options

Nathan Wehrman (1):
      DOC: config: correct the table for option tcplog

Olivier Houchard (1):
      TESTS: Fix build for filltab25.c

Valentine Krasnobaeva (6):
      BUG/MINOR: cli: don't show sockpairs in HAPROXY_CLI and HAPROXY_MASTER_CLI
      BUG/MINOR: signal: register default handler for SIGINT in signal_init()
      BUG/MINOR: ssl: put ssl_sock_load_ca under SSL_NO_GENERATE_CERTIFICATES
      BUG/MINOR: cfgparse: fix NULL ptr dereference in cfg_parse_peers
      BUG/MEIDUM: startup: return to initial cwd only after 
check_config_validity()
      BUG/MINOR: log: fix gcc warn about truncating NUL terminator while init 
char arrays

William Lallemand (5):
      BUG/MINOR: ssl: can't load a separated key file with openssl > 3.0
      BUG/MEDIUM: ssl: chosing correct certificate using RSA-PSS with TLSv1.3
      BUG/MEDIUM: htx: wrong count computation in htx_xfer_blks()
      DOC: htx: clarify <mark> parameter for htx_xfer_blks()
      TESTS: ist: fix wrong array size

Willy Tarreau (14):
      BUG/MEDIUM: checks: make sure to always apply offsets to now_ms in 
expiration
      BUG/MEDIUM: mailers: make sure to always apply offsets to now_ms in 
expiration
      BUG/MINOR: peers: make sure to always apply offsets to now_ms in 
expiration
      DOC: configuration: explain quotes and spaces in conditional blocks
      BUG/MEDIUM: clock: make sure now_ms cannot be TICK_ETERNITY
      BUG/MEDIUM: fd: mark FD transferred to another process as FD_CLONED
      MINOR: cli: export cli_io_handler() to ease symbol resolution
      DOC: config: fix two missing "content" in "tcp-request" examples
      BUG/MEDIUM: sample: fix risk of overflow when replacing multiple regex 
back-refs
      BUG/MINOR: backend: do not use the source port when hashing clientip
      DOC: config: add the missing "profiling.memory" to the global kw index
      BUG/MINOR: h2: always trim leading and trailing LWS in header values
      BUG/MINOR: server: check for either proxy-protocol v1 or v2 to send hedaer
      BUILD: makefile: silence deprecated declarations when using OpenSSL

---


Reply via email to