perf ui browser: Fix ui popup argv browser for many entries

Fix the argv ui browser code to correctly display more entries than fit
on the screen without crashing. The problem was some type confusion with
pointer types in the ->seek function. Do the argv arithmetic correctly
with char ** pointers. Also add some asserts to find overruns and limit
the display function correctly.

Then finally remove a workaround for this in the res sample browser.

Committer testing:

1) Resize the x terminal to have just some 5 lines

2) Use 'perf report --samples 1' to activate the sample browser options
in the menu

3) Press ENTER, this will cause the crash:

# perf report --samples 1
perf: Segmentation fault
-------- backtrace --------
perf[0x5a514a]
/lib64/libc.so.6(+0x385bf)[0x7f27281b55bf]
/lib64/libc.so.6(+0x161a67)[0x7f27282dea67]
/lib64/libslang.so.2(SLsmg_write_wrapped_string+0x82)[0x7f272874a0b2]
perf(ui_browser__argv_refresh+0x77)[0x5939a7]
perf[0x5924cc]
perf(ui_browser__run+0x39)[0x593449]
perf(ui__popup_menu+0x83)[0x5a5263]
perf[0x59f421]
perf(perf_evlist__tui_browse_hists+0x3a0)[0x5a3780]
perf(cmd_report+0x2746)[0x447136]
perf[0x4a95fe]
perf(main+0x61c)[0x42dc6c]
/lib64/libc.so.6(__libc_start_main+0xf2)[0x7f27281a1412]
perf(_start+0x2d)[0x42de9d]
#

After applying this patch no crash takes place in such situation.

Signed-off-by: Andi Kleen <ak@linux.intel.com>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Acked-by: Jiri Olsa <jolsa@kernel.org>
Link: http://lkml.kernel.org/r/20190311144502.15423-12-andi@firstfloor.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

authored by

Andi Kleen and committed by
Arnaldo Carvalho de Melo
59c24980 905e4aff

+7 -6
+7 -3
tools/perf/ui/browser.c
··· 611 611 browser->top = browser->entries; 612 612 break; 613 613 case SEEK_CUR: 614 - browser->top = browser->top + browser->top_idx + offset; 614 + browser->top = (char **)browser->top + offset; 615 615 break; 616 616 case SEEK_END: 617 - browser->top = browser->top + browser->nr_entries - 1 + offset; 617 + browser->top = (char **)browser->entries + browser->nr_entries - 1 + offset; 618 618 break; 619 619 default: 620 620 return; 621 621 } 622 + assert((char **)browser->top < (char **)browser->entries + browser->nr_entries); 623 + assert((char **)browser->top >= (char **)browser->entries); 622 624 } 623 625 624 626 unsigned int ui_browser__argv_refresh(struct ui_browser *browser) ··· 632 630 browser->top = browser->entries; 633 631 634 632 pos = (char **)browser->top; 635 - while (idx < browser->nr_entries) { 633 + while (idx < browser->nr_entries && 634 + row < (unsigned)SLtt_Screen_Rows - 1) { 635 + assert(pos < (char **)browser->entries + browser->nr_entries); 636 636 if (!browser->filter || !browser->filter(browser, *pos)) { 637 637 ui_browser__gotorc(browser, row, 0); 638 638 browser->write(browser, pos, row);
-3
tools/perf/ui/browsers/res_sample.c
··· 36 36 struct res_sample *r; 37 37 char extra_format[256]; 38 38 39 - /* For now since ui__popup_menu doesn't like lists that don't fit */ 40 - num_res = max(min(SLtt_Screen_Rows - 4, num_res), 0); 41 - 42 39 names = calloc(num_res, sizeof(char *)); 43 40 if (!names) 44 41 return -1;