Hi,

HAProxy 3.4.3 was released on 2026/07/29. It added 96 new commits
after version 3.4.2.

This release contains one important fix and a handful of security hardening
fixes reported by Red Hat/AISLE Research and others, on top of the usual set
of bug fixes.

* ssl/ocsp: An issue about missing lock was fixed.

  The OCSP stapling callback read the cached OCSP response buffer without
  any lock, while the buffer can be freed and replaced at any moment by a
  "set ssl ocsp-response" CLI command, the ocsp-update task, or a reload. A
  concurrent update could either crash the worker (use-after-free) or leak
  freed/reused heap contents to a remote client requesting the stapled
  response. The reads are now protected by the existing OCSP tree lock. This
  was reported and fixes by Matt Suiche from Tolmo Inc.

* QUIC/H3 : Three bugs were fixed around QUIC/H3 stream shutdown and error
  handling.

  A parser desync could occur when an H3 error was detected in the middle of
  a multi-frame buffer, causing the caller to remove only part of the data
  and restart parsing at a wrong offset, which usually produced a new,
  unrelated error or an unwarranted full connection closure. A QCS instance
  could also be wrongly freed if a STOP_SENDING was still scheduled for it,
  most impactful on the backend side where a server could keep emitting data
  on a stream haproxy already considered closed. Finally, shutting down a
  stream's read side (e.g. an aborted request) did not always send a
  STOP_SENDING to the peer, so a server backend could keep sending data for
  a request haproxy no longer cared about.

* fd: A deadlock when closing file descriptors of other thread groups was
  fixed.

  Destroying a listener while holding the listener lock could deadlock when
  it needed to close an fd belonging to another thread group and another
  thread was waiting on the same listener lock. This was easier to reproduce
  with a suspend/resume loop on ABNS sockets. The fd is now closed using a
  reference-counting scheme instead of thread isolation, avoiding the
  deadlock.

* tcpcheck: The internal proxy used to parse "healthcheck" sections was not
  added to the proxies list, so its initialization was not fully finalized;
  this notably broke some arguments such as regular expressions and could
  lead to crashes because of a NULL pointer dereference at runtime.

* applet: An issue leading to a stale task expiration date was fixed.

  When an applet was waiting for a connection (e.g. the Lua Socket applet)
  and reads were re-enabled once the connection became available, this was
  usually done from the connection's context, so the applet's task
  expiration date was not refreshed. With small timeouts this could cause
  the task to appear scheduled in the past, triggering a BUG_ON() in
  sc_notify(). This was fixed by moving the changes in the applet's context.

  Related to this issue, a bug about lua cosockets was fixed. the Lua
  cosocket timeout being applied on the wrong side. It was applied to both
  the client and server sides, while it must only apply to the server side.

* stats: Two issues about the stats page, reported by Red Hat/AISLE
  Research, were fixed.

  Proxies updated through the stats page while in "stats admin" mode were
  not subject to the "stats scope" filtering, meaning a scope meant to
  restrict which proxies are visible/actionable could be silently bypassed
  on POST requests.
  Separately, POST requests to the stats interface did not validate that the
  Origin (or Referer) header matched the Host, which is now checked to
  mitigate CSRF attacks.

* cache: A leak preventing the cache from reserving rows under "Vary" was
  fixed.

  When a secondary cache entry matching a request with a "Vary" header was
  still incomplete (being written by another stream), the request was
  forwarded without reattaching its row to the available list, leaking
  it. Over a Vary-heavy workload this eventually exhausted the cache and
  prevented any further row reservation.

* ssl-gencert: A memory leak on every certificate generation was fixed.

  Two temporary buffers were not freed after generating a certificate on the
  fly, leaking memory each time a new SNI triggered certificate
  generation. This issue was reported by Red Hat/AISLE Research.

* sample/protobuf/net-helper: buffer overflows after pointer-shift
  converters, reported by Red Hat/AISLE Research and Charles Vosburgh, were
  fixed.

  Several converters (protobuf/ungrpc field extraction, eth.data, eth.src,
  ip.data, bytes(), ltrim()) move the sample's data pointer forward on
  success but did not shrink the sample's recorded buffer capacity
  accordingly. A converter chained afterwards that relies on that capacity
  (e.g. padding via memset()) could then write past the end of the buffer,
  leading to heap corruption or a worker crash. All the affected converters
  now adjust the capacity together with the pointer.

* protobuf: A nested-path validation bypass reported by Red Hat/AISLE
  Research was fixed.

  The protobuf field lookup used for the protobuf()/ungrpc() converters did
  not strictly enforce hierarchical boundaries, so a flat sibling field
  could incorrectly satisfy a nested-path lookup (e.g. matching a root-level
  field as if it were nested under a parent). The lookup was rewritten as a
  strict, non-recursive path walker that correctly bounds each nesting
  level.
  Separately, a crash because of deprecated protobuf group wire types was
  fixed. These wire types are now explicitly rejected.

* proxy/server: Some CLI commands dumping info were not protected against
  concurrent proxy/server/backend deletion.

  "show servers conn/state", "show backend" and "show errors" all loop over
  lists of proxies or servers and may yield in case of a large output; if
  the entry the dump was paused on got deleted (e.g. via dynamic
  backend/server removal) in the meantime, the worker could crash on
  restart. These commands now rely on the existing watcher mechanism,
  already used by "show stat", to survive concurrent deletion.
  Separately, the check refusing to delete a server still attached to
  streams was not exhaustive: two paths (a failed connection attempt still
  referencing the server, and cookie persistence set very early) were not
  covered by the existing counters, allowing a server to be deleted while
  still referenced. A new per-thread-group stream counter now tracks this
  reliably.

* ssl: A kTLS splicing regression and a wrongly typo'd macro were fixed.

  A wrong macro name (USE_VANILLA_OPENSSL instead of HAVE_VANILLA_OPENSSL)
  could let kTLS start splicing while data was still pending in OpenSSL's
  internal buffers, causing data not to be properly read.
  Separately, when kTLS splicing received a non-application-data record
  (e.g. a TLSv1.3 KeyUpdate), splicing failed outright instead of falling
  back to a regular recvmsg() long enough to consume the record and resume
  splicing afterwards.

* mux-h1: The case of header names were not being adjusted on some outgoing
  messages.

  When a map was configured to adjust the case of some header names for
  legacy applications, it was not applied to the low-level error messages
  generated during th request parsing. And for all other messages,
  "Sec-Websocket-Key" and "Sec-Websocket-Accept" headers, inserted by the H1
  multiplexer, were also concerned.

* http-fetch: Two crashes reachable from health-check configurations were
  fixed.

  "res.body"/"res.hdr"/... and similar response fetches assumed the
  health-check receive buffer always held an HTX message, which is only true
  for actual HTTP checks; on a plain TCP check, a hostile/misbehaving server
  could craft the first bytes of its reply to be misinterpreted as HTX
  internal fields, causing a wild read and worker crash (or leaking
  arbitrary process memory).
  Separately, "capture.req.hdr"/"capture.res.hdr" only validated the upper
  bound of their index argument, so a negative capture id was accepted at
  boot and dereferenced an out-of-bounds array entry at runtime, crashing
  the worker on the very first request.

* tools: Converter to encode URLs was fixed to avoid silent truncation.

  encode_chunk(), used among others by the url_enc converter and OCSP
  encoding, used to silently truncate its output when the destination was
  too small, which could produce a partially-encoded URL. It can now fail
  explicitly instead; the url_enc converter and OCSP code were updated
  accordingly.

* slz: Several issues were fixed in the SLZ library.

  A stream alternating many literals in the 144-255 range with cheap
  back-references could keep inflating indefinitely instead of falling
  back to a stored block, exceeding the library's documented worst-case
  output size by several percent. A new accounting mechanism now bounds
  this overhead. Practical impact on haproxy requires tune.bufsize above
  ~43 kB with the default reserve.

  Five small correctness fixes inherited from upstream libslz were also
  backported: Avoid reading up to a few bytes past the end of very short
  inputs on architectures without fast unaligned access; stop appending an
  extra, misplaced block to an already-finished deflate/gzip/zlib stream
  (which could corrupt the trailing checksum in ~2% of fuzzed streams); fix
  the Adler32 checksum accumulator sign handling on 32-bit systems
  (affecting the zlib format only); avoid an undefined-behaviour signed left
  shift when assembling input words byte by byte; and use the exact bit cost
  when deciding whether to emit the last literals of a block as a stored
  block, avoiding compressed output slightly larger than the documented
  worst case.

* peers: A heap overflow when replicating large stick-table dictionary
  entries was fixed.

  peer_prepare_updatemsg() never verified that a stick-table entry's
  dictionary value (e.g. server_key, up to ~16 kB) actually fit in the
  update message being built. Since the peers protocol is plain-text and
  unauthenticated, a rogue or compromised peer could plant an oversized
  entry that overflows the 16 kB trash buffer as soon as the victim
  replicates ("teaches") it, confirmed as a heap-buffer-overflow write. The
  function now checks the available room before encoding and fails clea nly
  if it doesn't fit. This was reported and fixes by Matt Suiche from Tolmo
  Inc.

* chunk: The code was reviewed to avoid retrieving a large trash buffer by
  mistake.

  All call sites of the trash-chunk allocation helpers were reviewed to make
  sure a large buffer is only handed out when the caller's own buffer is
  already large and genuinely needs it, preventing unexpected extra memory
  usage. Several call sites were switched to the new
  get_best_trash_chunk()/alloc_best_trash_chunk() helpers.

* resolvers: Possible conflicts between the internal backend used for the
  "default" resolvers sections and regular backends with the same name were
  fixed.

  Since a "default" resolvers section is now created automatically, a
  same-named internal TCP backend proxy also appeared, and a config using
  "default_backend default" could either fail with a confusing "mode"
  error or silently route real traffic to the internal resolvers backend.
  Resolvers no longer need to be looked up by name in the proxies index,
  so they are no longer indexed there. Fixes GitHub issue #3445.

* server-template: Duplicated entries created from a "server-template" line
  did not properly inherit several settings that are only initialized once
  for the base line by srv_settings_init().

  The <alt_proto> field, used to select an alternative protocol such as
  MPTCP, was not copied to server-template duplicates, resulting in the
  wrong protocol being selected on connect. The "check-reuse-pool" flag,
  forcefully enabled for rHTTP servers, was not propagated either, causing
  health checks to always fail on rHTTP server-template entries. And the
  QUIC transport was never set up for these duplicates at all, since it was
  only performed in _srv_parse_init(), preventing any QUIC communication on
  server-template entries with a quic4/6 address. All three settings are now
  properly duplicated/initialized in srv_settings_cpy(), or moved to a
  callback that also runs for duplicates. A related improvement makes
  parsing error messages usable for server-template lines, which used to
  show "server-template be/(null)" instead of the template's name.

* cebtree: A bug in the duplicate-key detection of the lookup shortcut was
  fixed.

  It could make a lookup return the wrong entry among a list of duplicates,
  or make the walk to the previous/next duplicate fail to find it, as soon
  as the tree was deep enough to enter the shortcut path. This affects the
  cebis_tree used since 3.3 to index server names (conf.name), where it
  could sometimes let a duplicate server name go undetected.

And, as usual, the bunch of minor fixes here and there, mainly raised during
AI-assisted code reviews. Most were never noticed:

* HTX API: Some bugs about how the HTX API was used were fixed here and
  there.

* http-act: Double-frees and a couple of state bugs on parsing errors were
  fixed.

* http-fetch/http/http-ana/http-htx: Few out-of-bounds reads and a missing
  NULL/allocation check were fixed.

* h1: The right error offset is now reported for an authority/Host mismatch
  when "accept-unsafe-violations-in-http-request" option is enabled

* http-conv: The last input character could be lost when calling url-dec
  converter, when the input buffer was full. This was fixed by failing the
  converter in that case.

* http-rules: A crash on error path when parsing "set-cookie-fmt" redirect
  rule was fixed.

* mux-h1: An extra 200ms delay was observed on some H2-to-H1 messages
  because the end of the message was not always properly detected. This case
  is now properly handled.

* sample: Two edge cases in be2hex() and bytes() were fixed.

* shctx: An issue in the shctx was fixed. This notably broke revalidation of
  cached responses whose ETag was stored beyond the first block, causing a
  full 200 response to be served instead of a 304.

* ssl: "show ssl sni -f <frontend>" command was silently falling back to the
  first proxy when the given frontend did not exist. An error is now
  reported.

* stream: Custom per-request timeouts/retries set on listeners via
  "set-timeout" and "set-retries" action are now preserved, except when the
  stream is routed to a diffent backend. The configuration manual was
  updated to document this case.

Otherwise, two changes were backported:

* htx: To avoid trouble with large buffers, it is no longer possible to
  handle HTTP headers exceeding the size of a regular buffer. It is
  mandatory to avoid interoperability issues with H2 and H3.

* ssl: tune.ssl.keyupdate-rate-limit global directive was added to mitigate
  costly TLSv1.3 KeyUpdate floods.

  Processing a TLSv1.3 KeyUpdate is CPU-expensive and there is normally
  little reason to receive many of them. This new tunable caps the number
  of KeyUpdates accepted per second (default 100, 0 disables the limit).

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.4/src/
   Git repository   : https://git.haproxy.org/git/haproxy-3.4.git/
   Git Web browsing : https://git.haproxy.org/?p=haproxy-3.4.git
   Changelog        : https://www.haproxy.org/download/3.4/src/CHANGELOG
   Dataplane API    : 
https://github.com/haproxytech/dataplaneapi/releases/latest
   OpenTelemetry    : https://github.com/haproxytech/haproxy-opentelemetry
   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 (17):
      BUG/MEDIUM: h3: fix parser desync on error with multiple frames
      BUG/MINOR: mux_quic: prevent multiple STOP_SENDING emission per stream
      BUG/MEDIUM: mux_quic: do not free QCS if STOP_SENDING to sent
      MINOR: mux_quic: use separate error code for STOP_SENDING
      BUG/MEDIUM: mux_quic: complete stream shutdown for read channel
      BUG/MINOR: quic: ignore STREAM after MUX closure on BE side
      BUG/MINOR: ssl: fix proxy lookup for show ssl sni
      DOC: fix typo in "del ssl ech" command
      DOC: remove outdated experimental mention on dynamic backends
      BUG/MEDIUM: proxy: protect "show servers ..." against server deletion
      BUG/MEDIUM: proxy: protect "show servers ..." against backend deletion
      BUG/MEDIUM: proxy: protect show backend against be deletion
      BUG/MEDIUM: proxy: protect "show errors" against backend deletion
      MINOR: server: improve parsing error for server-template
      BUG/MINOR: server: fix QUIC on server-template
      BUG/MINOR: server: duplicate server alt_proto in srv_settings_cpy()
      BUG/MINOR: server: fix check reuse-pool in srv_settings_cpy()

Christopher Faulet (24):
      BUG/MEDIUM: tcpcheck: Add proxy used for healthcheck sections in proxies 
list
      BUG/MINOR: sample: Fix a possible underflow on be2hex for large chunk size
      MINOR: chunks: Add function to get a large/regular chunk depending on a 
buffer
      BUG/MEDIUM: chunk: Review chunks usage to not retrieve a large buffer by 
error
      MINOR: htx: Add a field to save the headers data size
      MEDIUM: htx: Be sure size of headers never exceed regular buffer on update
      BUG/MINOR: stream: Fix custom timeouts initialization when setting backend
      REGTESTS: Improve script testing the set-timeout action
      BUG/MINOR: stream: Fix custom max-retries initialization when setting 
backend
      BUG/MINOR: http-conv: Make url-dec failed if no space for trailing null 
byte
      BUG/MINOR: hlua: Apply socket timeout on server side only
      BUG/MEDIUM: applet: Reenable reads in applet context if requesting a 
connection
      BUG/MINOR: mux-h1: Don't delay send if message with c-l was fully sent
      BUG/MEDIUM: net-helper: Adjust sample size capacity after pointer shift
      BUG/MEDIUM: sample: Adjust sample size capacity after pointer shift for 
bytes()
      BUG/MEDIUM: sample: Adjust sample size capacity after pointer shift for 
ltrim()
      BUG/MINOR: sample: Fix bytes() when length it greater than remaining data
      REORG: h1-htx: Move h1 headers map in h1-htx
      BUG/MEDIUM: mux-h1: Always adjust case for all outgoing headers as 
expected
      BUG/MEDIUM: http-fetch: don't parse a non-HTTP check buffer as an HTX 
message
      BUG/MEDIUM: tools: make string encoding possible to fail instead of 
truncating
      BUG/MINOR: htx: Perform raw copy for messages of same size in 
htx_copy_msg()
      BUG/MINOR: htx: Transfer HTX_FL_EOM flag on success in htx_append_msg()
      BUG/MINOR: http-rules: fix release of a failed "set-cookie-fmt" redirect 
rule

Frederic Lecaille (4):
      MINOR: haterm: add note about QUIC usage on SSL port
      BUG/MEDIUM: protobuf: adjust sample size capacity after pointer shift
      BUG/MEDIUM: protobuf: fix nested path bypass in field lookup
      REGTESTS: protobuf: add regression test for nested vs flat paths

Matt Suiche (3):
      BUG/MEDIUM: peers: check the available room before encoding dict values
      BUG/MEDIUM: sample: reject the deprecated protobuf group wire types
      BUG/MAJOR: ssl/ocsp: lock the OCSP response around reads in the stapling 
callback

Maxime Henrion (4):
      BUG/MINOR: shctx: fix shctx_row_data_get() when offset exceeds a block
      MINOR: shctx: clamp shctx_row_data_get() reads against the offset
      DOC: stats: document the per-proxy byte count fields in the CSV list
      BUG/MEDIUM: cache: reattach the row when a secondary entry is incomplete

Olivier Houchard (11):
      BUG/MEDIUM: fd: Fix a deadlock when closing other tgroups fds
      BUG/MEDIUM: stats: Ensure that Origin is valid on POSTs
      DOC: stats: Document that stats admin is vulnerable to a CSRF attack
      BUG/MEDIUM: ssl-gencert: Don't forget to free memory when done
      BUG/MEDIUM: server: Properly check for streams before deletion
      BUG/MEDIUM: ssl: Spell HAVE_VANILLA_OPENSSL correctly
      BUG/MEDIUM: ssl: Handle non-application data record while splicing
      MEDIUM: ssl: Add a way to rate-limit TLSv1.3 KeyUpdate
      DOC: ssl: Document tune.ssl.keyupdate-rate-limit
      BUG/MEDIUM: ssl: Put CO_ER_SSL_KEYUPDATE at the right place
      BUILD: ssl: Do not use SSL3_MT_KEY_UPDATE, hardcode 24 instead

Willy Tarreau (33):
      BUILD: quic: workaround a gcc bug saying "maybe used uninitialized" when 
USE_TRACE=0
      CLEANUP: traces: get rid of a few rare empty args in TRACE calls
      MINOR: compiler: add a macro to ignore all arguments
      MINOR: trace: always pretend to use args when disabled
      BUG/MINOR: trace/quic_frame: use buf, not trace_buf in chunk_frm_appendf()
      MINOR: stats: factor the proxy vs scope check into its own function
      BUG/MEDIUM: stats: subject "stats admin" accesses to "stats scope" 
filtering
      BUG/MINOR: resolvers: do not index resolvers names in the proxies
      DEBUG: fd: catch access attempts to closed FDs
      BUG/MINOR: http-htx: fix the length moved when removing a header value
      BUG/MEDIUM: http-fetch: reject a negative capture id in 
capture.{req,res}.hdr
      BUG/MINOR: http-fetch: fix a NULL channel dereference in smp_fetch_body()
      BUG/MINOR: http: fix an out-of-bounds read in http_get_host_port() on 
empty host
      BUG/MINOR: http-htx: check the trash allocation in 
http_scheme_based_normalize()
      BUG/MINOR: h1: report the right error position on authority/host mismatch
      BUG/MINOR: h2: don't use a block pointer to roll back a partial HTX 
conversion
      BUG/MINOR: h3: don't use a block pointer to roll back a partial HTX 
conversion
      BUG/MINOR: http-ana: fix a one-byte over-read in the client-side cookie 
parser
      BUG/MINOR: http-act: fix a double free of the regex on a rule parsing 
error
      BUG/MINOR: http-act: fix a double free of the map reference on a parsing 
error
      BUG/MINOR: http-act: restore the response buffer state in the early-hint 
action
      BUG/MINOR: http-act: work on a copy of the sample in del-headers-bin
      BUG/MINOR: http-act: reject a negative capture id in the capture actions
      BUG/MINOR: http-htx: check the strdup() of the "lf-string" http reply 
argument
      BUG/MINOR: slz: do not read past the end of the input around the match 
loop
      CLEANUP: slz: fix the documented worst case size of flush() and finish()
      BUG/MINOR: slz: use the exact switch cost for the last literals of a block
      BUG/MEDIUM: slz: bound the bits wasted by the 9-bit literals
      BUG/MINOR: slz: do not append a block to an already finished stream
      BUG/MINOR: slz: fix the adler32 accumulators signedness on 32-bit
      BUG/MINOR: slz: avoid undefined shifts when building the word byte by byte
      CLEANUP: slz: clarify that the size promise applies to the stream, not to 
a call
      IMPORT: cebtree: private: fix the duplicate detection in the lookup 
shortcut

--
Christopher Faulet



Reply via email to