From: Willy Tarreau Date: Wed, 11 Nov 2026 10:42:38 +0000 (+0200) Subject: MINOR: acl: add acl_cond_find_positive_use() to find positive terms by usage X-Git-Tag: v3.5-dev12~12 X-Git-Url: https://git.kaiwu.me/%7B@url%7D?a=commitdiff_plain;h=4f49e579f761219f54fd9f351fa6752e72f25a56;p=haproxy.git MINOR: acl: add acl_cond_find_positive_use() to find positive terms by usage This function looks for a term of a condition which makes the condition true when it matches (a non-negated term after "if", or a negated one after "unless") and which involves a sample fetch having certain SMP_USE_* bits. It returns the first matching ACL and keyword, in the same way as acl_cond_kw_conflicts() does. The combination of terms is not considered, a single positive term is enough. It will be used to detect deny-lists built on aliasable contents. --- diff --git a/include/haproxy/acl.h b/include/haproxy/acl.h index af48dba38..5da8bfbfa 100644 --- a/include/haproxy/acl.h +++ b/include/haproxy/acl.h @@ -139,6 +139,14 @@ const struct acl *acl_cond_conflicts(const struct acl_cond *cond, unsigned int w */ int acl_cond_kw_conflicts(const struct acl_cond *cond, unsigned int where, struct acl const **acl, char const **kw); +/* Looks for a term of condition which may make the condition true when + * it matches, i.e. a non-negated term after "if" or a negated one after + * "unless", and which involves a sample fetch having one of the SMP_USE_* + * bits from . Returns true if such a term is found, with and + * set (if non null) to the first matching ACL and keyword, otherwise false. + */ +int acl_cond_find_positive_use(const struct acl_cond *cond, unsigned int use, struct acl const **acl, char const **kw); + /* * Find targets for userlist and groups in acl. Function returns the number * of errors or OK if everything is fine. diff --git a/src/acl.c b/src/acl.c index 7b1990aaf..40043f537 100644 --- a/src/acl.c +++ b/src/acl.c @@ -1190,6 +1190,45 @@ int acl_cond_kw_conflicts(const struct acl_cond *cond, unsigned int where, struc return 0; } +/* Looks for a term of condition which may make the condition true when + * it matches, i.e. a non-negated term after "if" or a negated one after + * "unless", and which involves a sample fetch having one of the SMP_USE_* + * bits from . Returns true if such a term is found, with and + * set (if non null) to the first matching ACL and keyword, otherwise false. + * This is used to detect deny-lists built on certain types of contents. + */ +int acl_cond_find_positive_use(const struct acl_cond *cond, unsigned int use, struct acl const **acl, char const **kw) +{ + struct acl_term_suite *suite; + struct acl_term *term; + struct acl_expr *expr; + + if (!(cond->use & use)) + return 0; + + list_for_each_entry(suite, &cond->suites, list) { + list_for_each_entry(term, &suite->terms, list) { + /* only keep terms whose match makes the condition true */ + if (!!term->neg != (cond->pol == ACL_COND_UNLESS)) + continue; + + if (!(term->acl->use & use)) + continue; + + list_for_each_entry(expr, &term->acl->expr, list) { + if (expr->smp->fetch->use & use) { + if (acl) + *acl = term->acl; + if (kw) + *kw = expr->kw; + return 1; + } + } + } + } + return 0; +} + /* * Find targets for userlist and groups in acl. Function returns the number * of errors or OK if everything is fine. It must be called only once sample