Re: [PATCH v4 4/6] perf probe-finder: Fix libdw API contract violations

From: Namhyung Kim

Date: Sun May 03 2026 - 19:49:55 EST


On Sun, May 03, 2026 at 10:10:30AM -0700, Ian Rogers wrote:
> Check return values of `dwarf_formsdata`, `dwarf_entrypc`,
> `dwarf_highpc`, `dwarf_bytesize`, `dwarf_attr`, `dwarf_decl_line`,
> `dwarf_getfuncs`, and `dwarf_formref_die`. Validate `dwarf_diename` and
> `dwarf_diecu` results to prevent potential crashes. Fix C90 mixed
> declarations.
>
> Additionally:
> - Avoid vfprintf undefined behavior with NULL strings by using the
> `die_name()` helper for `dwarf_diename()` in `pr_*` calls,
> including when warning about tail calls.
> - Prevent NULL pointer dereference in `convert_variable_fields()`
> when processing array elements for variables in registers.
> - Fallback to offset 0 in `line_range_search_cb()` instead of
> skipping functions without `DW_AT_decl_line`.
> - Relax `dwarf_getfuncs` error checking in
> `find_probe_point_by_func()` and `find_line_range_by_func()` to
> prevent premature CU search aborts, ensuring robustness against
> corrupted CUs.
>
> Fixes: 66f69b219716 ("perf probe: Support DW_AT_const_value constant value")
> Fixes: 3d918a12a1b3 ("perf probe: Find fentry mcount fuzzed parameter location")
> Fixes: bcfc082150c6 ("perf probe: Remove redundant dwarf functions")
> Fixes: 221d061182b8 ("perf probe: Fix to search local variables in appropriate scope")
> Fixes: b55a87ade383 ("perf probe: Remove die() from probe-finder code")
> Fixes: 4c859351226c ("perf probe: Support glob wildcards for function name")
> Assisted-by: Gemini-CLI:Google Gemini 3
> Signed-off-by: Ian Rogers <irogers@xxxxxxxxxx>
> ---
[SNIP]
> @@ -1293,13 +1318,17 @@ static int add_probe_trace_event(Dwarf_Die *sc_die, struct probe_finder *pf)
> if (ret < 0)
> goto end;
>
> - tev->point.realname = strdup(dwarf_diename(sc_die));
> + realname = dwarf_diename(sc_die);
> + tev->point.realname = strdup(realname ?: "unknown");

Could be:

tev->point.realname = strdup(die_name(sc_die));


> if (!tev->point.realname) {
> ret = -ENOMEM;
> goto end;
> }
>
> - tev->lang = dwarf_srclang(dwarf_diecu(sc_die, &pf->cu_die, NULL, NULL));
> + if (dwarf_diecu(sc_die, &cu_die_mem, NULL, NULL) != NULL)

I think it should fill pf->cu_die.

Thanks,
Namhyung


> + tev->lang = dwarf_srclang(&cu_die_mem);
> + else
> + tev->lang = DW_LANG_C; // Fallback
>
> pr_debug("Probe point found: %s+%lu\n", tev->point.symbol,
> tev->point.offset);
> @@ -1794,7 +1823,8 @@ static int line_range_search_cb(Dwarf_Die *sp_die, void *data)
>
> if (die_match_name(sp_die, lr->function) && die_is_func_def(sp_die)) {
> lf->fname = die_get_decl_file(sp_die);
> - dwarf_decl_line(sp_die, &lr->offset);
> + if (dwarf_decl_line(sp_die, &lr->offset) != 0)
> + lr->offset = 0; // Fallback if no line info
> pr_debug("fname: %s, lineno:%d\n", lf->fname, lr->offset);
> lf->lno_s = lr->offset + lr->start;
> if (lf->lno_s < 0) /* Overflow */
> @@ -1818,7 +1848,8 @@ static int line_range_search_cb(Dwarf_Die *sp_die, void *data)
> static int find_line_range_by_func(struct line_finder *lf)
> {
> struct dwarf_callback_param param = {.data = (void *)lf, .retval = 0};
> - dwarf_getfuncs(&lf->cu_die, line_range_search_cb, &param, 0);
> + if (dwarf_getfuncs(&lf->cu_die, line_range_search_cb, &param, 0) < 0)
> + pr_debug("Failed to get functions from CU\n");
> return param.retval;
> }
>
> --
> 2.54.0.545.g6539524ca2-goog
>