]> git.kaiwu.me - haproxy.git/commitdiff
BUG/MEDIUM: cache: fix "show cache" crash/skip with several caches
authorChristopher Faulet <cfaulet@haproxy.com>
Thu, 12 Nov 2026 07:14:51 +0000 (08:14 +0100)
committerChristopher Faulet <cfaulet@haproxy.com>
Thu, 12 Nov 2026 17:20:31 +0000 (18:20 +0100)
With "show cache" cli command, a crash could be experienced when several
caches are configured. This happened when iterating on the second cache in
the list. Indded the cache tree array was not reset when the dump of a cache
was finished, leading to computing the cache tree index against the wrong
cache tree and to lock the wrong cache tree.

This is a regression introduced by the resumable CLI output.

Fix it by clearing ctx->cache_tree when the dump of a cache finishes: the
pointer must only be non-NULL while the dump is paused on the cache it
belongs to.

This patch must be backported to all supported versions.

reg-tests/cache/multi_caches_show.vtc [new file with mode: 0644]
src/cache.c

diff --git a/reg-tests/cache/multi_caches_show.vtc b/reg-tests/cache/multi_caches_show.vtc
new file mode 100644 (file)
index 0000000..ee528ca
--- /dev/null
@@ -0,0 +1,53 @@
+varnishtest "show cache must dump all the caches, not only the first one"
+
+feature ignore_unknown_macro
+
+server s1 {
+    rxreq
+    txresp -hdr "Cache-Control: max-age=60" -body "x"
+} -start
+
+haproxy h1 -conf {
+    global
+        stats socket /tmp/mc.sock
+
+    defaults
+        mode http
+        timeout connect "${HAPROXY_TEST_TIMEOUT-5s}"
+        timeout client  "${HAPROXY_TEST_TIMEOUT-5s}"
+        timeout server  "${HAPROXY_TEST_TIMEOUT-5s}"
+
+    frontend fe
+        bind "fd@${fe}"
+        http-request cache-use c1
+        http-response cache-store c1
+        http-response cache-store c2
+        default_backend be
+
+    backend be
+        server s ${s1_addr}:${s1_port}
+
+    cache c1
+        total-max-size 4
+
+    cache c2
+        total-max-size 4
+
+    cache c3
+        total-max-size 4
+} -start
+
+client c1 -connect ${h1_fe_sock} {
+    txreq -url "/a"
+    rxresp
+    expect resp.status == 200
+} -run
+
+# Without the fix, cli_io_handler_show_cache() computes the resume index of
+# the second cache from the tree pointer left over by the first cache's dump:
+# the index is garbage. Depending on the mmap order of the shctxs, the entries
+# of the following caches are skipped, or their dump crashes the process.
+haproxy h1 -cli {
+    send "show cache"
+    expect ~ "(?s)c1.*hash.*c2.*hash.*c3"
+}
index 8e9cc75e7123c8bf7920b8beb9ebd9ba2c94302d..3e3a2119ee41432b20bddbf78d0240d3eb90bf94 100644 (file)
@@ -3816,6 +3816,9 @@ static int cli_io_handler_show_cache(struct appctx *appctx)
                        }
                        cache_rdunlock(cache_tree);
                }
+
+               /* Reset the cache tree for the next cache */
+               ctx->cache_tree = NULL;
        }
 
        free_trash_chunk(buf);