[PATCH smatch 3/4] smatch: record free callsites for assigned struct members
Harshit Mogalapalli <[email protected]> Wed, 22 Apr 2026 07:32:18 -0700
| Newsgroups | org.kernel.vger.smatch |
|---|---|
| Message-ID | <[email protected]> |
Smatch tracks member freed-state flow but does not record which free routine was used for each assigned struct member in function_type_info. Add smatch_free_locations and wire it into the checker list and build. The checker hooks definite and maybe-free paths, filters to real member dereferences, extracts destination struct type/member, and stores the free kind and free function name. This records free-site provenance for teardown paths and makes member free-site queries directly available to tooling. Assisted-by: Codex:gpt-5.3-codex Co-developed-by: Dan Carpenter <[email protected]> Signed-off-by: Harshit Mogalapalli <[email protected]> --- Makefile | 1 + check_list.h | 1 + smatch_free_locations.c | 88 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 90 insertions(+) create mode 100644 smatch_free_locations.c diff --git a/Makefile b/Makefile index 1b8bd34ffd92..d5cfbd4b2593 100644 --- a/Makefile +++ b/Makefile @@ -285,6 +285,7 @@ SMATCH_OBJS += smatch_files.o SMATCH_OBJS += smatch_flow.o SMATCH_OBJS += smatch_fn_arg_link.o SMATCH_OBJS += smatch_free.o +SMATCH_OBJS += smatch_free_locations.o SMATCH_OBJS += smatch_free_return_states.o SMATCH_OBJS += smatch_fresh_alloc.o SMATCH_OBJS += smatch_function_hooks.o diff --git a/check_list.h b/check_list.h index 330d43a12fb4..fb7883aa9f2f 100644 --- a/check_list.h +++ b/check_list.h @@ -87,6 +87,7 @@ CK(register_state_assigned) CK(register_points_to_container) CK(register_allocations) CK(register_allocations_locations) +CK(register_free_locations) CK(register_units) CK(register_goto_tracker) CK(register_refcount) diff --git a/smatch_free_locations.c b/smatch_free_locations.c new file mode 100644 index 000000000000..03858be3f9a6 --- /dev/null +++ b/smatch_free_locations.c @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2026 Oracle. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see http://www.gnu.org/copyleft/gpl.txt + */ + +#include "smatch.h" +#include "smatch_extra.h" + +static const char *get_free_fn_name(struct expression *expr) +{ + struct expression *call; + const char *fn_name; + + call = get_assigned_call(expr); + if (!call) + return NULL; + + fn_name = get_fn_name(call->fn); + return fn_name; +} + +static void match_free_member(struct expression *expr, const char *name, struct symbol *sym, bool maybe) +{ + struct expression *arg; + struct symbol *type; + const char *fn_name; + char *type_str; + char *member; + + if (__in_fake_assign) + return; + + arg = gen_expression_from_name_sym(name, sym); + if (!arg) + return; + arg = strip_expr(arg); + if (!arg || arg->type != EXPR_DEREF || !arg->member) + return; + + type = get_type(arg->deref); + if (!type || !type->ident) + return; + + type_str = type_to_str(type); + if (!type_str) + return; + + member = get_member_name_no_prefix(arg); + if (!member) + return; + + fn_name = get_free_fn_name(expr); + if (!fn_name) + return; + + if (maybe) + sql_insert_function_type_info(MAYBE_FREED, type_str, member, fn_name); + else + sql_insert_function_type_info(PARAM_FREED, type_str, member, fn_name); +} + +static void match_free(struct expression *expr, const char *name, struct symbol *sym) +{ + match_free_member(expr, name, sym, false); +} + +static void match_maybe_free(struct expression *expr, const char *name, struct symbol *sym) +{ + match_free_member(expr, name, sym, true); +} + +void register_free_locations(int id) +{ + add_free_hook(&match_free); + add_maybe_free_hook(&match_maybe_free); +} -- 2.47.3