Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package haproxy for openSUSE:Factory checked in at 2026-06-22 17:42:48 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/haproxy (Old) and /work/SRC/openSUSE:Factory/.haproxy.new.1956 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "haproxy" Mon Jun 22 17:42:48 2026 rev:187 rq:1361069 version:3.4.0+git31.fc300e9f2 Changes: -------- --- /work/SRC/openSUSE:Factory/haproxy/haproxy.changes 2026-06-10 15:50:28.206047000 +0200 +++ /work/SRC/openSUSE:Factory/.haproxy.new.1956/haproxy.changes 2026-06-22 17:43:18.334918732 +0200 @@ -1,0 +2,137 @@ +Mon Jun 22 10:08:53 UTC 2026 - [email protected] + +- Update to version 3.4.0+git31.fc300e9f2: + * BUG/MEDIUM: mux-fcgi: fix uint16_t overflow in drl += drp (bsc#1268557) VUL-0: CVE-2026-55203 + * BUG/MEDIUM: http-act: Make a copy of the sample expr in (set/add)-headers-bin + * BUG/MEDIUM: mux_quic: fix freeze transfer after QCS rxbuf realign + * BUG/MINOR: hpack-tbl: add missing NULL check after hpack_dht_defrag() (bsc#1268558) VUL-0: CVE-2026-55204 + * BUG/MEDIUM: ssl: Don't free the early data buffer too early + * BUG/MINOR: quic: fix rxbuf settings on backend side + * BUG/MINOR: mux-h1: Properly resolve file path for 'h1-case-adjust-file' + * BUG/MEDIUM: http-ana: Don't ignore L7 retry errors + * BUG/MINOR: http-ana: Remove a debugging memset on redirect + * BUG/MINOR: server: fix add server with consistent hash balancing + * BUG/MEDIUM: h3: Properly handle PUSH_PROMISE on backend connections + * BUG/MINOR: cpu-topo: use ha_diag_notice() to report thread creations + * MINOR: errors: add ha_diag_notice() to report diag-level notifications + * BUG/MEDIUM: ktls: defer enabling TLS ULP on a socket until connected + * BUG/MEDIUM: acme: stuck ACME task when authz is already "valid" + * BUG/MINOR: quic: fix Initial length value in sent packets + * REGTESTS: Fix log matching in healthcheck-section.vtc + * BUG/MEDIUM: checks: Dequeue checks on purge + * BUG/MINOR: acl: report "ACL" not "map" in ACL ID lookup failures + * CLEANUP: sessions: simplify the sess_priv_conns pool name + * BUG/MEDIUM: xprt_qmux: implement ->get_ssl_sock_ctx() to get the SSL laye + * BUG/MEDIUM: threads: Fiw build when using no thread + * BUG/MEDIUM: regex: initialize the match array earlier during boot + * REGTESTS: checks: Add script for external healthchecks + * BUG/MINOR: tcpcheck: Override external check if healthcheck section is set + * BUG/MINOR: mux_quic: do not interrupt recv on error/incomplete data + * BUG/MEDIUM: mux_quic: prevent risk of infinite loop on recv + * BUG/MEDIUM: server/checks: Support healtcheck keyword on default-server lines + * MINOR: check: Don't dump buffers state in check traces for external checks + * BUG/MEDIUM: check: Ignore small-buffer option when starting an external check + * BUG/MEDIUM: check: Skip tcpcheck post-config for external checks + +------------------------------------------------------------------- +Mon Jun 22 09:39:24 UTC 2026 - [email protected] + +- Update otel to version ce86d09: + * DOC: otel: dropped source-artifact counts from the prose + * DOC: otel: reconciled the docs with the current filter code + * BUILD: otel: added a .gitignore for build and scratch artifacts + * MINOR: otel: added an 'exception' span directive + * MINOR: otel: extended the location check to otel-group actions + * MINOR: otel: warned when a condition is unusable at the scope's event + * MINOR: otel: warned when a fetch is unusable at the scope's event + * MINOR: otel: set the fetch-validity bits, and fixed on-client-session-start + * DOC: otel: documented the flush, instruments and scopes CLI commands + * DOC: otel: documented HTTP/TCP proxy modes and the TCP event set + * MINOR: otel: test: sampled the system CPU during the speed test + * DOC: otel: described the metric instrument types in 'instrument' + * DOC: otel: documented the export-pipeline status in 'flt-otel status' + * MINOR: otel: showed export-pipeline state in 'flt-otel status' + * MINOR: otel: added a TCP-mode test configuration + * DOC: otel: documented TCP-mode tracing and byte counting + * MINOR: otel: extended tracing to TCP-mode proxies + * DOC: otel: documented periodic gauges via the on-idle-timeout event + * MINOR: otel: warned about documented limitations at config load + * MINOR: otel: added an 'otel.context' sample fetch + * MINOR: otel: logged a reused span as a reference, not referenceless + * CLEANUP: otel: referenced the span keyword by enum in the ID check + * CLEANUP: otel: initialized argc in the config-line check + * BUG/MINOR: otel: cast the name byte to uint8_t for the ctype check + * MINOR: otel: skipped a missing extract context with a debug note + * Revert "BUG/MINOR: otel: did not hard-fail a stream that initiates a trace" + * MINOR: otel: added a 'scopes' CLI introspection command + * MINOR: otel: added an 'instruments' CLI introspection command + * MINOR: otel: added a 'flush' CLI command to force an export + * BUG/MINOR: otel: did not reject the documented 'no log' directive + * DOC: otel: aligned the error-mode help text with the CLI + * MINOR: otel: gated the group action on flag_used like the scope dispatch + * DOC: otel: documented group_data smp_val as reserved for fetch validation + * DOC: otel: documented smp_val_fe/be as reserved for fetch validation + * BUG/MINOR: otel: rejected HTTP header injection at on-http-end-request + * DOC: otel: aligned event docs with code, documented inject limits + * DOC: otel: documented keyword multiplicity and closed reference gaps + * BUG/MINOR: otel: rejected a duplicate 'idle-timeout' in a scope + * CLEANUP: otel: reformatted the FLT_OTEL_KW_MAP macro definition + * CLEANUP: otel: unified the keyword-to-code table lookups + * MINOR: otel: allowed several conditional status lines per span + * MINOR: otel: test: defaulted the path to the sibling haproxy executable + * CLEANUP: otel: unified the out-of-memory error message + * CLEANUP: otel: made the debug output consistent and unambiguous + * CLEANUP: otel: deduplicated the filter error handlers + * BUG/MINOR: otel: corrected the debug-only diagnostics + * BUG/MINOR: otel: did not hard-fail a stream that initiates a trace + * BUG/MINOR: otel: corrected the log-record body error handling + * BUG/MINOR: otel: did not leak injected pairs when the injection failed + * BUG/MEDIUM: otel: drove the idle timer from the stream task expiry + * BUG/MINOR: otel: did not format a NULL detail in the var registration + * BUG/MINOR: otel: made the bounds qsort comparator transitive + * BUG/MINOR: otel: rejected duplicate span 'parent' and 'kind' arguments + * BUG/MINOR: otel: hardened the group action error paths + * CLEANUP: otel: refreshed stale function doc comments + * DOC: otel: corrected stale facts across the documentation + * BUG/MINOR: otel: hardened the string buffer handling + * BUG/MINOR: otel: did not dereference NULL when removing headers + * MINOR: otel: improved the CLI status output and command access + * MINOR: otel: gated the 'unset-var' keyword on a condition + * MINOR: otel: gated the 'set-var-ctx' keyword on a condition + * CLEANUP: otel: centralized the 'if'/'unless' condition detection + * MINOR: otel: gated the 'log-record' keyword on a condition + * MINOR: otel: gated the 'instrument' keyword on a condition + * BUG/MINOR: otel: skipped set_status() for the 'ignore' status code + * DOC: otel: clarified that only the 'error' status carries a description + * MINOR: otel: guarded the deinit callback against a NULL configuration + * DOC: otel: reconciled the documentation with the parser + * BUG/MINOR: otel: allowed any valid address in the 'log' keyword + * MINOR: otel: gated the 'set-var' keyword on a condition + * MINOR: otel: gated the 'baggage' keyword on a condition + * MINOR: otel: gated the 'status' keyword on a condition + * MINOR: otel: gated the 'event' keyword on a condition + * MINOR: otel: gated the 'attribute' keyword on a condition + * MINOR: otel: added a shared helper for an optional if/unless condition + * DOC: otel: documented that telemetry delivery is best-effort + * MINOR: otel: added attributes to the standalone 'link' keyword + * MINOR: otel: added a per-event timestamp to the 'event' keyword + * BUG/MINOR: otel: kept the span timestamp when a 'time' sample is empty + * MINOR: otel: added the 'kind' keyword to set the span kind + * MINOR: otel: started the SDK once via an atomic claim, not the HTX flag + * BUG/MINOR: otel: read the attach rate limit from one snapshot + * MINOR: otel: traced spans and contexts as the runtime context is freed + * BUG/MINOR: otel: allowed a span status without a description + * CLEANUP: otel: unified config keyword synopsis placeholders + * DOC: otel: documented which callback raises each scope event + * MINOR: otel: added the on-http-tarpit-request scope event + * BUG/MEDIUM: otel: stopped the idle timer from clobbering analyse_exp + * CLEANUP: otel: named the link target a reference instead of a span + * MINOR: otel: added set-var/set-var-ctx/unset-var scope directives + * MINOR: otel: always compiled vars.o and added by-name variable helpers + * MINOR: otel: added an 'otel-stop' keyword to end tracing for a connection + * CLEANUP: otel: factored the scope ACL test into flt_otel_cond_pass() + * DOC: otel: corrected the stale flt_otel_is_disabled() description + * MINOR: otel: test: added log-record 'time' coverage to the full test + * MINOR: otel: recorded the wall-clock as the log record's observed time + +------------------------------------------------------------------- Old: ---- haproxy-3.4.0+git0.64a335366.tar.gz haproxy-opentelemetry-849ecaf.tar.gz New: ---- haproxy-3.4.0+git31.fc300e9f2.tar.gz haproxy-opentelemetry-ce86d09.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ haproxy.spec ++++++ --- /var/tmp/diff_new_pack.rxVASD/_old 2026-06-22 17:43:19.934974783 +0200 +++ /var/tmp/diff_new_pack.rxVASD/_new 2026-06-22 17:43:19.946975204 +0200 @@ -44,10 +44,10 @@ %bcond_with opentelemetry Name: haproxy -Version: 3.4.0+git0.64a335366 +Version: 3.4.0+git31.fc300e9f2 Release: 0 %if %{with opentelemetry} -%global otel_revision 849ecaf +%global otel_revision ce86d09 %global otel_subdir haproxy-opentelemetry-%{otel_revision} %global otel_additional_source -a9 %endif ++++++ _service ++++++ --- /var/tmp/diff_new_pack.rxVASD/_old 2026-06-22 17:43:20.030978146 +0200 +++ /var/tmp/diff_new_pack.rxVASD/_new 2026-06-22 17:43:20.034978287 +0200 @@ -1,28 +1,23 @@ <services> <service name="tar_scm" mode="manual"> - <param name="url">https://github.com/haproxytech/haproxy-opentelemetry.git/</param> - <param name="scm">git</param> - <param name="filename">haproxy-opentelemetry</param> - <param name="versionformat">%h</param> - <param name="revision">main</param> - <param name="changesgenerate">enable</param> - </service> - <service name="tar_scm" mode="manual"> <param name="url">http://git.haproxy.org/git/haproxy-3.4.git/</param> <param name="scm">git</param> <param name="filename">haproxy</param> <param name="versionformat">@PARENT_TAG@+git@TAG_OFFSET@.%h</param> - <param name="revision">v3.4.0</param> + <param name="revision">master</param> <param name="versionrewrite-pattern">v(.*)</param> <param name="versionrewrite-replacement">\1</param> - <!-- - <param name="revision">master</param> - <param name="versionrewrite-pattern">v(.*)-(dev.*)</param> - <param name="versionrewrite-replacement">\1~\2</param> - --> <param name="changesgenerate">enable</param> </service> + <service name="tar_scm" mode="manual"> + <param name="url">https://github.com/haproxytech/haproxy-opentelemetry.git/</param> + <param name="scm">git</param> + <param name="filename">haproxy-opentelemetry</param> + <param name="versionformat">%h</param> + <param name="revision">main</param> + <param name="changesgenerate">enable</param> + </service> <service name="recompress" mode="manual"> <param name="file">haproxy*.tar</param> <param name="compression">gz</param> ++++++ _servicedata ++++++ --- /var/tmp/diff_new_pack.rxVASD/_old 2026-06-22 17:43:20.062979267 +0200 +++ /var/tmp/diff_new_pack.rxVASD/_new 2026-06-22 17:43:20.066979408 +0200 @@ -1,11 +1,12 @@ <servicedata> <service name="tar_scm"> <param name="url">http://git.haproxy.org/git/haproxy-3.4.git/</param> - <param name="changesrevision">64a335366dc1bb5431e28a75e3a22e4226ac9b8f</param> + <param name="changesrevision">fc300e9f2ce352516341503e8bc62f4c0b429627</param> </service> <service name="tar_scm"> <param name="url">https://github.com/haproxytech/haproxy-opentelemetry.git/</param> - <param name="changesrevision">849ecaf450a03c17a8a405c4d8c3148fea9cb305</param> + <param name="changesrevision">ce86d09e9d9b41d73212f5081cf7f4f74b6ff28d</param> </service> </servicedata> +(No newline at EOF) ++++++ haproxy-3.4.0+git0.64a335366.tar.gz -> haproxy-3.4.0+git31.fc300e9f2.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-3.4.0+git0.64a335366/include/haproxy/errors.h new/haproxy-3.4.0+git31.fc300e9f2/include/haproxy/errors.h --- old/haproxy-3.4.0+git0.64a335366/include/haproxy/errors.h 2026-06-03 15:01:51.000000000 +0200 +++ new/haproxy-3.4.0+git31.fc300e9f2/include/haproxy/errors.h 2026-06-18 09:19:41.000000000 +0200 @@ -101,6 +101,8 @@ * These functions are reserved to output diagnostics on MODE_DIAG. * Use the underscore variants only if MODE_DIAG has already been checked. */ +void ha_diag_notice(const char *fmt, ...) + __attribute__ ((format(printf, 1 ,2))); void _ha_vdiag_warning(const char *fmt, va_list argp); void _ha_diag_warning(const char *fmt, ...); void ha_diag_warning(const char *fmt, ...) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-3.4.0+git0.64a335366/include/haproxy/ssl_sock-t.h new/haproxy-3.4.0+git31.fc300e9f2/include/haproxy/ssl_sock-t.h --- old/haproxy-3.4.0+git0.64a335366/include/haproxy/ssl_sock-t.h 2026-06-03 15:01:51.000000000 +0200 +++ new/haproxy-3.4.0+git31.fc300e9f2/include/haproxy/ssl_sock-t.h 2026-06-18 09:19:41.000000000 +0200 @@ -255,6 +255,7 @@ #define SSL_SOCK_F_KTLS_RECV (1 << 3) /* kTLS receive is configure on that socket */ #define SSL_SOCK_F_CTRL_SEND (1 << 4) /* We want to send a kTLS control message for that socket */ #define SSL_SOCK_F_HAS_ALPN (1 << 5) /* An ALPN has been negotiated */ +#define SSL_SOCK_F_KTLS_ULP (1 << 6) /* TLS ULP is enabled on that socket */ struct ssl_sock_ctx { struct connection *conn; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-3.4.0+git0.64a335366/reg-tests/checks/extcheck.vtc new/haproxy-3.4.0+git31.fc300e9f2/reg-tests/checks/extcheck.vtc --- old/haproxy-3.4.0+git0.64a335366/reg-tests/checks/extcheck.vtc 1970-01-01 01:00:00.000000000 +0100 +++ new/haproxy-3.4.0+git31.fc300e9f2/reg-tests/checks/extcheck.vtc 2026-06-18 09:19:41.000000000 +0200 @@ -0,0 +1,77 @@ +varnishtest "Health-checks: some external check tests" +feature ignore_unknown_macro +#REGTEST_TYPE=slow + +server s1 { + rxreq + expect req.method == GET + expect req.url == /health + expect req.proto == HTTP/1.1 + txresp +} -start + +syslog S1 -level notice { + recv + expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Health check for server be[0-9]/srv succeeded, reason: External check passed, code: 0" + recv + expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Health check for server be[0-9]/srv succeeded, reason: External check passed, code: 0" +} -start + +syslog S2 -level notice { + recv + expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Health check for server be[0-9]/srv succeeded.*code: 200" +} -start + +haproxy h1 -conf { + global + .if feature(THREAD) + thread-groups 1 + .endif + external-check + insecure-fork-wanted + + healthcheck http-health + type httpchk + http-check send meth GET uri /health ver HTTP/1.1 + + defaults + mode http + timeout client "${HAPROXY_TEST_TIMEOUT-5s}" + timeout server "${HAPROXY_TEST_TIMEOUT-5s}" + timeout connect "${HAPROXY_TEST_TIMEOUT-5s}" + option log-health-checks + + backend be1 + log ${S1_addr}:${S1_port} len 2048 local0 + option external-check + external-check command /bin/true + server srv ${h1_li1_addr}:${h1_li1_port} check inter 100ms rise 1 fall 1 + + defaults + mode http + timeout client "${HAPROXY_TEST_TIMEOUT-5s}" + timeout server "${HAPROXY_TEST_TIMEOUT-5s}" + timeout connect "${HAPROXY_TEST_TIMEOUT-5s}" + option external-check + external-check command /bin/true + option log-health-checks + + backend be2 + log ${S1_addr}:${S1_port} len 2048 local0 + server srv ${h1_li1_addr}:${h1_li1_port} check inter 100ms rise 1 fall 1 + + backend be3 + log ${S2_addr}:${S2_port} len 2048 local0 + option external-check + external-check command /bin/true + server srv ${s1_addr}:${s1_port} check inter 100ms rise 1 fall 1 healthcheck http-health + + listen li1 + mode http + bind "fd@${li1}" + http-request return status 200 + +} -start + +syslog S1 -wait +syslog S2 -wait diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-3.4.0+git0.64a335366/reg-tests/checks/healthcheck-section.vtc new/haproxy-3.4.0+git31.fc300e9f2/reg-tests/checks/healthcheck-section.vtc --- old/haproxy-3.4.0+git0.64a335366/reg-tests/checks/healthcheck-section.vtc 2026-06-03 15:01:51.000000000 +0200 +++ new/haproxy-3.4.0+git31.fc300e9f2/reg-tests/checks/healthcheck-section.vtc 2026-06-18 09:19:41.000000000 +0200 @@ -144,7 +144,7 @@ recv expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Health check for server be2/srv[0-9]+ succeeded" recv - expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Health check for server be2/srv[0-9] succeeded" + expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Health check for server be2/srv[0-9]+ succeeded" recv expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Health check for server be2/srv[0-9]+ succeeded" recv diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-3.4.0+git0.64a335366/src/acme.c new/haproxy-3.4.0+git31.fc300e9f2/src/acme.c --- old/haproxy-3.4.0+git0.64a335366/src/acme.c 2026-06-03 15:01:51.000000000 +0200 +++ new/haproxy-3.4.0+git31.fc300e9f2/src/acme.c 2026-06-18 09:19:41.000000000 +0200 @@ -2028,6 +2028,7 @@ /* if auth is already valid we need to skip solving challenges */ if (strncasecmp("valid", trash.area, trash.data) == 0) { auth->validated = 1; + auth->ready = ctx->cfg->cond_ready; /* no challenge needed, satisfy all readiness conditions */ goto out; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-3.4.0+git0.64a335366/src/check.c new/haproxy-3.4.0+git31.fc300e9f2/src/check.c --- old/haproxy-3.4.0+git0.64a335366/src/check.c 2026-06-03 15:01:51.000000000 +0200 +++ new/haproxy-3.4.0+git31.fc300e9f2/src/check.c 2026-06-18 09:19:41.000000000 +0200 @@ -232,6 +232,9 @@ chunk_appendf(&trace_buf, " sc=%p(0x%08x)", check->sc, check->sc->flags); } + if (check->type != PR_O2_TCPCHK_CHK) + return; + if (mask & CHK_EV_TCPCHK) { const char *type; @@ -1404,7 +1407,20 @@ check_release_buf(check, &check->bi); check_release_buf(check, &check->bo); - _HA_ATOMIC_DEC(&th_ctx->running_checks); + + if (unlikely(LIST_INLIST(&check->check_queue))) { + /* + * If that check is still queued, and we're about to + * purge it, then remove it from the queue, as it is + * about to be freed. + * This can happen if a server is deleted while the check + * is queued. + */ + if (check->state & CHK_ST_PURGE) + LIST_DEL_INIT(&check->check_queue); + } + else + _HA_ATOMIC_DEC(&th_ctx->running_checks); _HA_ATOMIC_DEC(&th_ctx->active_checks); check->state &= ~(CHK_ST_INPROGRESS|CHK_ST_IN_ALLOC|CHK_ST_OUT_ALLOC); check->state &= ~CHK_ST_READY; @@ -1563,6 +1579,7 @@ ha_free(&check->tcpcheck); } + LIST_DEL_INIT(&check->check_queue); pool_free(pool_head_uniqueid, istptr(check->unique_id)); check->unique_id = IST_NULL; ha_free(&check->pool_conn_name); @@ -1682,7 +1699,7 @@ for (px = proxies_list; px; px = px->next) { for (s = px->srv; s; s = s->next) { if ((px->options2 & PR_O2_USE_SBUF_CHECK) && - (s->check.tcpcheck->rs->flags & TCPCHK_RULES_MAY_USE_SBUF)) + (s->check.tcpcheck->rs && s->check.tcpcheck->rs->flags & TCPCHK_RULES_MAY_USE_SBUF)) s->check.state |= CHK_ST_USE_SMALL_BUFF; if (s->check.state & CHK_ST_CONFIGURED) { @@ -1799,6 +1816,9 @@ if (!srv->do_check || !(srv->proxy->cap & PR_CAP_BE)) goto out; + if (!srv->check.type && (srv->proxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) + goto init; + check_type = srv->check.tcpcheck->rs->flags & TCPCHK_RULES_PROTO_CHK; if (!(srv->flags & SRV_F_DYNAMIC)) { @@ -1939,7 +1959,7 @@ } init: - err = init_check(&srv->check, srv->proxy->options2 & PR_O2_CHK_ANY); + err = init_check(&srv->check, srv->check.type ? srv->check.type : (srv->proxy->options2 & PR_O2_CHK_ANY)); if (err) { ha_alert("config: %s '%s': unable to init check for server '%s' (%s).\n", proxy_type_str(srv->proxy), srv->proxy->id, srv->id, err); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-3.4.0+git0.64a335366/src/cpu_topo.c new/haproxy-3.4.0+git31.fc300e9f2/src/cpu_topo.c --- old/haproxy-3.4.0+git0.64a335366/src/cpu_topo.c 2026-06-03 15:01:51.000000000 +0200 +++ new/haproxy-3.4.0+git31.fc300e9f2/src/cpu_topo.c 2026-06-18 09:19:41.000000000 +0200 @@ -1279,7 +1279,7 @@ if (tmin <= thr_count && thr_count < tmax) tmax = thr_count; - ha_diag_warning("Multi-socket cpu detected, automatically binding on active CPUs of '%d' (%u active cpu(s))\n", first_node_id, cpu_count); + ha_diag_notice("Multi-socket cpu detected, automatically binding on active CPUs of '%d' (%u active cpu(s))\n", first_node_id, cpu_count); if (!global.nbthread) global.nbthread = tmax; @@ -1586,9 +1586,9 @@ } if (global.nbthread) - ha_diag_warning("Created %d threads split into %d groups\n", global.nbthread, global.nbtgroups); + ha_diag_notice("Created %d threads split into %d groups\n", global.nbthread, global.nbtgroups); else - ha_diag_warning("Could not determine any CPU cluster\n"); + ha_diag_notice("Could not determine any CPU cluster\n"); return 0; } @@ -1684,9 +1684,9 @@ } if (global.nbthread) - ha_diag_warning("Created %d threads split into %d groups\n", global.nbthread, global.nbtgroups); + ha_diag_notice("Created %d threads split into %d groups\n", global.nbthread, global.nbtgroups); else - ha_diag_warning("Could not determine any CPU cluster\n"); + ha_diag_notice("Could not determine any CPU cluster\n"); return 0; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-3.4.0+git0.64a335366/src/errors.c new/haproxy-3.4.0+git31.fc300e9f2/src/errors.c --- old/haproxy-3.4.0+git0.64a335366/src/errors.c 2026-06-03 15:01:51.000000000 +0200 +++ new/haproxy-3.4.0+git31.fc300e9f2/src/errors.c 2026-06-18 09:19:41.000000000 +0200 @@ -387,6 +387,20 @@ } /* + * Displays the message on stderr with the pid if MODE_DIAG is set. + */ +void ha_diag_notice(const char *fmt, ...) +{ + va_list argp; + + if (global.mode & MODE_DIAG) { + va_start(argp, fmt); + print_message(1, "DIAG", fmt, argp); + va_end(argp); + } +} + +/* * Displays the message on stderr with the pid. */ void ha_notice(const char *fmt, ...) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-3.4.0+git0.64a335366/src/h3.c new/haproxy-3.4.0+git31.fc300e9f2/src/h3.c --- old/haproxy-3.4.0+git0.64a335366/src/h3.c 2026-06-03 15:01:51.000000000 +0200 +++ new/haproxy-3.4.0+git31.fc300e9f2/src/h3.c 2026-06-18 09:19:41.000000000 +0200 @@ -2012,8 +2012,9 @@ * receipt of a PUSH_PROMISE frame that contains a larger push ID than * the client has advertised as a connection error of H3_ID_ERROR. */ - ret = H3_ERR_ID_ERROR; - break; + TRACE_ERROR("Received unexpected PUSH_PROMISE frame", H3_EV_RX_FRAME, qcs->qcc->conn, qcs); + qcc_set_error(qcs->qcc, H3_ERR_ID_ERROR, 1, muxc_tevt_type_proto_err); + goto err; case H3_FT_MAX_PUSH_ID: /* h3_check_frame_valid() must reject on client side. */ BUG_ON(conn_is_back(qcs->qcc->conn)); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-3.4.0+git0.64a335366/src/hpack-tbl.c new/haproxy-3.4.0+git31.fc300e9f2/src/hpack-tbl.c --- old/haproxy-3.4.0+git0.64a335366/src/hpack-tbl.c 2026-06-03 15:01:51.000000000 +0200 +++ new/haproxy-3.4.0+git31.fc300e9f2/src/hpack-tbl.c 2026-06-18 09:19:41.000000000 +0200 @@ -351,6 +351,8 @@ else { /* need to defragment the table before inserting upfront */ dht = hpack_dht_defrag(dht); + if (!dht) + return -1; wrap = dht->wrap + 1; head = dht->head + 1; dht->dte[head].addr = dht->dte[dht->front].addr - (name.len + value.len); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-3.4.0+git0.64a335366/src/http_act.c new/haproxy-3.4.0+git31.fc300e9f2/src/http_act.c --- old/haproxy-3.4.0+git0.64a335366/src/http_act.c 2026-06-03 15:01:51.000000000 +0200 +++ new/haproxy-3.4.0+git31.fc300e9f2/src/http_act.c 2026-06-18 09:19:41.000000000 +0200 @@ -1490,6 +1490,7 @@ struct http_msg *msg = ((rule->from == ACT_F_HTTP_REQ) ? &s->txn.http->req : &s->txn.http->rsp); struct htx *htx = htxbuf(&msg->chn->buf); struct sample *hdrs_bin; + struct buffer *copy = NULL; char *p, *end; enum act_return ret = ACT_RET_CONT; struct http_hdr_ctx ctx; @@ -1500,8 +1501,19 @@ if (!hdrs_bin) return ACT_RET_CONT; - p = b_orig(&hdrs_bin->data.u.str); - end = b_tail(&hdrs_bin->data.u.str); + /* The sample may point into the very HTX message we're about to modify + * (e.g. req.body) or into a rotating trash chunk that http_add_header() + * reuses internally; either way a defrag/realloc would leave our p/end/ + * n/v pointers dangling. Work on a private copy to stay safe. + */ + copy = alloc_trash_chunk(); + if (!copy || b_data(&hdrs_bin->data.u.str) > b_size(copy)) + goto fail_rewrite; + memcpy(b_orig(copy), b_orig(&hdrs_bin->data.u.str), b_data(&hdrs_bin->data.u.str)); + b_set_data(copy, b_data(&hdrs_bin->data.u.str)); + + p = b_orig(copy); + end = b_tail(copy); while (p < end) { if (decode_varint(&p, end, &sz) == -1) goto fail_rewrite; @@ -1546,6 +1558,7 @@ ret = ACT_RET_ERR; leave: + free_trash_chunk(copy); return ret; fail_rewrite: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-3.4.0+git0.64a335366/src/http_ana.c new/haproxy-3.4.0+git31.fc300e9f2/src/http_ana.c --- old/haproxy-3.4.0+git0.64a335366/src/http_ana.c 2026-06-03 15:01:51.000000000 +0200 +++ new/haproxy-3.4.0+git31.fc300e9f2/src/http_ana.c 2026-06-18 09:19:41.000000000 +0200 @@ -1265,7 +1265,7 @@ struct htx *htx; struct connection *srv_conn; struct htx_sl *sl; - int n; + int n, l7_retry_failed = 0; DBG_TRACE_ENTER(STRM_EV_STRM_ANA|STRM_EV_HTTP_ANA, s, txn, msg); @@ -1306,19 +1306,22 @@ (!conn || conn->err_code != CO_ER_SSL_EARLY_FAILED)) { if (co_data(rep) || do_l7_retry(s, s->scb) == 0) return 0; + l7_retry_failed = 1; } /* Perform a L7 retry on empty response or because server refuses the early data. */ if ((txn->flags & TX_L7_RETRY) && (s->be->retry_type & PR_RE_EARLY_ERROR) && - conn && conn->err_code == CO_ER_SSL_EARLY_FAILED && - do_l7_retry(s, s->scb) == 0) { - DBG_TRACE_DEVEL("leaving on L7 retry", - STRM_EV_STRM_ANA|STRM_EV_HTTP_ANA, s, txn); - return 0; + conn && conn->err_code == CO_ER_SSL_EARLY_FAILED) { + if (do_l7_retry(s, s->scb) == 0) { + DBG_TRACE_DEVEL("leaving on L7 retry", + STRM_EV_STRM_ANA|STRM_EV_HTTP_ANA, s, txn); + return 0; + } + l7_retry_failed = 1; } - if (s->flags & SF_SRV_REUSED) + if (!l7_retry_failed && (s->flags & SF_SRV_REUSED)) goto abort_keep_alive; if (s->be_tgcounters) @@ -1416,9 +1419,10 @@ STRM_EV_STRM_ANA|STRM_EV_HTTP_ANA, s, txn); return 0; } + l7_retry_failed = 1; } - if (s->flags & SF_SRV_REUSED) + if (!l7_retry_failed && (s->flags & SF_SRV_REUSED)) goto abort_keep_alive; if (s->be_tgcounters) @@ -2517,7 +2521,6 @@ } case REDIRECT_TYPE_LOCATION: default: - memset(chunk->area, 0x50, chunk->size); if (rule->rdr_str) { /* this is an old "redirect" rule */ /* add location */ if (!chunk_memcat(chunk, rule->rdr_str, rule->rdr_len)) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-3.4.0+git0.64a335366/src/map.c new/haproxy-3.4.0+git31.fc300e9f2/src/map.c --- old/haproxy-3.4.0+git0.64a335366/src/map.c 2026-06-03 15:01:51.000000000 +0200 +++ new/haproxy-3.4.0+git31.fc300e9f2/src/map.c 2026-06-18 09:19:41.000000000 +0200 @@ -998,8 +998,12 @@ /* Lookup the reference in the maps. */ ctx->ref = pat_ref_lookup_ref(args[2]); if (!ctx->ref || - !(ctx->ref->flags & ctx->display_flags)) - return cli_err(appctx, "Unknown map identifier. Please use #<id> or <file>.\n"); + !(ctx->ref->flags & ctx->display_flags)) { + if (ctx->display_flags == PAT_REF_MAP) + return cli_err(appctx, "Unknown map identifier. Please use #<id> or <file>.\n"); + else + return cli_err(appctx, "Unknown ACL identifier. Please use #<id> or <file>.\n"); + } /* If the entry identifier start with a '#', it is considered as * pointer id diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-3.4.0+git0.64a335366/src/mux_fcgi.c new/haproxy-3.4.0+git31.fc300e9f2/src/mux_fcgi.c --- old/haproxy-3.4.0+git0.64a335366/src/mux_fcgi.c 2026-06-03 15:01:51.000000000 +0200 +++ new/haproxy-3.4.0+git31.fc300e9f2/src/mux_fcgi.c 2026-06-18 09:19:41.000000000 +0200 @@ -54,7 +54,7 @@ uint32_t flags; /* Connection flags: FCGI_CF_* */ int16_t dsi; /* dmux stream ID (<0 = idle ) */ - uint16_t drl; /* demux record length (if dsi >= 0) */ + uint32_t drl; /* demux record length (if dsi >= 0) */ uint8_t drt; /* demux record type (if dsi >= 0) */ uint8_t drp; /* demux record padding (if dsi >= 0) */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-3.4.0+git0.64a335366/src/mux_h1.c new/haproxy-3.4.0+git31.fc300e9f2/src/mux_h1.c --- old/haproxy-3.4.0+git0.64a335366/src/mux_h1.c 2026-06-03 15:01:51.000000000 +0200 +++ new/haproxy-3.4.0+git31.fc300e9f2/src/mux_h1.c 2026-06-18 09:19:41.000000000 +0200 @@ -5986,7 +5986,24 @@ return -1; } free(hdrs_map.name); - hdrs_map.name = strdup(args[1]); + if (args[1][0] != '/') { + char *curpath; + char *fullpath = NULL; + + /* filename is provided using relative path, store the absolute path + * to take current chdir into account for other threads file load + * which occur later + */ + curpath = getcwd(trash.area, trash.size); + if (!curpath) { + memprintf(err, "failed to retrieve cur path"); + return -1; + } + hdrs_map.name = memprintf(&fullpath, "%s/%s", curpath, args[1]); + } + else + hdrs_map.name = strdup(args[1]); + if (!hdrs_map.name) { memprintf(err, "'%s %s' : out of memory", args[0], args[1]); return -1; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-3.4.0+git0.64a335366/src/mux_quic.c new/haproxy-3.4.0+git31.fc300e9f2/src/mux_quic.c --- old/haproxy-3.4.0+git0.64a335366/src/mux_quic.c 2026-06-03 15:01:51.000000000 +0200 +++ new/haproxy-3.4.0+git31.fc300e9f2/src/mux_quic.c 2026-06-18 09:19:41.000000000 +0200 @@ -1268,10 +1268,11 @@ rxbuf->off_end = qcs->rx.offset + b_data(&b) + to_copy; eb64_insert(&qcs->rx.bufs, &rxbuf->off_node); + /* Increment next rxbuf offset. This must not exceed off_end. */ rxbuf_next->off_node.key += to_copy; BUG_ON(rxbuf_next->off_node.key > rxbuf_next->off_end); - - if (rxbuf_next->off_node.key == rxbuf_next->off_end) { + /* Now reinsert next rxbuf unless it has been completely truncated. */ + if (rxbuf_next->off_node.key < rxbuf_next->off_end) { eb64_insert(&qcs->rx.bufs, &rxbuf_next->off_node); } else { @@ -3315,6 +3316,7 @@ qcc_qmux_recv(qcc); } + next_recv: while (!LIST_ISEMPTY(&qcc->recv_list)) { qcs = LIST_ELEM(qcc->recv_list.n, struct qcs *, el_recv); /* No need to add an uni local stream in recv_list. */ @@ -3322,12 +3324,26 @@ while (qcs_rx_avail_data(qcs) && !(qcs->flags & QC_SF_DEM_FULL)) { ret = qcc_decode_qcs(qcc, qcs); - LIST_DEL_INIT(&qcs->el_recv); + if (ret <= 0) { + LIST_DEL_INIT(&qcs->el_recv); + /* Interrupt all receive if connection on error. */ + if (qcc->flags & QC_CF_ERRL) + goto done; + /* Decode next entry if stream on error. */ + goto next_recv; + } - if (ret <= 0) - goto done; total += ret; } + + /* Always remove QCS from recv_list to prevent infinite loop. + * This is performed even if inner loop was not executed : QCS + * has nothing to do in recv_list if no avail Rx data or demux + * is blocked. Next decoding will be performed on new data read + * unless demux is blocked. In this case QCS will be reinserted + * in recv_list on unblocking to execute decode here again. + */ + LIST_DEL_INIT(&qcs->el_recv); } done: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-3.4.0+git0.64a335366/src/quic_tp.c new/haproxy-3.4.0+git31.fc300e9f2/src/quic_tp.c --- old/haproxy-3.4.0+git0.64a335366/src/quic_tp.c 2026-06-03 15:01:51.000000000 +0200 +++ new/haproxy-3.4.0+git31.fc300e9f2/src/quic_tp.c 2026-06-18 09:19:41.000000000 +0200 @@ -58,6 +58,7 @@ server ? quic_tune.fe.stream_max_concurrent : quic_tune.be.stream_max_concurrent; /* TODO value used to conform with HTTP/3, should be derived from app_ops */ const int max_streams_uni = 3; + uint64_t max_stream_data_bidi; /* Set RFC default values for unspecified parameters. */ quic_dflt_transport_params_cpy(p); @@ -81,21 +82,30 @@ p->initial_max_data = stream_rxbuf ? stream_rxbuf : max_streams_bidi * stream_rx_bufsz; - /* Set remote streams flow-control data limit. This is calculated as a - * ratio from max-data, then rounded up to bufsize. + /* Calculate the limit for the Rx capability of bidirectional streams. + * This is a ratio from max-data rounded up to bufsize. */ - p->initial_max_stream_data_bidi_remote = server ? + max_stream_data_bidi = server ? p->initial_max_data * quic_tune.fe.stream_data_ratio / 100 : p->initial_max_data * quic_tune.be.stream_data_ratio / 100; - p->initial_max_stream_data_bidi_remote = - stream_rx_bufsz * ((p->initial_max_stream_data_bidi_remote + (stream_rx_bufsz - 1)) / stream_rx_bufsz); + max_stream_data_bidi = + stream_rx_bufsz * ((max_stream_data_bidi + (stream_rx_bufsz - 1)) / stream_rx_bufsz); - /* Set remaining flow-control data limit. Local bidi streams are unused - * on server side. Uni streams are only used for control exchange, so - * only a single buffer for in flight data should be enough. + /* Apply bidirectional streams Rx cap. This depends on the connection + * side. On FE side, exchange will occur on remote streams; on BE side, + * exchange will occur on local streams. */ - p->initial_max_stream_data_bidi_local = stream_rx_bufsz; - p->initial_max_stream_data_uni = stream_rx_bufsz; + if (server) { + p->initial_max_stream_data_bidi_remote = max_stream_data_bidi; + p->initial_max_stream_data_bidi_local = stream_rx_bufsz; + } + else { + p->initial_max_stream_data_bidi_remote = stream_rx_bufsz; + p->initial_max_stream_data_bidi_local = max_stream_data_bidi; + } + + /* Unidirectional streams exchange should be minimal. */ + p->initial_max_stream_data_uni = stream_rx_bufsz; if (server) { p->with_stateless_reset_token = 1; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-3.4.0+git0.64a335366/src/quic_tx.c new/haproxy-3.4.0+git31.fc300e9f2/src/quic_tx.c --- old/haproxy-3.4.0+git0.64a335366/src/quic_tx.c 2026-06-03 15:01:51.000000000 +0200 +++ new/haproxy-3.4.0+git31.fc300e9f2/src/quic_tx.c 2026-06-18 09:19:41.000000000 +0200 @@ -2029,8 +2029,8 @@ /* Handle Initial packet padding if necessary. */ if (padding && dglen < QUIC_INITIAL_PACKET_MINLEN) { padding_len = QUIC_INITIAL_PACKET_MINLEN - dglen; - len += padding_len; + /* Update size of packet length field with new PADDING data. */ if (pkt->type != QUIC_PACKET_TYPE_SHORT) { size_t len_sz_diff = quic_int_getsize(len) - len_sz; @@ -2038,6 +2038,7 @@ padding_len -= len_sz_diff; len_sz += len_sz_diff; dglen += len_sz_diff; + len -= len_sz_diff; } } } @@ -2074,6 +2075,7 @@ len += padding_len; } + /* Encode length field : length of PN and payload (frames + TLS AEAD tag). */ if (pkt->type != QUIC_PACKET_TYPE_SHORT && !quic_enc_int(&pos, end, len)) goto no_room; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-3.4.0+git0.64a335366/src/regex.c new/haproxy-3.4.0+git31.fc300e9f2/src/regex.c --- old/haproxy-3.4.0+git0.64a335366/src/regex.c 2026-06-03 15:01:51.000000000 +0200 +++ new/haproxy-3.4.0+git31.fc300e9f2/src/regex.c 2026-06-18 09:19:41.000000000 +0200 @@ -442,7 +442,7 @@ INITCALL0(STG_REGISTER, regex_register_build_options); #ifdef USE_PCRE2 -static int init_pcre2_per_thread(void) +static int init_pcre2_one_thread(void) { local_pcre2_match = pcre2_match_data_create(MAX_MATCH, NULL); if (!local_pcre2_match) { @@ -452,13 +452,32 @@ return 1; } +/* per-thread init for the next threads (first one already done) */ +static int init_pcre2_per_thread(void) +{ + if (!tid) + return 1; + return init_pcre2_one_thread(); +} + +/* per-thread deinit for the next threads */ static void deinit_pcre2_per_thread(void) { + if (tid) + pcre2_match_data_free(local_pcre2_match); +} + +/* late deinit for the first thread */ +static void deinit_pcre2_first_thread(void) +{ pcre2_match_data_free(local_pcre2_match); } +/* early init for the first thread */ +INITCALL0(STG_INIT, init_pcre2_one_thread); REGISTER_PER_THREAD_INIT(init_pcre2_per_thread); REGISTER_PER_THREAD_DEINIT(deinit_pcre2_per_thread); +REGISTER_POST_DEINIT(deinit_pcre2_first_thread); #endif /* diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-3.4.0+git0.64a335366/src/server.c new/haproxy-3.4.0+git31.fc300e9f2/src/server.c --- old/haproxy-3.4.0+git0.64a335366/src/server.c 2026-06-03 15:01:51.000000000 +0200 +++ new/haproxy-3.4.0+git31.fc300e9f2/src/server.c 2026-06-18 09:19:41.000000000 +0200 @@ -2978,6 +2978,19 @@ srv->check.alpn_len = src->check.alpn_len; } } + if (src->check.tcpcheck && src->check.tcpcheck->healthcheck) { + struct tcpcheck *tcpcheck = NULL; + + tcpcheck = calloc(1, sizeof(*tcpcheck)); + if (tcpcheck) { + LIST_INIT(&tcpcheck->preset_vars); + tcpcheck->healthcheck = strdup(src->check.tcpcheck->healthcheck); + if (tcpcheck->healthcheck == NULL) + ha_free(&tcpcheck); + } + if (tcpcheck) + srv->check.tcpcheck = tcpcheck; + } if (!(srv->flags & SRV_F_RHTTP)) srv->check.reuse_pool = src->check.reuse_pool; @@ -6206,7 +6219,6 @@ struct server *srv; char *be_name, *sv_name, *errmsg; int errcode, argc; - int next_id; const int parse_flags = SRV_PARSE_DYNAMIC|SRV_PARSE_PARSE_ADDR; usermsgs_clr("CLI"); @@ -6373,6 +6385,19 @@ if (errcode) goto out; + /* Generate the server ID if not manually specified. This must be + * performed before the server queuing in LB tree (srv_alloc_lb()). + * Proxy tree ID insertion though is only done when all fallible + * operation are completed. + */ + if (!srv->puid) { + srv->puid = server_get_next_id(be, 1); + if (!srv->puid) { + ha_alert("Cannot attach server : no id left in proxy\n"); + goto out; + } + } + if (!srv_alloc_lb(srv, be)) { ha_alert("Failed to initialize load-balancing data.\n"); goto out; @@ -6392,16 +6417,7 @@ if (errcode) goto out; - /* generate the server id if not manually specified */ - if (!srv->puid) { - next_id = server_get_next_id(be, 1); - if (!next_id) { - ha_alert("Cannot attach server : no id left in proxy\n"); - goto out; - } - - srv->puid = next_id; - } + /* All fallible operations completed, the server can now be made visible. */ /* insert the server in the backend trees */ server_index_id(be, srv); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-3.4.0+git0.64a335366/src/session.c new/haproxy-3.4.0+git31.fc300e9f2/src/session.c --- old/haproxy-3.4.0+git0.64a335366/src/session.c 2026-06-03 15:01:51.000000000 +0200 +++ new/haproxy-3.4.0+git31.fc300e9f2/src/session.c 2026-06-18 09:19:41.000000000 +0200 @@ -30,7 +30,7 @@ DECLARE_TYPED_POOL(pool_head_session, "session", struct session); -DECLARE_TYPED_POOL(pool_head_sess_priv_conns, "session priv conns list", struct sess_priv_conns); +DECLARE_TYPED_POOL(pool_head_sess_priv_conns, "sess_priv_conns", struct sess_priv_conns); int conn_complete_session(struct connection *conn); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-3.4.0+git0.64a335366/src/ssl_sock.c new/haproxy-3.4.0+git31.fc300e9f2/src/ssl_sock.c --- old/haproxy-3.4.0+git0.64a335366/src/ssl_sock.c 2026-06-03 15:01:51.000000000 +0200 +++ new/haproxy-3.4.0+git31.fc300e9f2/src/ssl_sock.c 2026-06-18 09:19:41.000000000 +0200 @@ -439,6 +439,22 @@ } #ifdef HA_USE_KTLS +static int ktls_enable_ulp(struct ssl_sock_ctx *ctx) +{ + int ret = 0; + + if (!(ctx->flags & SSL_SOCK_F_KTLS_ULP)) { + ret = setsockopt(ctx->conn->handle.fd, SOL_TCP, TCP_ULP, "tls", + sizeof("tls")); + if (ret == 0) + ctx->flags |= SSL_SOCK_F_KTLS_ULP; + else + ctx->flags &= ~SSL_SOCK_F_KTLS_ENABLED; + } + + return ret; +} + /* Returns 0 on success, -1 on failure */ static int ktls_set_key(struct ssl_sock_ctx *ctx, void *info, size_t info_len, int is_tx) { @@ -485,6 +501,9 @@ if (!(ctx->flags & SSL_SOCK_F_KTLS_ENABLED)) return 0; + + if (ktls_enable_ulp(ctx) == -1) + return 0; /* * As OpenSSL doesn't export struct tls_crypto_info_all, * and it puts the size at the end of the struct, @@ -5670,14 +5689,6 @@ if (ret < 0) return ret; } -#ifdef HA_USE_KTLS - /* - * Make the socket usable for kTLS. That does not mean that we will - * use kTLS, though, just that the socket will be able to do it. - */ - if ((ctx->flags & SSL_SOCK_F_KTLS_ENABLED) && setsockopt(conn->handle.fd, SOL_TCP, TCP_ULP, "tls", sizeof("tls")) != 0) - ctx->flags &= ~SSL_SOCK_F_KTLS_ENABLED; -#endif tasklet_wakeup(ctx->wait_event.tasklet); return 0; @@ -6617,6 +6628,9 @@ if (!(ctx->flags & SSL_SOCK_F_KTLS_ENABLED)) return; + if (ktls_enable_ulp(ctx) == -1) + return; + switch (SSL_version(ctx->ssl)) { case TLS_1_2_VERSION: is_tls_12 = 1; @@ -7078,8 +7092,12 @@ memcpy(b_tail(buf), b_head(&ctx->early_buf), try); b_add(buf, try); b_del(&ctx->early_buf, try); - if (b_data(&ctx->early_buf) == 0) - b_free(&ctx->early_buf); + if (b_data(&ctx->early_buf) == 0) { + if (!(ctx->conn->flags & CO_FL_EARLY_SSL_HS)) + b_free(&ctx->early_buf); + else + b_reset(&ctx->early_buf); + } TRACE_STATE("read early data", SSL_EV_CONN_RECV|SSL_EV_CONN_RECV_EARLY, conn, &try); return try; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-3.4.0+git0.64a335366/src/tcpcheck.c new/haproxy-3.4.0+git31.fc300e9f2/src/tcpcheck.c --- old/haproxy-3.4.0+git0.64a335366/src/tcpcheck.c 2026-06-03 15:01:51.000000000 +0200 +++ new/haproxy-3.4.0+git31.fc300e9f2/src/tcpcheck.c 2026-06-18 09:19:41.000000000 +0200 @@ -4198,7 +4198,7 @@ } srv->check.tcpcheck->rs = rs; srv->check.tcpcheck->flags = rs->conf.flags; - + srv->check.type = PR_O2_TCPCHK_CHK; err_code = check_tcpcheck_ruleset(srv->proxy, rs); } @@ -5970,7 +5970,7 @@ goto out; } - if (srv->check.tcpcheck->healthcheck) { + if (srv->check.tcpcheck && srv->check.tcpcheck->healthcheck) { /* a healthcheck section was already defined. Replace it */ ha_free(&srv->check.tcpcheck->healthcheck); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-3.4.0+git0.64a335366/src/thread.c new/haproxy-3.4.0+git31.fc300e9f2/src/thread.c --- old/haproxy-3.4.0+git0.64a335366/src/thread.c 2026-06-03 15:01:51.000000000 +0200 +++ new/haproxy-3.4.0+git31.fc300e9f2/src/thread.c 2026-06-18 09:19:41.000000000 +0200 @@ -1667,7 +1667,9 @@ char *err __maybe_unused; int thr_forced = 0; int tgrp_forced = 0; +#ifdef USE_THREAD int cpus_detected = 0; +#endif thr_min = 1; thr_max = MAX_THREADS; grp_min = 1; grp_max = MAX_TGROUPS; @@ -1810,6 +1812,7 @@ if (!global.nbtgroups) global.nbtgroups = grp_min; +#ifdef USE_THREAD if (tgrp_forced && !thr_forced && !cpu_map_in_conf && (!global.thread_limit || (global.nbthread < global.thread_limit)) && global.nbthread < MIN(cpus_detected, thread_cpus_enabled_at_boot) && @@ -1828,6 +1831,7 @@ ha_notice("%d usable CPUs detected but 'nbthread' forced to %d (%d%%). Remove 'nbthread' for optimal tuning.\n", nbcpus, global.nbthread, global.nbthread * 100 / nbcpus); } +#endif if (global.nbthread > global.maxthrpertgroup * global.nbtgroups) { ha_diag_warning("nbthread too large or not set, found %d CPUs, limiting to %d threads (maximum is %d per thread group and %d groups). Please set nbthreads and/or increase thread-groups in the global section to silence this warning.\n", diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-3.4.0+git0.64a335366/src/xprt_qmux.c new/haproxy-3.4.0+git31.fc300e9f2/src/xprt_qmux.c --- old/haproxy-3.4.0+git0.64a335366/src/xprt_qmux.c 2026-06-03 15:01:51.000000000 +0200 +++ new/haproxy-3.4.0+git31.fc300e9f2/src/xprt_qmux.c 2026-06-18 09:19:41.000000000 +0200 @@ -350,6 +350,22 @@ pool_free(xprt_qmux_ctx_pool, ctx); } +/* Retrieve the ssl_sock_ctx of the lower layer. Contrary to most XPRTs, QMux + * is stacked on top of the SSL layer (and not the other way around), so during + * the QMux handshake conn->xprt points to xprt_qmux. Without this delegation, + * conn_get_ssl_sock_ctx() would return NULL for any code inspecting the SSL + * layer of the connection (sample fetches, logging, info callback, ...) while + * the QMux handshake is in progress. + */ +static struct ssl_sock_ctx *xprt_qmux_get_ssl_sock_ctx(struct connection *conn) +{ + struct xprt_qmux_ctx *ctx = conn->xprt_ctx; + + if (ctx && ctx->ops_lower == xprt_get(XPRT_SSL)) + return ctx->ctx_lower; + return NULL; +} + static int xprt_qmux_get_alpn(const struct connection *conn, void *xprt_ctx, const char **str, int *len) { @@ -371,6 +387,7 @@ .start = xprt_qmux_start, .close = xprt_qmux_close, .get_alpn = xprt_qmux_get_alpn, + .get_ssl_sock_ctx = xprt_qmux_get_ssl_sock_ctx, .name = "qmux", }; ++++++ haproxy-opentelemetry-849ecaf.tar.gz -> haproxy-opentelemetry-ce86d09.tar.gz ++++++ ++++ 10691 lines of diff (skipped)
