diff --git a/tools/perf/ui/gtk/hists.c b/tools/perf/ui/gtk/hists.c index 716dcf02bd0e..80df3fec8ea1 100644 --- a/tools/perf/ui/gtk/hists.c +++ b/tools/perf/ui/gtk/hists.c @@ -449,7 +449,7 @@ static void perf_gtk__add_hierarchy_entries(struct hists *hists, bf = hpp->buf; size = hpp->size; perf_hpp_list__for_each_format(he->hpp_list, fmt) { - int ret; + int ret, inc; if (fmt->color) ret = fmt->color(fmt, hpp, he); @@ -457,15 +457,26 @@ static void perf_gtk__add_hierarchy_entries(struct hists *hists, ret = fmt->entry(fmt, hpp, he); snprintf(hpp->buf + ret, hpp->size - ret, " "); - advance_hpp(hpp, ret + 2); + /* + * ret can be as large as hpp->size - 1, so ret + 2 + * can exceed hpp->size. advance_hpp() doesn't clamp, + * so passing that through would underflow the + * size_t hpp->size and let a later fmt->entry() in + * this loop write past the end of the caller's + * stack buffer. + */ + inc = ret + 2; + if (inc > (int)hpp->size) + inc = hpp->size; + advance_hpp(hpp, inc); } gtk_tree_store_set(store, &iter, col_idx, strim(bf), -1); - if (!he->leaf) { - hpp->buf = bf; - hpp->size = size; + hpp->buf = bf; + hpp->size = size; + if (!he->leaf) { perf_gtk__add_hierarchy_entries(hists, &he->hroot_out, store, &iter, hpp, min_pcnt); @@ -505,6 +516,7 @@ static void perf_gtk__show_hierarchy(GtkWidget *window, struct hists *hists, GtkWidget *view; int col_idx; int nr_cols = 0; + int ret; char s[512]; char buf[512]; bool first_node, first_col; @@ -541,9 +553,10 @@ static void perf_gtk__show_hierarchy(GtkWidget *window, struct hists *hists, /* construct merged column header since sort keys share single column */ buf[0] = '\0'; first_node = true; + ret = 0; list_for_each_entry_continue(fmt_node, &hists->hpp_formats, list) { if (!first_node) - strcat(buf, " / "); + ret += scnprintf(buf + ret, sizeof(buf) - ret, " / "); first_node = false; first_col = true; @@ -552,11 +565,11 @@ static void perf_gtk__show_hierarchy(GtkWidget *window, struct hists *hists, continue; if (!first_col) - strcat(buf, "+"); + ret += scnprintf(buf + ret, sizeof(buf) - ret, "+"); first_col = false; fmt->header(fmt, &hpp, hists, 0, NULL); - strcat(buf, strim(hpp.buf)); + ret += scnprintf(buf + ret, sizeof(buf) - ret, "%s", strim(hpp.buf)); } }