From: Frederic Lecaille Date: Thu, 10 Sep 2026 13:37:17 +0000 (+0200) Subject: REGTESTS: map: check map_regm inside an ACL over an iterating fetch X-Git-Tag: v3.5-dev7~45 X-Git-Url: https://git.kaiwu.me/?a=commitdiff_plain;h=992eda1bbf46e55b60bb0900b4cf6f0fcc8878c5;p=haproxy.git REGTESTS: map: check map_regm inside an ACL over an iterating fetch This test covers the bug fixed by this commit: 7646c657a BUG/MEDIUM: map: do not overwrite the fetch context in pat_match_regm() It uses map_regm in an ACL over req.hdr() with no occurrence. The first value does not match, so the ACL runs a second iteration of the fetch, which crashed the process before the fix. A request with two header values checks that the fetch cursor survives the first iteration. Thank you to @Michael-JRead for having produced the first version of this reg test. This must be backported with the fix above. --- diff --git a/reg-tests/http-rules/map_regm_in_acl.map b/reg-tests/http-rules/map_regm_in_acl.map new file mode 100644 index 000000000..48e543fa6 --- /dev/null +++ b/reg-tests/http-rules/map_regm_in_acl.map @@ -0,0 +1,2 @@ +^Mozilla/.* browser +^name-(.*)$ \1 diff --git a/reg-tests/http-rules/map_regm_in_acl.vtc b/reg-tests/http-rules/map_regm_in_acl.vtc new file mode 100644 index 000000000..2284d070b --- /dev/null +++ b/reg-tests/http-rules/map_regm_in_acl.vtc @@ -0,0 +1,53 @@ +#commit 7646c657af79b304c6bff76564d310af5c7de67f +# BUG/MEDIUM: map: do not overwrite the fetch context in pat_match_regm() +# +# pat_match_regm() stored the address of the thread-local array +# into ctx.a[0]>. This slot belongs to the sample fetch, which uses +# it to keep an iteration cursor. When map_regm is used inside an ACL over +# an iterating fetch (req.hdr() with no occurrence), the second iteration +# read the pointer as its cursor and crashed the process. + +varnishtest "map_regm inside an ACL over an iterating fetch" +feature ignore_unknown_macro + +#REGTEST_TYPE=bug + +haproxy h1 -conf { + global + .if feature(THREAD) + thread-groups 1 + .endif + + 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}" + # req.hdr() with no occurrence iterates over all X-Agent values. + acl is_bot req.hdr(X-Agent),map_regm(${testdir}/map_regm_in_acl.map,unknown) -m str bot + http-request deny deny_status 403 if is_bot + http-request return status 200 content-type text/plain hdr x-mapped "%[req.hdr(X-Agent),map_regm(${testdir}/map_regm_in_acl.map,unknown)]" string "OK\n" +} -start + +client c1 -connect ${h1_fe_sock} { + # One value mapped to "browser": the ACL does not match and runs a + # second iteration of the fetch. This crashed before the fix. + txreq -hdr "X-Agent: Mozilla/5.0" + rxresp + expect resp.status == 200 + expect resp.http.x-mapped == "browser" + + # Back-reference: "name-bot" is mapped to "\1", that is "bot". + txreq -hdr "X-Agent: name-bot" + rxresp + expect resp.status == 403 + + # Two values: the first one does not match, the second one does. + # The 403 proves the fetch cursor survived the first iteration. + txreq -hdr "X-Agent: Mozilla/5.0" -hdr "X-Agent: name-bot" + rxresp + expect resp.status == 403 +} -run