]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: regex: modify regex_comp() to atomically allocate/free the my_regex struct
authorDragan Dosen <ddosen@haproxy.com>
Tue, 30 Apr 2019 13:54:36 +0000 (15:54 +0200)
committerWilly Tarreau <w@1wt.eu>
Tue, 7 May 2019 04:58:15 +0000 (06:58 +0200)
Now we atomically allocate the my_regex struct within function
regex_comp() and compile the regex or free both in case of failure. The
pointer to the allocated my_regex struct is returned directly. The
my_regex* argument to regex_comp() is removed.

Function regex_free() was modified so that it systematically frees the
my_regex entry. The function does nothing when called with a NULL as
argument (like free()). It will avoid existing risk of not properly
freeing the initialized area.

Other structures are also updated in order to be compatible (the ones
related to Lua and action rules).

14 files changed:
include/common/regex.h
include/types/action.h
include/types/hlua.h
src/cfgparse-listen.c
src/checks.c
src/haproxy.c
src/hlua.c
src/hlua_fcn.c
src/http_rules.c
src/pattern.c
src/proto_http.c
src/proto_htx.c
src/regex.c
src/sample.c

index c3b921b3f178aa95ab6376df25d9b35ab6bb616b..0814f8f8b0d81a046b2d6eb6080edf2764361e73 100644 (file)
@@ -88,7 +88,7 @@ extern THREAD_LOCAL regmatch_t pmatch[MAX_MATCH];
  *
  * The function return 1 is succes case, else return 0 and err is filled.
  */
-int regex_comp(const char *str, struct my_regex *regex, int cs, int cap, char **err);
+struct my_regex *regex_comp(const char *str, int cs, int cap, char **err);
 int exp_replace(char *dst, unsigned int dst_size, char *src, const char *str, const regmatch_t *matches);
 const char *check_replace_string(const char *str);
 const char *chain_regex(struct hdr_exp **head, struct my_regex *preg,
@@ -161,6 +161,8 @@ int regex_exec_match2(const struct my_regex *preg, char *subject, int length,
                       size_t nmatch, regmatch_t pmatch[], int flags);
 
 static inline void regex_free(struct my_regex *preg) {
+       if (!preg)
+               return;
 #if defined(USE_PCRE) || defined(USE_PCRE_JIT)
        pcre_free(preg->reg);
 /* PCRE < 8.20 requires pcre_free() while >= 8.20 requires pcre_study_free(),
@@ -176,6 +178,7 @@ static inline void regex_free(struct my_regex *preg) {
 #else
        regfree(&preg->regex);
 #endif
+       free(preg);
 }
 
 #endif /* _COMMON_REGEX_H */
index 6c5fccf4cfd8474607cdee3fc19cfb25c8847fb9..948e281d7fcb0fbe11e3970749d9ca3eed7d87e3 100644 (file)
@@ -121,7 +121,7 @@ struct act_rule {
                        char *name;            /* header name */
                        int name_len;          /* header name's length */
                        struct list fmt;       /* log-format compatible expression */
-                       struct my_regex re;    /* used by replace-header and replace-value */
+                       struct my_regex *re;   /* used by replace-header and replace-value */
                } hdr_add;                     /* args used by "add-header" and "set-header" */
                struct {
                        char *name;            /* header name */
index 36554e265221f7a940775f2d1c5a795a9480671d..70c76852945b867e828ec6de43d45a354b2aca32 100644 (file)
@@ -6,6 +6,7 @@
 #include <lua.h>
 #include <lauxlib.h>
 
+#include <common/regex.h>
 #include <common/xref.h>
 
 #include <types/proto_http.h>
index b46e119fa22838c41b201fdbd02630ffcf4999e6..7760d9c3ca9d663e8ba67e5b658559d5f887b662 100644 (file)
@@ -275,17 +275,10 @@ static int create_cond_regex_rule(const char *file, int line,
                                          ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
                                          file, line);
 
-       preg = calloc(1, sizeof(*preg));
-       if (!preg) {
-               ha_alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
-               ret_code = ERR_ALERT | ERR_FATAL;
-               goto err;
-       }
-
        cs = !(flags & REG_ICASE);
        cap = !(flags & REG_NOSUB);
        error = NULL;
-       if (!regex_comp(reg, preg, cs, cap, &error)) {
+       if (!(preg = regex_comp(reg, cs, cap, &error))) {
                ha_alert("parsing [%s:%d] : '%s' : regular expression '%s' : %s\n", file, line, cmd, reg, error);
                free(error);
                ret_code = ERR_ALERT | ERR_FATAL;
@@ -309,7 +302,6 @@ static int create_cond_regex_rule(const char *file, int line,
  err_free:
        regex_free(preg);
  err:
-       free(preg);
        free(errmsg);
        return ret_code;
 }
@@ -444,8 +436,14 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
                                curproxy->expect_str = strdup(defproxy.expect_str);
                                if (defproxy.expect_regex) {
                                        /* note: this regex is known to be valid */
-                                       curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
-                                       regex_comp(defproxy.expect_str, curproxy->expect_regex, 1, 1, NULL);
+                                       error = NULL;
+                                       if (!(curproxy->expect_regex = regex_comp(defproxy.expect_str, 1, 1, &error))) {
+                                               ha_alert("parsing [%s:%d] : regular expression '%s' : %s\n", file, linenum,
+                                                        defproxy.expect_str, error);
+                                               free(error);
+                                               err_code |= ERR_ALERT | ERR_FATAL;
+                                               goto out;
+                                       }
                                }
                        }
 
@@ -631,11 +629,8 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
                free(defproxy.server_id_hdr_name);
                defproxy.server_id_hdr_len = 0;
                free(defproxy.expect_str);
-               if (defproxy.expect_regex) {
-                       regex_free(defproxy.expect_regex);
-                       free(defproxy.expect_regex);
-                       defproxy.expect_regex = NULL;
-               }
+               regex_free(defproxy.expect_regex);
+               defproxy.expect_regex = NULL;
 
                if (defproxy.conf.logformat_string != default_http_log_format &&
                    defproxy.conf.logformat_string != default_tcp_log_format &&
@@ -2927,16 +2922,11 @@ stats_error_parsing:
                                }
                                curproxy->options2 |= PR_O2_EXP_RSTS;
                                free(curproxy->expect_str);
-                               if (curproxy->expect_regex) {
-                                       regex_free(curproxy->expect_regex);
-                                       free(curproxy->expect_regex);
-                                       curproxy->expect_regex = NULL;
-                               }
+                               regex_free(curproxy->expect_regex);
                                curproxy->expect_str = strdup(args[cur_arg + 1]);
-                               curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
                                error = NULL;
-                               if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
-                                       ha_alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
+                               if (!(curproxy->expect_regex = regex_comp(args[cur_arg + 1], 1, 1, &error))) {
+                                       ha_alert("parsing [%s:%d] : '%s %s %s' : regular expression '%s': %s.\n",
                                                 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
                                        free(error);
                                        err_code |= ERR_ALERT | ERR_FATAL;
@@ -2952,16 +2942,11 @@ stats_error_parsing:
                                }
                                curproxy->options2 |= PR_O2_EXP_RSTR;
                                free(curproxy->expect_str);
-                               if (curproxy->expect_regex) {
-                                       regex_free(curproxy->expect_regex);
-                                       free(curproxy->expect_regex);
-                                       curproxy->expect_regex = NULL;
-                               }
+                               regex_free(curproxy->expect_regex);
                                curproxy->expect_str = strdup(args[cur_arg + 1]);
-                               curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
                                error = NULL;
-                               if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
-                                       ha_alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
+                               if (!(curproxy->expect_regex = regex_comp(args[cur_arg + 1], 1, 1, &error))) {
+                                       ha_alert("parsing [%s:%d] : '%s %s %s' : regular expression '%s': %s.\n",
                                                 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
                                        free(error);
                                        err_code |= ERR_ALERT | ERR_FATAL;
@@ -3258,10 +3243,9 @@ stats_error_parsing:
                                tcpcheck->action = TCPCHK_ACT_EXPECT;
                                tcpcheck->string_len = 0;
                                tcpcheck->string = NULL;
-                               tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
                                error = NULL;
-                               if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
-                                       ha_alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
+                               if (!(tcpcheck->expect_regex = regex_comp(args[cur_arg + 1], 1, 1, &error))) {
+                                       ha_alert("parsing [%s:%d] : '%s %s %s' : regular expression '%s': %s.\n",
                                                 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
                                        free(error);
                                        err_code |= ERR_ALERT | ERR_FATAL;
index a7b4b2fcea7e411543ef155ae9a2ae8eda483959..e6b0bd1d063f37e84143a21c9c3c5cc9ff7208c3 100644 (file)
@@ -3193,8 +3193,7 @@ void email_alert_free(struct email_alert *alert)
                LIST_DEL(&rule->list);
                free(rule->comment);
                free(rule->string);
-               if (rule->expect_regex)
-                       regex_free(rule->expect_regex);
+               regex_free(rule->expect_regex);
                pool_free(pool_head_tcpcheck_rule, rule);
        }
        pool_free(pool_head_email_alert, alert);
index bf91c0b88bbb42db5f9fad280b7a2852bbb018d6..318ebf2f9cd423e478be18d4ad920d6a0058fac1 100644 (file)
@@ -2168,11 +2168,7 @@ void deinit(void)
                }
 
                for (exp = p->req_exp; exp != NULL; ) {
-                       if (exp->preg) {
-                               regex_free(exp->preg);
-                               free(exp->preg);
-                       }
-
+                       regex_free(exp->preg);
                        free((char *)exp->replace);
                        expb = exp;
                        exp = exp->next;
@@ -2180,11 +2176,7 @@ void deinit(void)
                }
 
                for (exp = p->rsp_exp; exp != NULL; ) {
-                       if (exp->preg) {
-                               regex_free(exp->preg);
-                               free(exp->preg);
-                       }
-
+                       regex_free(exp->preg);
                        free((char *)exp->replace);
                        expb = exp;
                        exp = exp->next;
index ff5ffba553e035e0b8967573a8df640b4c64e613..a7fd52baa73d4fb93afab21a2605d60bd9a7681d 100644 (file)
@@ -5366,13 +5366,13 @@ __LJMP static inline int hlua_http_rep_hdr(lua_State *L, struct hlua_txn *htxn,
        const char *name = MAY_LJMP(luaL_checklstring(L, 2, &name_len));
        const char *reg = MAY_LJMP(luaL_checkstring(L, 3));
        const char *value = MAY_LJMP(luaL_checkstring(L, 4));
-       struct my_regex re;
+       struct my_regex *re;
 
-       if (!regex_comp(reg, &re, 1, 1, NULL))
+       if (!(re = regex_comp(reg, 1, 1, NULL)))
                WILL_LJMP(luaL_argerror(L, 3, "invalid regex"));
 
-       http_transform_header_str(htxn->s, msg, name, name_len, value, &re, action);
-       regex_free(&re);
+       http_transform_header_str(htxn->s, msg, name, name_len, value, re, action);
+       regex_free(re);
        return 0;
 }
 
index 60882f3eb48da82a164bc50e055a78cf9c215d1f..3b71ce1bd10ce12671d12a31fc4777f7fa08a9e9 100644 (file)
@@ -1537,14 +1537,14 @@ int hlua_match_addr(lua_State *L)
        return 1;
 }
 
-static struct my_regex *hlua_check_regex(lua_State *L, int ud)
+static struct my_regex **hlua_check_regex(lua_State *L, int ud)
 {
        return (hlua_checkudata(L, ud, class_regex_ref));
 }
 
 static int hlua_regex_comp(struct lua_State *L)
 {
-       struct my_regex *regex;
+       struct my_regex **regex;
        const char *str;
        int cs;
        char *err;
@@ -1556,7 +1556,7 @@ static int hlua_regex_comp(struct lua_State *L)
        regex = lua_newuserdata(L, sizeof(*regex));
 
        err = NULL;
-       if (!regex_comp(str, regex, cs, 1, &err)) {
+       if (!(*regex = regex_comp(str, cs, 1, &err))) {
                lua_pushboolean(L, 0); /* status error */
                lua_pushstring(L, err); /* Reason */
                free(err);
@@ -1576,7 +1576,7 @@ static int hlua_regex_comp(struct lua_State *L)
 
 static int hlua_regex_exec(struct lua_State *L)
 {
-       struct my_regex *regex;
+       struct my_regex **regex;
        const char *str;
        size_t len;
        struct buffer *tmp;
@@ -1584,6 +1584,11 @@ static int hlua_regex_exec(struct lua_State *L)
        regex = hlua_check_regex(L, 1);
        str = luaL_checklstring(L, 2, &len);
 
+       if (!*regex) {
+               lua_pushboolean(L, 0);
+               return 1;
+       }
+
        /* Copy the string because regex_exec2 require a 'char *'
         * and not a 'const char *'.
         */
@@ -1594,14 +1599,14 @@ static int hlua_regex_exec(struct lua_State *L)
        }
        memcpy(tmp->area, str, len);
 
-       lua_pushboolean(L, regex_exec2(regex, tmp->area, len));
+       lua_pushboolean(L, regex_exec2(*regex, tmp->area, len));
 
        return 1;
 }
 
 static int hlua_regex_match(struct lua_State *L)
 {
-       struct my_regex *regex;
+       struct my_regex **regex;
        const char *str;
        size_t len;
        regmatch_t pmatch[20];
@@ -1612,6 +1617,11 @@ static int hlua_regex_match(struct lua_State *L)
        regex = hlua_check_regex(L, 1);
        str = luaL_checklstring(L, 2, &len);
 
+       if (!*regex) {
+               lua_pushboolean(L, 0);
+               return 1;
+       }
+
        /* Copy the string because regex_exec2 require a 'char *'
         * and not a 'const char *'.
         */
@@ -1622,7 +1632,7 @@ static int hlua_regex_match(struct lua_State *L)
        }
        memcpy(tmp->area, str, len);
 
-       ret = regex_exec_match2(regex, tmp->area, len, 20, pmatch, 0);
+       ret = regex_exec_match2(*regex, tmp->area, len, 20, pmatch, 0);
        lua_pushboolean(L, ret);
        lua_newtable(L);
        if (ret) {
@@ -1636,10 +1646,11 @@ static int hlua_regex_match(struct lua_State *L)
 
 static int hlua_regex_free(struct lua_State *L)
 {
-       struct my_regex *regex;
+       struct my_regex **regex;
 
        regex = hlua_check_regex(L, 1);
-       regex_free(regex);
+       regex_free(*regex);
+       *regex = NULL;
        return 0;
 }
 
index c7b5a71e71740c4b3430f39465f57731e8291e97..ab01f264c1b2166ca71f3116cf8244e24868e419 100644 (file)
@@ -263,7 +263,7 @@ struct act_rule *parse_http_req_cond(const char **args, const char *file, int li
                LIST_INIT(&rule->arg.hdr_add.fmt);
 
                error = NULL;
-               if (!regex_comp(args[cur_arg + 1], &rule->arg.hdr_add.re, 1, 1, &error)) {
+               if (!(rule->arg.hdr_add.re = regex_comp(args[cur_arg + 1], 1, 1, &error))) {
                        ha_alert("parsing [%s:%d] : '%s' : %s.\n", file, linenum,
                                 args[cur_arg + 1], error);
                        free(error);
@@ -713,7 +713,7 @@ struct act_rule *parse_http_res_cond(const char **args, const char *file, int li
                LIST_INIT(&rule->arg.hdr_add.fmt);
 
                error = NULL;
-               if (!regex_comp(args[cur_arg + 1], &rule->arg.hdr_add.re, 1, 1, &error)) {
+               if (!(rule->arg.hdr_add.re = regex_comp(args[cur_arg + 1], 1, 1, &error))) {
                        ha_alert("parsing [%s:%d] : '%s' : %s.\n", file, linenum,
                                 args[cur_arg + 1], error);
                        free(error);
@@ -1191,7 +1191,7 @@ void free_http_res_rules(struct list *r)
 
        list_for_each_entry_safe(pr, tr, r, list) {
                LIST_DEL(&pr->list);
-               regex_free(&pr->arg.hdr_add.re);
+               regex_free(pr->arg.hdr_add.re);
                free(pr);
        }
 }
@@ -1205,7 +1205,7 @@ void free_http_req_rules(struct list *r)
                if (pr->action == ACT_HTTP_REQ_AUTH)
                        free(pr->arg.auth.realm);
 
-               regex_free(&pr->arg.hdr_add.re);
+               regex_free(pr->arg.hdr_add.re);
                free(pr);
        }
 }
index 49d05a106b0b4a22cb3e486d36b2a4045e94b418..c93be9b59947865856fb755ee98077b9b775aa03 100644 (file)
@@ -1142,7 +1142,6 @@ void pat_prune_reg(struct pattern_expr *expr)
 
        list_for_each_entry_safe(pat, tmp, &expr->patterns, list) {
                regex_free(pat->pat.ptr.ptr);
-               free(pat->pat.ptr.ptr);
                free(pat->pat.data);
                free(pat);
        }
@@ -1253,18 +1252,9 @@ int pat_idx_list_reg_cap(struct pattern_expr *expr, struct pattern *pat, int cap
        /* duplicate pattern */
        memcpy(&patl->pat, pat, sizeof(*pat));
 
-       /* allocate regex */
-       patl->pat.ptr.reg = calloc(1, sizeof(*patl->pat.ptr.reg));
-       if (!patl->pat.ptr.reg) {
-               free(patl);
-               memprintf(err, "out of memory while indexing pattern");
-               return 0;
-       }
-
        /* compile regex */
-       if (!regex_comp(pat->ptr.str, patl->pat.ptr.reg,
-                       !(expr->mflags & PAT_MF_IGNORE_CASE), cap, err)) {
-               free(patl->pat.ptr.reg);
+       if (!(patl->pat.ptr.reg = regex_comp(pat->ptr.str, !(expr->mflags & PAT_MF_IGNORE_CASE),
+                                            cap, err))) {
                free(patl);
                return 0;
        }
@@ -1562,7 +1552,6 @@ void pat_del_list_reg(struct pattern_expr *expr, struct pat_ref_elt *ref)
                /* Delete and free entry. */
                LIST_DEL(&pat->list);
                regex_free(pat->pat.ptr.ptr);
-               free(pat->pat.ptr.ptr);
                free(pat->pat.data);
                free(pat);
        }
index 2ab33154272a09414820c8eb02b6843284f86b16..b47fbe6351c7598dd27aa6a4aa334da17cf9b402 100644 (file)
@@ -1581,7 +1581,7 @@ resume_execution:
                        if (http_transform_header(s, &txn->req, rule->arg.hdr_add.name,
                                                  rule->arg.hdr_add.name_len,
                                                  &rule->arg.hdr_add.fmt,
-                                                 &rule->arg.hdr_add.re, rule->action)) {
+                                                 rule->arg.hdr_add.re, rule->action)) {
                                rule_ret = HTTP_RULE_RES_BADREQ;
                                goto end;
                        }
@@ -1939,7 +1939,7 @@ resume_execution:
                        if (http_transform_header(s, &txn->rsp, rule->arg.hdr_add.name,
                                                  rule->arg.hdr_add.name_len,
                                                  &rule->arg.hdr_add.fmt,
-                                                 &rule->arg.hdr_add.re, rule->action)) {
+                                                 rule->arg.hdr_add.re, rule->action)) {
                                rule_ret = HTTP_RULE_RES_BADREQ;
                                goto end;
                        }
index 2d1d8fb82b4b79a4edf0ca25605aac24dc912517..b99b9cf9b38a9e9ee71c8c32537ba3608c493a90 100644 (file)
@@ -2901,7 +2901,7 @@ static enum rule_result htx_req_get_intercept_rule(struct proxy *px, struct list
                                if (htx_transform_header(s, &s->req, htx,
                                                         ist2(rule->arg.hdr_add.name, rule->arg.hdr_add.name_len),
                                                         &rule->arg.hdr_add.fmt,
-                                                        &rule->arg.hdr_add.re, rule->action)) {
+                                                        rule->arg.hdr_add.re, rule->action)) {
                                        rule_ret = HTTP_RULE_RES_BADREQ;
                                        goto end;
                                }
@@ -3243,7 +3243,7 @@ resume_execution:
                                if (htx_transform_header(s, &s->res, htx,
                                                         ist2(rule->arg.hdr_add.name, rule->arg.hdr_add.name_len),
                                                         &rule->arg.hdr_add.fmt,
-                                                        &rule->arg.hdr_add.re, rule->action)) {
+                                                        rule->arg.hdr_add.re, rule->action)) {
                                        rule_ret = HTTP_RULE_RES_BADREQ;
                                        goto end;
                                }
index 713f0c9875b63540171525c7f85928e4ec0fbb25..6b86b037e7c9f39ba4471206abcf457c5c7f920d 100644 (file)
@@ -337,13 +337,32 @@ int regex_exec_match2(const struct my_regex *preg, char *subject, int length,
 #endif
 }
 
-int regex_comp(const char *str, struct my_regex *regex, int cs, int cap, char **err)
+struct my_regex *regex_comp(const char *str, int cs, int cap, char **err)
 {
+       struct my_regex *regex = NULL;
 #if defined(USE_PCRE) || defined(USE_PCRE_JIT)
        int flags = 0;
        const char *error;
        int erroffset;
+#elif defined(USE_PCRE2) || defined(USE_PCRE2_JIT)
+       int flags = 0;
+       int errn;
+#if defined(USE_PCRE2_JIT)
+       int jit;
+#endif
+       PCRE2_UCHAR error[256];
+       PCRE2_SIZE erroffset;
+#else
+       int flags = REG_EXTENDED;
+#endif
+
+       regex = calloc(1, sizeof(*regex));
+       if (!regex) {
+               memprintf(err, "not enough memory to build regex");
+               goto out_fail_alloc;
+       }
 
+#if defined(USE_PCRE) || defined(USE_PCRE_JIT)
        if (!cs)
                flags |= PCRE_CASELESS;
        if (!cap)
@@ -352,24 +371,16 @@ int regex_comp(const char *str, struct my_regex *regex, int cs, int cap, char **
        regex->reg = pcre_compile(str, flags, &error, &erroffset, NULL);
        if (!regex->reg) {
                memprintf(err, "regex '%s' is invalid (error=%s, erroffset=%d)", str, error, erroffset);
-               return 0;
+               goto out_fail_alloc;
        }
 
        regex->extra = pcre_study(regex->reg, PCRE_STUDY_JIT_COMPILE, &error);
        if (!regex->extra && error != NULL) {
                pcre_free(regex->reg);
                memprintf(err, "failed to compile regex '%s' (error=%s)", str, error);
-               return 0;
+               goto out_fail_alloc;
        }
 #elif defined(USE_PCRE2) || defined(USE_PCRE2_JIT)
-       int flags = 0;
-       int errn;
-#if defined(USE_PCRE2_JIT)
-       int jit;
-#endif
-       PCRE2_UCHAR error[256];
-       PCRE2_SIZE erroffset;
-
        if (!cs)
                flags |= PCRE2_CASELESS;
        if (!cap)
@@ -379,7 +390,7 @@ int regex_comp(const char *str, struct my_regex *regex, int cs, int cap, char **
        if (!regex->reg) {
                pcre2_get_error_message(errn, error, sizeof(error));
                memprintf(err, "regex '%s' is invalid (error=%s, erroffset=%zu)", str, error, erroffset);
-               return 0;
+               goto out_fail_alloc;
        }
 
 #if defined(USE_PCRE2_JIT)
@@ -391,13 +402,11 @@ int regex_comp(const char *str, struct my_regex *regex, int cs, int cap, char **
        if (jit < 0 && jit != PCRE2_ERROR_JIT_BADOPTION) {
                pcre2_code_free(regex->reg);
                memprintf(err, "regex '%s' jit compilation failed", str);
-               return 0;
+               goto out_fail_alloc;
        }
 #endif
 
 #else
-       int flags = REG_EXTENDED;
-
        if (!cs)
                flags |= REG_ICASE;
        if (!cap)
@@ -405,10 +414,14 @@ int regex_comp(const char *str, struct my_regex *regex, int cs, int cap, char **
 
        if (regcomp(&regex->regex, str, flags) != 0) {
                memprintf(err, "regex '%s' is invalid", str);
-               return 0;
+               goto out_fail_alloc;
        }
 #endif
-       return 1;
+       return regex;
+
+  out_fail_alloc:
+       free(regex);
+       return NULL;
 }
 
 static void regex_register_build_options(void)
index 2a1ce8d5e324f7a38bd17df324453456ddf3b173..67f59e8447ceb2838e10cae21d89e2d7eddf7cd4 100644 (file)
@@ -1328,20 +1328,11 @@ int smp_resolve_args(struct proxy *p)
                                continue;
                        }
 
-                       reg = calloc(1, sizeof(*reg));
-                       if (!reg) {
-                               ha_alert("parsing [%s:%d] : not enough memory to build regex in arg %d of %s%s%s%s '%s' %s proxy '%s'.\n",
-                                        cur->file, cur->line,
-                                        cur->arg_pos + 1, conv_pre, conv_ctx, conv_pos, ctx, cur->kw, where, p->id);
-                               cfgerr++;
-                               continue;
-                       }
-
                        rflags = 0;
                        rflags |= (arg->type_flags & ARGF_REG_ICASE) ? REG_ICASE : 0;
                        err = NULL;
 
-                       if (!regex_comp(arg->data.str.area, reg, !(rflags & REG_ICASE), 1 /* capture substr */, &err)) {
+                       if (!(reg = regex_comp(arg->data.str.area, !(rflags & REG_ICASE), 1 /* capture substr */, &err))) {
                                ha_alert("parsing [%s:%d] : error in regex '%s' in arg %d of %s%s%s%s '%s' %s proxy '%s' : %s.\n",
                                         cur->file, cur->line,
                                         arg->data.str.area,
@@ -1425,11 +1416,8 @@ static void release_sample_arg(struct arg *p)
                        p->unresolved = 0;
                }
                else if (p->type == ARGT_REG) {
-                       if (p->data.reg) {
-                               regex_free(p->data.reg);
-                               free(p->data.reg);
-                               p->data.reg = NULL;
-                       }
+                       regex_free(p->data.reg);
+                       p->data.reg = NULL;
                }
                p++;
        }