Fix potential memory leak. Function new_term may return error, so it is need to free memory when the return value is negative. What's more, add jump targets so that a configuration object and a duplicated string are released after a call of the function "strdup" or "new_term" failed.
Fixes: b6645a723595 ("perf parse: Ensure config and str in terms are unique") Signed-off-by: Chen Wandun <chenwan...@huawei.com> --- tools/perf/util/parse-events.c | 47 ++++++++++++++++++++++++++-------- 1 file changed, 37 insertions(+), 10 deletions(-) diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 6f4dc8a92817..a9f32032af08 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -2947,6 +2947,7 @@ int parse_events_term__sym_hw(struct parse_events_term **term, .type_term = PARSE_EVENTS__TERM_TYPE_USER, .config = config, }; + int ret; if (!temp.config) { temp.config = strdup("event"); @@ -2958,12 +2959,23 @@ int parse_events_term__sym_hw(struct parse_events_term **term, str = strdup(sym->symbol); if (!str) { - if (!config) - free(temp.config); - return -ENOMEM; + ret = -ENOMEM; + goto free_config; } - return new_term(term, &temp, str, 0); + ret = new_term(term, &temp, str, 0); + if (ret) + goto free_str; + + return 0; + +free_str: + free(str); +free_config: + if (!config) + free(temp.config); + + return ret; } int parse_events_term__clone(struct parse_events_term **new, @@ -2977,23 +2989,38 @@ int parse_events_term__clone(struct parse_events_term **new, .err_term = term->err_term, .err_val = term->err_val, }; + int ret; if (term->config) { temp.config = strdup(term->config); if (!temp.config) return -ENOMEM; } - if (term->type_val == PARSE_EVENTS__TERM_TYPE_NUM) - return new_term(new, &temp, NULL, term->val.num); + if (term->type_val == PARSE_EVENTS__TERM_TYPE_NUM) { + ret = new_term(new, &temp, NULL, term->val.num); + if (ret) + goto free_config; + } str = strdup(term->val.str); if (!str) { - if (term->config) - free(temp.config); - return -ENOMEM; + ret = -ENOMEM; + goto free_config; } - return new_term(new, &temp, str, 0); + ret = new_term(new, &temp, str, 0); + if (ret) + goto free_str; + + return 0; + +free_str: + free(str); +free_config: + if (term->config) + free(temp.config); + + return ret; } void parse_events_term__delete(struct parse_events_term *term) -- 2.17.1