]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: acl; Warn when matching method based on a suffix is overwritten
authorChristopher Faulet <cfaulet@haproxy.com>
Fri, 29 Aug 2025 15:47:17 +0000 (17:47 +0200)
committerChristopher Faulet <cfaulet@haproxy.com>
Mon, 1 Sep 2025 13:45:05 +0000 (15:45 +0200)
From time to time, issues are reported about string matching based on suffix
(for instance path_beg). Each time, it appears these ACLs are used in
conjunction with a converter or followed by an explicit matching method
(-m).

Unfortunatly, it is not an issue but an expected behavior, while it is not
obvious. matching suffixes can be consider as aliases on the corresponding
'-m' matching method. Thus "path_beg" is equivalent to "path -m beg". When a
converter is used the original matching (string) is used and the suffix is
lost. When followed by an explicit matching method, it overwrites the
matching method based on the suffix.

It is expected but confusing. Thus now a warning is emitted because it is a
configuration issue for sure. Following sample fetch functions are concerned:

 * base
 * path
 * req.cook
 * req.hdr
 * res.hdr
 * url
 * urlp

The configuration manual was modified to make it less ambiguous.

doc/configuration.txt
src/acl.c

index de3da7a2b8ca8040b900bee89af4146f8a55fd56..5e705befae09da1213de294f60cb13d4a42f6a05 100644 (file)
@@ -19466,7 +19466,10 @@ obvious matching method (e.g. string or binary). When "-m" is specified and
 followed by a pattern matching method name, this method is used instead of the
 default one for the criterion. This makes it possible to match contents in ways
 that were not initially planned, or with sample fetch methods which return a
-string. The matching method also affects the way the patterns are parsed.
+string. The matching method also affects the way the patterns are parsed. So,
+it must not be used with sample fetches with a matching suffix (_beg, _end,
+_sub...). In addition, specifying several "-m" pattern matching methods is now
+allowed.
 
 The "-n" flag forbids the dns resolutions. It is used with the load of ip files.
 By default, if the parser cannot parse ip address it considers that the parsed
@@ -25442,6 +25445,9 @@ base : string
     base_reg : regex match
     base_sub : substring match
 
+  Note: ACL derivatives must not be used followed by a converter or in ACLs
+        with a "-m" pattern matching method.
+
 base32 : integer
   This returns a 32-bit hash of the value returned by the "base" fetch method
   above. This is useful to track per-URL activity on high traffic sites without
@@ -25600,6 +25606,9 @@ path : string
     path_reg : regex match
     path_sub : substring match
 
+  Note: ACL derivatives must not be used followed by a converter or in ACLs
+        with a "-m" pattern matching method.
+
 pathq : string
   This extracts the request's URL path with the query-string, which starts at
   the first slash. This sample fetch is pretty handy to always retrieve a
@@ -25676,6 +25685,9 @@ cook([<name>]) : string (deprecated)
     req.cook_reg([<name>]) : regex match
     req.cook_sub([<name>]) : substring match
 
+  Note: ACL derivatives must not be used followed by a converter or in ACLs
+        with a "-m" pattern matching method.
+
 req.cook_cnt([<name>]) : integer
 cook_cnt([<name>]) : integer (deprecated)
   Returns an integer value representing the number of occurrences of the cookie
@@ -25744,6 +25756,9 @@ req.hdr([<name>[,<occ>]]) : string
     hdr_reg([<name>[,<occ>]]) : regex match
     hdr_sub([<name>[,<occ>]]) : substring match
 
+  Note: ACL derivatives must not be used followed by a converter or in ACLs
+        with a "-m" pattern matching method.
+
 req.hdr_cnt([<name>]) : integer
 hdr_cnt([<header>]) : integer (deprecated)
   Returns an integer value representing the number of occurrences of request
@@ -25978,6 +25993,9 @@ shdr([<name>[,<occ>]]) : string (deprecated)
     res.hdr_reg([<name>[,<occ>]]) : regex match
     res.hdr_sub([<name>[,<occ>]]) : substring match
 
+  Note: ACL derivatives must not be used followed by a converter or in ACLs
+        with a "-m" pattern matching method.
+
 res.hdr_cnt([<name>]) : integer
 shdr_cnt([<name>]) : integer (deprecated)
   This fetch works like the req.hdr_cnt() fetch with the difference that it
@@ -26116,6 +26134,9 @@ url : string
     url_reg : regex match
     url_sub : substring match
 
+  Note: ACL derivatives must not be used followed by a converter or in ACLs
+        with a "-m" pattern matching method.
+
 url32 : integer
   This returns a 32-bit hash of the value obtained by concatenating the first
   Host header and the whole URL including parameters (not only the path part of
@@ -26163,6 +26184,8 @@ url_param([<name>[,<delim>[,i]]]) : string
     urlp_reg(<name>[,<delim>]) : regex match
     urlp_sub(<name>[,<delim>]) : substring match
 
+  Note: ACL derivatives must not be used followed by a converter or in ACLs
+        with a "-m" pattern matching method.
 
   Example :
       # match http://example.com/foo?PHPSESSIONID=some_id
index 57fcaa5a7e02ec25e1abebca9790f2be874bc19b..71cdb5b89a5040f6d24a55956b9b35839cc4cb5e 100644 (file)
--- a/src/acl.c
+++ b/src/acl.c
@@ -406,6 +406,15 @@ struct acl_expr *parse_acl_expr(const char **args, char **err, struct arg_list *
                goto out_free_expr;
        }
 
+       if (aclkw) {
+               if (((aclkw->match_type == PAT_MATCH_BEG || aclkw->match_type == PAT_MATCH_DIR || aclkw->match_type == PAT_MATCH_DOM ||
+                    aclkw->match_type == PAT_MATCH_DOM || aclkw->match_type == PAT_MATCH_END || aclkw->match_type == PAT_MATCH_LEN ||
+                    aclkw->match_type == PAT_MATCH_REG) && expr->pat.match != pat_match_fcts[aclkw->match_type]) ||
+                   (aclkw->match && expr->pat.match != pat_match_fcts[aclkw->match_type]))
+                       ha_warning("parsing [%s:%d] : original matching method '%s' was overwritten and will not be applied as expected.\n",
+                                  file, line, aclkw->kw);
+       }
+
        /* Create displayed reference */
        snprintf(trash.area, trash.size, "acl '%s' file '%s' line %d",
                 expr->kw, file, line);