diff --git a/include/haproxy/listener.h b/include/haproxy/listener.h index 17fe9e090..a8c798c53 100644 --- a/include/haproxy/listener.h +++ b/include/haproxy/listener.h @@ -174,19 +174,27 @@ unsigned int bind_map_thread_id(const struct bind_conf *conf, unsigned int r); /* allocate an bind_conf struct for a bind line, and chain it to the frontend . * If is not NULL, it is duplicated into ->arg to store useful config - * information for error reporting. + * information for error reporting. NULL is returned on error. */ static inline struct bind_conf *bind_conf_alloc(struct proxy *fe, const char *file, int line, const char *arg, struct xprt_ops *xprt) { struct bind_conf *bind_conf = calloc(1, sizeof(struct bind_conf)); - bind_conf->file = strdup(file); - bind_conf->line = line; - LIST_ADDQ(&fe->conf.bind, &bind_conf->by_fe); - if (arg) - bind_conf->arg = strdup(arg); + if (!bind_conf) + goto err; + bind_conf->file = strdup(file); + if (!bind_conf->file) + goto err; + bind_conf->line = line; + if (arg) { + bind_conf->arg = strdup(arg); + if (!bind_conf->arg) + goto err; + } + + LIST_ADDQ(&fe->conf.bind, &bind_conf->by_fe); bind_conf->settings.ux.uid = -1; bind_conf->settings.ux.gid = -1; bind_conf->settings.ux.mode = 0; @@ -200,6 +208,14 @@ static inline struct bind_conf *bind_conf_alloc(struct proxy *fe, const char *fi #endif LIST_INIT(&bind_conf->listeners); return bind_conf; + + err: + if (bind_conf) { + ha_free(&bind_conf->file); + ha_free(&bind_conf->arg); + } + ha_free(&bind_conf); + return NULL; } static inline const char *listener_state_str(const struct listener *l) diff --git a/src/cfgparse-listen.c b/src/cfgparse-listen.c index fba6d019d..3038beb14 100644 --- a/src/cfgparse-listen.c +++ b/src/cfgparse-listen.c @@ -387,7 +387,11 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm) } bind_conf = bind_conf_alloc(curproxy, file, linenum, args[1], xprt_get(XPRT_RAW)); - + if (!bind_conf) { + ha_alert("Out of memory error.\n"); + err_code |= ERR_ALERT | ERR_ABORT; + goto out; + } /* use default settings for unix sockets */ bind_conf->settings.ux.uid = global.unix_bind.ux.uid; bind_conf->settings.ux.gid = global.unix_bind.ux.gid; diff --git a/src/cli.c b/src/cli.c index 32d7efbe0..13603df5d 100644 --- a/src/cli.c +++ b/src/cli.c @@ -401,6 +401,10 @@ static int cli_parse_global(char **args, int section_type, struct proxy *curpx, } bind_conf = bind_conf_alloc(global.cli_fe, file, line, args[2], xprt_get(XPRT_RAW)); + if (!bind_conf) { + memprintf(err, "'%s %s' : out of memory trying to allocate a bind_conf", args[0], args[1]); + return -1; + } bind_conf->level &= ~ACCESS_LVL_MASK; bind_conf->level |= ACCESS_LVL_OPER; /* default access level */ diff --git a/src/log.c b/src/log.c index 2931ee96d..7930c52ef 100644 --- a/src/log.c +++ b/src/log.c @@ -4031,6 +4031,11 @@ int cfg_parse_log_forward(const char *file, int linenum, char **args, int kwm) bind_conf = bind_conf_alloc(cfg_log_forward, file, linenum, NULL, xprt_get(XPRT_RAW)); + if (!bind_conf) { + ha_alert("parsing [%s:%d] : out of memory error.", file, linenum); + err_code |= ERR_ALERT | ERR_FATAL; + goto out; + } if (!str2receiver(args[1], cfg_log_forward, bind_conf, file, linenum, &errmsg)) { if (errmsg && *errmsg) {