From: Willy Tarreau Date: Tue, 1 Sep 2026 13:53:06 +0000 (+0200) Subject: REGTESTS: log: add a test for "show events -s" X-Git-Tag: v3.5-dev6~12 X-Git-Url: https://git.kaiwu.me/?a=commitdiff_plain;h=c6f8f5e0108ae0e8ae27bff21a21e4b393ace533;p=haproxy.git REGTESTS: log: add a test for "show events -s" The commit that added the "-s" option to "show events" was marked as hard to test, the difficulty being to get control characters into a ring in the first place. It is in fact easy from the configuration alone, without involving a client at all: "Gw==", "Cg==" and "Cf==" are the base64 encodings of ESC, LF and TAB, so a log-format that passes them through b64dec emits raw control characters into the ring, exactly like a log field does when it is emitted without "+E". The test then checks the three behaviours that matter: - the default output remains byte-for-byte faithful: the raw LF is still there and turns a single record into two lines, - "-s" replaces the ESC and the LF with '?', and the TAB with a space, so a record can no longer forge another one nor drive the terminal, - "-0 -s" still delimits the records, which the previous commit fixed. The last check fails without that fix, and the whole test fails on any version predating the "-s" option since it reports an unknown option. --- diff --git a/reg-tests/log/ring_sanitize.vtc b/reg-tests/log/ring_sanitize.vtc new file mode 100644 index 000000000..db01b3e0d --- /dev/null +++ b/reg-tests/log/ring_sanitize.vtc @@ -0,0 +1,73 @@ +varnishtest "Check that 'show events -s' sanitizes the ring contents" +feature ignore_unknown_macro + +# The log-format below deliberately emits control characters into the ring +# without involving any client: "Gw==", "Cg==" and "Cf==" are the base64 +# encodings of ESC (0x1b), LF (0x0a) and TAB (0x09), so b64dec turns them into +# raw bytes. This is what an attacker-influenced log field may carry when it is +# emitted without "+E". +# +# Without "-s", "show events" dumps them verbatim: the ESC sequence reaches the +# operator's terminal, and the LF splits one record into two, forging a log +# line. With "-s", the ESC and LF become '?', and TAB becomes a space, so each +# record stays on a single line. + +haproxy h1 -conf { + global + .if feature(THREAD) + thread-groups 1 + .endif + + ring myring + size 16384 + format raw + + 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}" + log ring@myring local0 + log-format "BEG%[str(Gw==),b64dec][2JMID%[str(Cg==),b64dec]FORGED%[str(Cf==),b64dec]END" + http-request return status 200 +} -start + +# two requests, hence two records, so that the record delimiter can be checked +client c1 -connect ${h1_fe_sock} { + txreq -url "/" + rxresp + expect resp.status == 200 +} -run + +client c2 -connect ${h1_fe_sock} { + txreq -url "/" + rxresp + expect resp.status == 200 +} -run + +delay 0.2 + +# the default output is byte-for-byte faithful: the raw LF is still there, so a +# single record shows up as two lines +haproxy h1 -cli { + send "show events myring" + expect ~ "MID\nFORGED\tEND" +} + +# with -s the LF is turned into a space, so the forged line is joined back onto +# the real one, and the ESC is replaced with '?' +haproxy h1 -cli { + send "show events myring -s" + expect ~ "BEG\\?\\[2JMID\\?FORGED END" +} + +# "-0" delimits records with a NUL byte instead of a LF. Combined with "-s" the +# delimiter must still be emitted, otherwise consecutive records get glued +# together and the end of one cannot be told from the start of the next. +haproxy h1 -cli { + send "show events myring -0 -s" + expect !~ "ENDBEG" +}