Hi,

HAProxy 3.0.30 was released on 2026/10/14. It added 46 new commits
after version 3.0.29.

This release is mostly made of backports of the fixes shipped in 3.2.26. It
also carries the same two important security fixes. The first one concerns
the HTTP/2 multiplexer, where a truncated PING frame could prevent the CPU
from going back to idle, and the second one the HTTP/1 parser, where a
chunked request with a too long chunk-size line could lead to the same
behavior. CVEs were requested for both.

The rest of the release fixes issues in the configuration parser, the CLI,
the stick-table key exchange over peers, maps/ACLs, the H1 and H2
multiplexers, the compression filter and several sample converters, along
with the cipher and curve restrictions of crt-list lines on AWS-LC builds of
the SSL layer. The internal random generator, whose output could otherwise be
predicted by observers, is hardened as well.

* mux-h2: A truncated PING frame could waste the CPU of spurious wakeups.

   An HTTP/2 PING frame cannot be entirely consumed until it is complete,
   and the presence of an incomplete frame is sufficient to cause a wakeup,
   preventing the CPU from going idle until the entire frame is received,
   and resulting in a 100% CPU measurement for as long as the peer keeps the
   connection open without completing the frame (or until "timeout
   http-request" expired, when one is set). The performance impact is
   moderate and depends on the ratio of such connections among all
   concurrent connections. Partial PING frames are now detected as short
   reads like the other frame types, so the tasklet goes back to sleep until
   the rest of the frame arrives. The handling of short reads was fixed in
   2.5, but PING was missed; it only became a problem in 3.1 when the
   tasklet wake-up logic changed. As a workaround on an older build, setting
   "timeout http-request" to a low value such as 1-5 seconds limits the CPU
   consumption.

* h1-htx: A too long chunk-size line waste the CPU of spurious wakeups.

  For chunked messages, when a chunk-size line was longer than the input
  buffer, the parser made no progress, waiting for the end of the line. So
  no data was consumed, the buffer was full and could not be extended: the
  same bytes were retried endlessly with no request ever processed on it,
  preventing, as for the H2 multiplexer issue, the CPU from going idle. Here
  too, the impact is moderate and depends on the ratio of such connections
  among all concurrent connections. A parsing error (HTTP 400) is now
  reported as soon as the parser determines that the line cannot possibly
  fit, using the same full-buffer detection that already exists for
  oversized headers and trailers. Reported with a fix proposal by Adam
  Crawford.

* tools: The random generator was hardened against state recovery.

  The internal random generator was consumed in pairs and its output was
  used directly, so enough of its internal state could be observed on
  moderately idle systems to predict the values it produces: the UUIDs used
  in logs and identifiers, the QUIC retry tokens, or the WebSocket keys
  HAProxy generates. An XXH64 mixing layer seeded with the boot secret is
  now applied to its output, which hides that state, for about 2% of the
  UUID throughput when single-threaded (not measurable with threads).

* cfgparse: Several configuration parsing issues were fixed.

  A backend section given extra arguments after its name (e.g. "backend b
  junk") was silently ignored when it was the last section of the file; it
  is now properly rejected with a clear message. The "email-alert" options
  now really check that a value was provided, the proxy "description"
  keyword no longer leaks the previous string when used twice, the global
  "description" allocation is checked, and "max-spread-checks" no longer
  stores an uninitialized value on a parse error. Finally, the list of
  suggested options used when one is mistyped was completed and fixed.

* cli: The help of the "del server" command was misleading.

  It stated that only dynamically added servers could be removed, while any
  server can be removed at runtime since version 2.5.

* stick-table: Oversized keys could corrupt memory when replicated to peers.

  The overhead and the stored data were not accounted for when building the
  key sent over the peers protocol, although the whole message must fit in
  one buffer. A key close to the buffer size could therefore crash the
  sender, or overwrite a few bytes past the end of the buffer: this is
  reachable by tracking a large body or by applying an expansion converter
  (b64dec, hex, ...) to a key, or more easily with binary keys, which are
  always sent fully padded. Keys are now sized against the available room:
  string keys are trimmed, and binary keys too large to fit are refused at
  configuration time with an explicit message. There is no protocol change,
  so mixed-version peers still interoperate; realistic configurations are
  unaffected. Reported with a reproducer by Dmitri Kaslov.

  A stick-table counter was also fixed: the number of trackers returned
  by "table_trackers()" no longer counts the lookup itself, in line with
  the other fetches.

* map/acl: A use-after-free could be triggered with maps and ACLs.

  When a lookup succeeded through the tree without filling the result (the
  case of ACL matches), the returned sample still pointed at data left over
  by an earlier lookup done on the same thread outside the normal path,
  e.g. by the CLI's "get map" command. If that element was then freed ("del
  map", "clear map", or the old generation purged after "commit map"), the
  next matching request read freed memory, leading to random behaviour or a
  worker crash. Configurations using both an ACL and a map loaded from a
  virtual file are concerned. The returned pattern is no longer touched when
  it is not filled.

* tcpcheck: A crash was possible with "tcp-check expect rstring".

  The rule could be evaluated while the check's input buffer was not yet
  allocated, passing a NULL buffer to the regular expression engine, which
  expects a writable one. Only builds using the libc regex were affected
  (PCRE/PCRE2 and the binary case return cleanly). Such a rule now simply
  reports no match, like the string and binary cases already did.

* listener: A stuck accept loop could trigger the watchdog.

  Listeners were woken up without checking whether "maxconn" had already
  been reached. With many thread groups, a group could dequeue listeners,
  fail to accept because another group had consumed the last slots, and
  remain stuck long enough to trip the watchdog.

* ssl: Cipher and curve restrictions of crt-list lines were ignored with
  AWS-LC.

  On AWS-LC builds, the SSL object keeps its own copy of the cipher lists
  and curves taken at creation, and switching to the certificate's SSL_CTX
  during the handshake did not refresh them. As a result, the "ciphers",
  "ciphersuites", "curves" and "ecdhe" options of a crt-list line were
  silently ignored, and a client could negotiate a cipher or a curve that
  the certificate explicitly excluded, as long as the bind line allowed
  it. These settings are now reapplied after the context switch (OpenSSL
  builds were not affected).

* muxes: Several crashes and connection-handling bugs were fixed in the H1
  and H2 multiplexers.

  A connection upgraded from HTTP/1 to HTTP/2 (via the H2 connection
  preface) is only allowed to do so on its very first request, but the check
  was defeated when the preface of a later request arrived split across
  several reads: the connection could then be switched to H2 in the middle
  of its life, dropping the end of the previous response that was still
  pending in the output buffer. The first-request condition is now checked
  reliably.

  Other fixes in this area: the reverse HTTP gateway ("rhttp@") could crash
  when an outgoing H2 connection failed, because the failure was not
  reported to the caller that then used a freed connection (an experimental
  feature); the H2 multiplexer could return a pointer to an already freed
  tasklet when a deferred shutdown was scheduled, and the H1 multiplexer
  passed an upgraded (thus no longer valid) connection to the traces when
  destroying a stream.  Also, when an error page (400, 408, 500, 501) was
  mapped to an empty file or /dev/null, the H1 multiplexer failed to release
  its embryonic stream, so the connection stayed open until the client
  timeout instead of being closed immediately.

* h3/quic: Several protocol robustness issues were fixed.

  HTTP/3 frames whose header itself was truncated are now rejected with
  H3_FRAME_ERROR, closing the connection immediately instead of leaving the
  stream to time out. A peer that resets (RESET_STREAM) its QPACK encoder or
  decoder stream is now detected as a critical-stream violation, like a
  close with FIN already was. In the QUIC transport, a STREAM frame that
  sets FIN before the already-received offset is now rejected with
  FINAL_SIZE_ERROR even when the final size is not yet known.

* flt-http-comp: The compression filter could truncate a message.

  Since the filter produces a new payload and may hold data in its own
  context, the end-of-message flag now stays cleared on the HTX message
  until the compression is really complete, instead of being visible while
  data is still buffered in the filter. Otherwise a message with no input
  left and the EOM flag set was considered complete and the remaining
  compressed data could be dropped, truncating the response.

* http-ana: "option checkcache" now returns a 502 as documented.

  When "option checkcache" blocked a response, the status returned to the
  client was still the server's original one (usually 200) instead of the
  502 bad gateway that the documentation promises and that "http-response
  deny" produces; the error files are now used as well.

* samples: Several converters and fetches returned wrong results.

  Time converters ("ms_ltime", "ms_utime", "us_ltime", "us_utime") applied their
  offset in the wrong unit, "http_date()" did not zero-pad the sub-second part
  ("23 ms" printed as ".23", same as "23 us"), the JWT part queries failed
  without a path, "quic_enabled()" and "req.ssl_ec_ext" failed instead of
  returning false, "res.cook_cnt()" miscounted Set-Cookie attributes, TCP-mode
  fetches exposed the ":method"/":path" pseudo-headers, and "language" skipped
  values after a truncated q-factor. All were fixed.

* spoe/stconn: A few internal robustness fixes.

  A SPOE agent configuration file that defines no "spoe-message" section
  corrupted the agent's message list during parsing, which could break the
  agent's messages; the list is now spliced correctly. Streams caught in the
  middle of a connection retry could crash the process while being dumped by
  "show threads", the watchdog or "warn-blocked-traffic-after"; endpoints
  are now replaced instead of being briefly detached, so an observer can
  never see a stream without endpoint.

* doc: The documentation was corrected on several points.

  The "url_ip" and "url_port" fetches are now documented as failing when the
  authority part contains a host name rather than an address. The "hex2i"
  converter is documented as failing (returning nothing) on unparsable input
  instead of returning zero. "option checkcache" now mentions that responses
  carrying neither a validator nor freshness information are not examined
  and pass unfiltered. The diagnostic mode section explains that some
  diagnostic messages interact with "zero-warning" mode (and thus must only
  be used interactively).

Thanks everyone for your help on this release.


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
   Q&A from devs    : https://github.com/orgs/haproxy/discussions
   Sources          : https://www.haproxy.org/download/3.0/src/
   Git repository   : https://git.haproxy.org/git/haproxy-3.0.git/
   Git Web browsing : https://git.haproxy.org/?p=haproxy-3.0.git
   Changelog        : https://www.haproxy.org/download/3.0/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


---
Complete changelog :
Amaury Denoyelle (4):
      BUG/MINOR: server: fix "del server" description
      BUG/MINOR: mux_quic: extend FINAL_SIZE_ERROR detection on stream
      BUG/MINOR: h3: reject frames with truncated header
      BUG/MINOR: h3: reject RS/SS for QPACK uni streams

Christopher Faulet (8):
      BUG/MEDIUM: flt-http-comp: Block HTX_FL_EOM flag till the end of 
compression
      BUG/MINOR: flt-http-comp: Rely on htx_set_eom() to restore EOM flag
      BUG/MINOR: spoe: Fix the message list splice with an empty list
      BUG/MEDIUM: mux-h1: also release the embryonic stream when the error is 
empty
      BUG/MINOR: http-fetch: don't report pseudo-headers in TCP mode
      BUG/MEDIUM: mux-h1: only accept the H2 preface on the first request
      REGTESTS: http-messaging: Fix http_fail_cnt_body to succeed with small 
timeouts
      BUG/MAJOR: h1-htx: report an error on a too long chunk-size line

Frederic Lecaille (2):
      BUG/MEDIUM: ssl: crt-list ciphers ignored with AWS-LC
      BUG/MEDIUM: ssl: crt-list curves ignored with AWS-LC

Lukas Tribus (1):
      MINOR: doc: elaborate on diagnostic mode behavior

Olivier Houchard (1):
      BUG/MEDIUM: listener: Consider maxconn before waking listeners

William Lallemand (1):
      REGTEST: ssl: require OpenSSL 1.1.1 for crt-list ciphersuites tests

Willy Tarreau (29):
      BUG/MEDIUM: tools: insert an XXH64 layer on the PRNG output
      MINOR: stconn: prefer to replace endpoints rather than detaching them
      MINOR: stick-table: provide a function to estimate on-wire data size
      MINOR: stick-table: calculate the on-wire size of each key
      BUG/MEDIUM: stick-table: restrict key sizes to what fits in a buffer
      BUG/MEDIUM: pattern: don't dereference static_pattern's data when not 
filling it
      BUG/MINOR: http: do not consume the delimiter of a truncated q-factor
      BUG/MINOR: sample: apply the ms_/us_ time offsets in the input unit
      BUG/MINOR: sample: zero-pad the fractional part emitted by http_date()
      BUG/MINOR: sample: make quic_enabled() always succeed
      BUG/MINOR: http-ana: return a 502 when checkcache blocks a response
      BUG/MINOR: stick-table: do not count the lookup itself in table_trackers()
      BUG/MINOR: payload: always report a boolean from req.ssl_ec_ext
      BUG/MINOR: http-fetch: do not count Set-Cookie attributes as cookies
      BUG/MEDIUM: tcpcheck: do not run a regex on an unallocated buffer
      BUG/MINOR: sample: return the decoded JWT part when no path is given
      DOC: config: mention other responses not blocked by option checkcache
      DOC: config: fix doc for hex2i() converter on unparsable input
      DOC: config: mention that url_ip and url_port fail when passed a name
      BUG/MINOR: cfgparse-global: add missing gotos to error label in 
max-spread-checks
      BUG/MINOR: cfgparse-global: add missing calloc() check for the global 
description
      BUG/MINOR: cfgparse-listen: release the previous description of the proxy
      BUG/MINOR: cfgparse-listen: fix the argument checked by "email-alert"
      BUG/MINOR: cfgparse-listen: properly reject extra args in a backend 
section
      BUG/MINOR: cfgparse-listen: complete the list of options for the 
suggestions
      BUG/MEDIUM: mux-h2: don't return a freed tasklet from h2_deferred_shut()
      BUG/MEDIUM: mux-h1: don't pass an upgraded connection to traces in 
h1s_destroy()
      BUG/MEDIUM: mux-h2: report a dead rhttp connection in h2_wake()
      BUG/MAJOR: mux-h2: properly handle short reads on PING frames

--
Christopher Faulet



Reply via email to