]> git.kaiwu.me - haproxy.git/commit
BUG/MEDIUM: pattern: don't dereference static_pattern's data when not filling it
authorWilly Tarreau <w@1wt.eu>
Wed, 30 Sep 2026 14:07:21 +0000 (16:07 +0200)
committerWilly Tarreau <w@1wt.eu>
Wed, 30 Sep 2026 14:10:19 +0000 (16:10 +0200)
commit4e151a25b65bbbc83f10a320eddf71dc8076970c
tree93d89e26f2d059a476d5f8a47292fc778f9b44ab
parent197506b44086ee48c1b33802c27c2bce1eb122d9
BUG/MEDIUM: pattern: don't dereference static_pattern's data when not filling it

The match functions (pat_match_str() etc) may return a pointer to the
thread-local <static_pattern> without updating it when <fill> is not
set. However pattern_exec_match() then unconditionally duplicates the
returned pattern's sample data, dereferencing static_pattern.data, which
may still hold a stale pointer left there by an earlier lookup performed
on the same thread with <fill> set but without going through
pattern_exec_match(). This is what the CLI's "get map" does in
cli_io_handler_map_lookup(): it calls the match function directly, so
static_pattern.data points to the element's real sample data. If this
element is later freed (e.g. by "del map", "clear map", or the purge of
the old generation after "commit map"), the next ACL match on this thread
succeeding via the tree (ACLs use fill=0) reads freed memory in
pattern_exec_match().

This can be reproduced with an ACL and a map, both using virtual files,
with one thread:

    acl known url_param(q) -f virt@cliacl
    http-request set-var(txn.map) url_param(q),map(virt@climap)

then on the CLI: "add map virt@climap one first", "get map virt@climap
one", "prepare map virt@climap", "prepare acl virt@cliacl", "add map @1
virt@climap two third", "add acl @1 virt@cliacl two", "commit map @1
virt@climap", "commit acl @1 virt@cliacl", and finally a request to
"/?q=two" makes ASAN report a heap-use-after-free in pattern_exec_match().
Without ASAN, random garbage may be read, or the process may crash.

The fix consists in not touching the returned pattern at all when <fill>
is not set, since the caller only checks it against NULL. The problem was
introduced in 1.8 with commit b5997f740 ("MAJOR: threads/map: Make
acls/maps thread safe") so this must be backported to all stable versions.
src/pattern.c