From: Willy Tarreau Date: Thu, 3 Sep 2026 05:05:35 +0000 (+0200) Subject: REGTESTS: log: check the escaping performed by the +json option X-Git-Tag: v3.5-dev6~8 X-Git-Url: https://git.kaiwu.me/?a=commitdiff_plain;h=6457968043ccab554d1b52ecf04e45d35cc4c2b9;p=haproxy.git REGTESTS: log: check the escaping performed by the +json option Check that a control character, a byte above the printable range and the two characters which JSON requires to be escaped all come out escaped, and that nothing outside 32..126 reaches the ring. The test fails without the previous commit. --- diff --git a/reg-tests/log/log_json.vtc b/reg-tests/log/log_json.vtc new file mode 100644 index 000000000..f2fe4dc87 --- /dev/null +++ b/reg-tests/log/log_json.vtc @@ -0,0 +1,77 @@ +varnishtest "Check the escaping performed by the +json option" +feature ignore_unknown_macro + +# Section 8.6 of the config manual states that only the characters from 32 to +# 126 are emitted as-is in the logs, everything else being encoded, and the +# JSON encoding has no reason to be more permissive than the plain one. +# Escaping them all also makes the output valid UTF-8, which RFC 8259 #8.1 +# requires, without having to guess what the logged bytes represent: a header +# value is arbitrary bytes, not text. + +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}" + capture request header x len 64 + log ring@myring local0 + log-format "{\"hdr\":%{+json}[capture.req.hdr(0)],\"bin\":%{+json}[str(Gw==),b64dec]}" + http-request return status 200 +} -start + +# an ESC, which has no two-character form, a tab, which has one, a double quote +# and a backslash +client c1 -connect ${h1_fe_sock} { + txreq -url "/ctl" -hdr "x: A\x1b[31m\tB\"C\\D" + rxresp + expect resp.status == 200 +} -run + +# bytes above the printable range, here a valid UTF-8 sequence and a lone +# continuation byte, are encoded the same way: one escape per byte +client c2 -connect ${h1_fe_sock} { + txreq -url "/high" -hdr "x: A\xc3\xa9B\xaaC" + rxresp + expect resp.status == 200 +} -run + +delay 0.2 + +# the ESC comes out as the six-character form and the tab as the short one, in +# both the string sample and the binary sample paths +haproxy h1 -cli { + send "show events myring" + expect ~ "A\\\\u001B\\[31m\\\\tB" +} + +haproxy h1 -cli { + send "show events myring" + expect ~ "\"bin\":\"\\\\u001B\"" +} + +# one escape per byte above the printable range, so the output stays plain +# ASCII and no byte can be mistaken for a sequence introducer +haproxy h1 -cli { + send "show events myring" + expect ~ "A\\\\u00C3\\\\u00A9B\\\\u00AAC" +} + +# nothing outside 32..126 reached the ring, which "-s" would have turned into +# a '?' +haproxy h1 -cli { + send "show events myring -s" + expect !~ "\\?" +}