[PATCH smatch-devel 3/5] smatch: track functions variables are passed to

Harshit Mogalapalli <[email protected]>
Newsgroups org.kernel.vger.smatch
Message-ID <[email protected]>
Record every direct variable argument handled by FUNCTION_CALL_HOOK.
Keep the call expression, zero-based parameter index, and previous
sm_state in a linked smatch_state data payload.

Expose print_passed_to() to walk linear and merged histories.
Deduplicate shared states and print each function with its $N index.

Assisted-by: Codex:5.6
Signed-off-by: Harshit Mogalapalli <[email protected]>
---
 Makefile           |   1 +
 smatch.h           |   1 +
 smatch_modules.h   |   1 +
 smatch_passed_to.c | 111 +++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 114 insertions(+)
 create mode 100644 smatch_passed_to.c

diff --git a/Makefile b/Makefile
index eabaef4c8e01..85517e4660e6 100644
--- a/Makefile
+++ b/Makefile
@@ -353,6 +353,7 @@ SMATCH_OBJS += smatch_parents.o
 SMATCH_OBJS += smatch_parse_call_math.o
 SMATCH_OBJS += smatch_parsed_conditions.o
 SMATCH_OBJS += smatch_passes_array_size.o
+SMATCH_OBJS += smatch_passed_to.o
 SMATCH_OBJS += smatch_points_to_container.o
 SMATCH_OBJS += smatch_points_to_user_data.o
 SMATCH_OBJS += smatch_points_to_host_data.o
diff --git a/smatch.h b/smatch.h
index 681be3354bc1..58edc256965a 100644
--- a/smatch.h
+++ b/smatch.h
@@ -1050,6 +1050,7 @@ void __call_array_initialized_hooks(struct expression *array, int nr);
 /* smatch_function_hooks.c */
 const char *get_fn_name(struct expression *fn);
 struct expression *get_current_fn_call(void);
+void print_passed_to(struct expression *expr);
 void add_fake_call_after_return(struct expression *call);
 struct expression *get_real_call(void);
 struct expression *get_this_fn_call(void);
diff --git a/smatch_modules.h b/smatch_modules.h
index c8fd14f5dca0..dbc8fa4dd0dc 100644
--- a/smatch_modules.h
+++ b/smatch_modules.h
@@ -107,6 +107,7 @@ CK(smatch_parameter_names)
 CK(smatch_param_filter)
 CK(smatch_param_to_mtag_data)
 CK(smatch_parse_call_math)
+CK(smatch_passed_to)
 CK(smatch_points_to_container)
 CK(smatch_points_to_host_data)
 CK(smatch_points_to_user_data)
diff --git a/smatch_passed_to.c b/smatch_passed_to.c
new file mode 100644
index 000000000000..06b1e2a77fec
--- /dev/null
+++ b/smatch_passed_to.c
@@ -0,0 +1,111 @@
+#include "smatch.h"
+
+static int my_id;
+
+struct smatch_state_data {
+	struct sm_state *previous;
+	struct expression *expr;
+	int param;
+};
+
+static struct smatch_state *alloc_passed_to_state(const char *fn_name,
+						  struct expression *expr,
+						  int param,
+						  struct sm_state *previous)
+{
+	struct smatch_state_data *data;
+	struct smatch_state *state;
+
+	state = __alloc_smatch_state(sizeof(*data));
+	data = (struct smatch_state_data *)(state + 1);
+
+	state->name = alloc_sname(fn_name);
+	state->data = data;
+	data->previous = previous;
+	data->expr = expr;
+	data->param = param;
+
+	return state;
+}
+
+static void save_passed_to(const char *fn_name, struct expression *expr, int param,
+			   struct expression *arg)
+{
+	struct smatch_state *state;
+	struct sm_state *previous;
+	struct symbol *sym;
+	char *name;
+
+	name = expr_to_var_sym(arg, &sym);
+	if (!name || !sym)
+		goto free;
+
+	previous = get_sm_state(my_id, name, sym);
+	state = alloc_passed_to_state(fn_name, expr, param, previous);
+	set_state(my_id, name, sym, state);
+free:
+	free_string(name);
+}
+
+static void match_call(struct expression *expr)
+{
+	struct expression *arg;
+	char *fn_name;
+	int param = -1;
+
+	if (sym_name_is(expr->fn, "__smatch_passed_to"))
+		return;
+
+	fn_name = expr_to_str(expr->fn);
+	if (!fn_name)
+		return;
+
+	FOR_EACH_PTR(expr->args, arg) {
+		save_passed_to(fn_name, expr, ++param, arg);
+	} END_FOR_EACH_PTR(arg);
+
+	free_string(fn_name);
+}
+
+static void print_passed_to_sm(struct sm_state *sm, struct state_list **printed)
+{
+	struct smatch_state_data *data;
+	char *fn_name;
+
+	if (!sm)
+		return;
+	if (lookup_ptr_list_entry((struct ptr_list *)*printed, sm))
+		return;
+	add_ptr_list(printed, sm);
+
+	data = sm->state->data;
+	if (!data) {
+		print_passed_to_sm(sm->left, printed);
+		print_passed_to_sm(sm->right, printed);
+		return;
+	}
+
+	print_passed_to_sm(data->previous, printed);
+
+	fn_name = expr_to_str(data->expr->fn);
+	if (!fn_name)
+		return;
+	sm_msg("passed to %s $%d", fn_name, data->param);
+	free_string(fn_name);
+}
+
+void print_passed_to(struct expression *expr)
+{
+	struct state_list *printed = NULL;
+
+	print_passed_to_sm(get_sm_state_expr(my_id, expr), &printed);
+	free_slist(&printed);
+}
+
+void smatch_passed_to(int id)
+{
+	my_id = id;
+
+	set_dynamic_states(my_id);
+	add_hook(&match_call, FUNCTION_CALL_HOOK);
+}
-- 
2.52.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.