Smatch (Semantic Matching Tool) development
 help / color / mirror / Atom feed
* [PATCH smatch-devel 1/5] docs: document selecting individual Smatch checks
@ 2026-08-18 13:03 Harshit Mogalapalli
  2026-08-18 13:03 ` [PATCH smatch-devel 2/5] smatch: prevent recursive --ai state dumps Harshit Mogalapalli
                   ` (4 more replies)
  0 siblings, 5 replies; 6+ messages in thread
From: Harshit Mogalapalli @ 2026-08-18 13:03 UTC (permalink / raw)
  To: error27; +Cc: smatch, Harshit Mogalapalli

Smatch can limit a run to selected checker registration functions with
--enable, but the kchecker documentation does not describe this useful
development and triage workflow.

Document how to list and select checks, enable companion hooks, and
choose a cross-function database.  Also explain that
smatch_db.sqlite.new is a staging file which is promoted only after a
successful database build.

Assisted-by: Codex:gpt-5.6
Signed-off-by: Harshit Mogalapalli <harshit.m.mogalapalli@oracle.com>
---
 Documentation/smatch.rst | 43 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 43 insertions(+)

diff --git a/Documentation/smatch.rst b/Documentation/smatch.rst
index 4d5cbf34896d..24ff5540601c 100644
--- a/Documentation/smatch.rst
+++ b/Documentation/smatch.rst
@@ -71,6 +71,49 @@ You can also build a directory like this::
 
 The kchecker script prints its warnings to stdout.
 
+Running a single check
+----------------------
+
+Use ``--show-checks`` to list the available check names::
+
+	~/path/to/smatch_dir/smatch --show-checks
+
+Pass ``--enable=<name>`` to kchecker to run one check while retaining the
+internal Smatch infrastructure that the check depends on.  The ``check_``
+prefix is optional::
+
+	~/path/to/smatch_dir/smatch_scripts/kchecker --spammy \
+		--enable=uninitialized drivers/whatever/file.c
+
+Multiple checks can be enabled with a comma-separated list::
+
+	~/path/to/smatch_dir/smatch_scripts/kchecker --spammy \
+		--enable=uninitialized,unreachable \
+		drivers/whatever/file.c
+
+Some source files register companion checks, such as an ``_info`` function
+used when generating cross-function data.  List each companion explicitly
+when it is needed.  For example, the unwind checker registers both
+``check_unwind`` and ``check_unwind_info``::
+
+	~/path/to/smatch_dir/smatch_scripts/kchecker --spammy \
+		--enable=unwind,unwind_info drivers/whatever/file.c
+
+Smatch reads ``smatch_db.sqlite`` from the current directory by default.  Use
+``--db-file=<path>`` to select a different cross-function database::
+
+	~/path/to/smatch_dir/smatch_scripts/kchecker --spammy \
+		--enable=uninitialized \
+		--db-file=~/path/to/kernel_dir/smatch_db.sqlite \
+		drivers/whatever/file.c
+
+The database builder creates ``smatch_db.sqlite.new`` as a staging file.  Once
+the build and its sanity check complete, it renames that file to
+``smatch_db.sqlite``.  A leftover ``.new`` file therefore belongs to an
+in-progress, interrupted, or failed database build and may be incomplete.  Do
+not select it for normal checking; finish or rerun ``build_kernel_data.sh`` so
+that a validated database is promoted to ``smatch_db.sqlite``.
+
 The above scripts will ensure that any ARCH or CROSS_COMPILE environment
 variables are passed to kernel build system - thus allowing for the use of
 Smatch with kernels that are normally built with cross-compilers.
-- 
2.52.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH smatch-devel 2/5] smatch: prevent recursive --ai state dumps
  2026-08-18 13:03 [PATCH smatch-devel 1/5] docs: document selecting individual Smatch checks Harshit Mogalapalli
@ 2026-08-18 13:03 ` Harshit Mogalapalli
  2026-08-18 13:03 ` [PATCH smatch-devel 3/5] smatch: track functions variables are passed to Harshit Mogalapalli
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Harshit Mogalapalli @ 2026-08-18 13:03 UTC (permalink / raw)
  To: error27; +Cc: smatch, Harshit Mogalapalli

The --ai report wrapper prints the current stree after every diagnostic.
__print_stree() emits each state with sm_msg(), so those messages start
new AI reports and dump the same stree recursively until stack overflow.

Disable AI report wrapping while serializing a stree, then restore the
option after the dump.  Normal diagnostics and each outer AI report keep
their existing output, while nested dump messages cannot recurse.

Fixes: 47487a9dbf4e ("smatch: add broken --ai option")
Assisted-by: Codex:5.6
Signed-off-by: Harshit Mogalapalli <harshit.m.mogalapalli@oracle.com>
---
 smatch.h | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/smatch.h b/smatch.h
index 0db2062e1f5d..681be3354bc1 100644
--- a/smatch.h
+++ b/smatch.h
@@ -447,7 +447,10 @@ do {                                                           \
         sm_printf(msg);                                        \
         sm_printf("\n");                                       \
 	if (option_ai) {				       \
+		int __saved_option_ai = option_ai;	       \
+		option_ai = 0;				       \
 		__print_cur_stree();			       \
+		option_ai = __saved_option_ai;		       \
 		sm_printf("end report: %d\n", __this_warn);    \
 	}						       \
 } while (0)
-- 
2.52.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH smatch-devel 3/5] smatch: track functions variables are passed to
  2026-08-18 13:03 [PATCH smatch-devel 1/5] docs: document selecting individual Smatch checks Harshit Mogalapalli
  2026-08-18 13:03 ` [PATCH smatch-devel 2/5] smatch: prevent recursive --ai state dumps Harshit Mogalapalli
@ 2026-08-18 13:03 ` Harshit Mogalapalli
  2026-08-18 13:03 ` [PATCH smatch-devel 4/5] smatch: add passed-to debug helper Harshit Mogalapalli
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Harshit Mogalapalli @ 2026-08-18 13:03 UTC (permalink / raw)
  To: error27; +Cc: smatch, Harshit Mogalapalli

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 <harshit.m.mogalapalli@oracle.com>
---
 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


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH smatch-devel 4/5] smatch: add passed-to debug helper
  2026-08-18 13:03 [PATCH smatch-devel 1/5] docs: document selecting individual Smatch checks Harshit Mogalapalli
  2026-08-18 13:03 ` [PATCH smatch-devel 2/5] smatch: prevent recursive --ai state dumps Harshit Mogalapalli
  2026-08-18 13:03 ` [PATCH smatch-devel 3/5] smatch: track functions variables are passed to Harshit Mogalapalli
@ 2026-08-18 13:03 ` Harshit Mogalapalli
  2026-08-18 13:03 ` [PATCH smatch-devel 5/5] smatch: report passed-to history for --ai Harshit Mogalapalli
  2026-08-18 13:11 ` [PATCH smatch-devel 1/5] docs: document selecting individual Smatch checks Dan Carpenter
  4 siblings, 0 replies; 6+ messages in thread
From: Harshit Mogalapalli @ 2026-08-18 13:03 UTC (permalink / raw)
  To: error27; +Cc: smatch, Harshit Mogalapalli

Add __smatch_passed_to() to check_debug so validation and developers can
print the linked call history for a variable expression.

Cover sequential calls using different argument positions and verify the
reported $N indexes.

Assisted-by: Codex:5.6
Signed-off-by: Harshit Mogalapalli <harshit.m.mogalapalli@oracle.com>
---
 check_debug.c             |  9 +++++++++
 check_debug.h             |  3 +++
 validation/sm_passed_to.c | 21 +++++++++++++++++++++
 3 files changed, 33 insertions(+)
 create mode 100644 validation/sm_passed_to.c

diff --git a/check_debug.c b/check_debug.c
index 30b9e617ca5d..59970412a491 100644
--- a/check_debug.c
+++ b/check_debug.c
@@ -782,6 +782,14 @@ static void match_about(const char *fn, struct expression *expr, void *info)
 	debug_print_about(arg);
 }
 
+static void match_passed_to(const char *fn, struct expression *expr, void *info)
+{
+	struct expression *arg;
+
+	arg = get_check_arg(expr, 0);
+	print_passed_to(arg);
+}
+
 static void match_intersection(const char *fn, struct expression *expr, void *info)
 {
 	struct expression *one, *two;
@@ -1173,6 +1181,7 @@ void check_debug(int id)
 	my_id = id;
 
 	add_function_hook("__smatch_about", &match_about, NULL);
+	add_function_hook("__smatch_passed_to", &match_passed_to, NULL);
 	add_function_hook("__smatch_all_values", &match_all_values, NULL);
 	add_function_hook("__smatch_state", &match_state, NULL);
 	add_function_hook("__smatch_states", &match_states, NULL);
diff --git a/check_debug.h b/check_debug.h
index 59714b7b82ab..5758919059cf 100644
--- a/check_debug.h
+++ b/check_debug.h
@@ -6,6 +6,9 @@
 static inline void __smatch_about(long var){}
 #define __smatch_about(x) __smatch_about(cast_ptr(x))
 
+static inline void __smatch_passed_to(long var){}
+#define __smatch_passed_to(x) __smatch_passed_to(cast_ptr(x))
+
 static inline void __smatch_cur_stree(void){}
 static inline void __smatch_all_values(void){}
 static inline void __smatch_state(const char *check_name, const char *state_name){}
diff --git a/validation/sm_passed_to.c b/validation/sm_passed_to.c
new file mode 100644
index 000000000000..57c284f96e22
--- /dev/null
+++ b/validation/sm_passed_to.c
@@ -0,0 +1,21 @@
+#include "check_debug.h"
+
+void first(int ignored, int value);
+void second(int value);
+
+void func(int value)
+{
+	first(0, value);
+	second(value);
+	__smatch_passed_to(value);
+}
+
+/*
+ * check-name: smatch passed to
+ * check-command: smatch -I.. sm_passed_to.c
+ *
+ * check-output-start
+sm_passed_to.c:10 func() passed to first $1
+sm_passed_to.c:10 func() passed to second $0
+ * check-output-end
+ */
-- 
2.52.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH smatch-devel 5/5] smatch: report passed-to history for --ai
  2026-08-18 13:03 [PATCH smatch-devel 1/5] docs: document selecting individual Smatch checks Harshit Mogalapalli
                   ` (2 preceding siblings ...)
  2026-08-18 13:03 ` [PATCH smatch-devel 4/5] smatch: add passed-to debug helper Harshit Mogalapalli
@ 2026-08-18 13:03 ` Harshit Mogalapalli
  2026-08-18 13:11 ` [PATCH smatch-devel 1/5] docs: document selecting individual Smatch checks Dan Carpenter
  4 siblings, 0 replies; 6+ messages in thread
From: Harshit Mogalapalli @ 2026-08-18 13:03 UTC (permalink / raw)
  To: error27; +Cc: smatch, Harshit Mogalapalli

Replace the generic current-state dump in --ai reports with a callback list
so modules can report focused state without recursively dumping every check.

Register the passed-to tracker as the first callback.  Walk its current
states and recursively print each function history with the tracked variable
name and argument number on the same line.

Assisted-by: Codex:5.6
Signed-off-by: Harshit Mogalapalli <harshit.m.mogalapalli@oracle.com>
---
 smatch.h           |  4 +++-
 smatch_hooks.c     | 11 +++++++++++
 smatch_passed_to.c | 29 +++++++++++++++++++++++------
 3 files changed, 37 insertions(+), 7 deletions(-)

diff --git a/smatch.h b/smatch.h
index 58edc256965a..32eec7c3ccd7 100644
--- a/smatch.h
+++ b/smatch.h
@@ -186,6 +186,8 @@ DECLARE_PTR_LIST(name_sym_fn_list, name_sym_hook);
 DECLARE_PTR_LIST(string_hook_list, string_hook);
 DECLARE_PTR_LIST(stree_func_list, stree_func);
 void call_void_fns(struct void_fn_list *list);
+void register_ai_info(void_fn *fn);
+void print_ai_info(void);
 void call_expr_fns(struct expr_fn_list *list, struct expression *expr);
 void call_stmt_fns(struct stmt_fn_list *list, struct statement *stmt);
 void call_sym_fns(struct sym_fn_list *list, struct symbol *sym);
@@ -449,7 +451,7 @@ do {                                                           \
 	if (option_ai) {				       \
 		int __saved_option_ai = option_ai;	       \
 		option_ai = 0;				       \
-		__print_cur_stree();			       \
+		print_ai_info();			       \
 		option_ai = __saved_option_ai;		       \
 		sm_printf("end report: %d\n", __this_warn);    \
 	}						       \
diff --git a/smatch_hooks.c b/smatch_hooks.c
index 0933df9c6787..813c5fbfde56 100644
--- a/smatch_hooks.c
+++ b/smatch_hooks.c
@@ -135,6 +135,17 @@ void add_pre_merge_hook(int client_id, void (*hook)(struct sm_state *cur, struct
 }
 
 struct position *__hook_pos;
+static struct void_fn_list *ai_info_hooks;
+
+void register_ai_info(void_fn *fn)
+{
+	add_ptr_list(&ai_info_hooks, fn);
+}
+
+void print_ai_info(void)
+{
+	call_void_fns(ai_info_hooks);
+}
 
 static void pass_expr_to_client(expr_func *fn, void *data)
 {
diff --git a/smatch_passed_to.c b/smatch_passed_to.c
index 06b1e2a77fec..bc9231715d43 100644
--- a/smatch_passed_to.c
+++ b/smatch_passed_to.c
@@ -67,7 +67,8 @@ static void match_call(struct expression *expr)
 	free_string(fn_name);
 }
 
-static void print_passed_to_sm(struct sm_state *sm, struct state_list **printed)
+static void print_passed_to_sm(struct sm_state *sm, const char *name,
+			       struct state_list **printed)
 {
 	struct smatch_state_data *data;
 	char *fn_name;
@@ -80,17 +81,20 @@ static void print_passed_to_sm(struct sm_state *sm, struct state_list **printed)
 
 	data = sm->state->data;
 	if (!data) {
-		print_passed_to_sm(sm->left, printed);
-		print_passed_to_sm(sm->right, printed);
+		print_passed_to_sm(sm->left, name, printed);
+		print_passed_to_sm(sm->right, name, printed);
 		return;
 	}
 
-	print_passed_to_sm(data->previous, printed);
+	print_passed_to_sm(data->previous, name, printed);
 
 	fn_name = expr_to_str(data->expr->fn);
 	if (!fn_name)
 		return;
-	sm_msg("passed to %s $%d", fn_name, data->param);
+	if (name)
+		sm_msg("%s passed to %s $%d", name, fn_name, data->param);
+	else
+		sm_msg("passed to %s $%d", fn_name, data->param);
 	free_string(fn_name);
 }
 
@@ -98,14 +102,27 @@ void print_passed_to(struct expression *expr)
 {
 	struct state_list *printed = NULL;
 
-	print_passed_to_sm(get_sm_state_expr(my_id, expr), &printed);
+	print_passed_to_sm(get_sm_state_expr(my_id, expr), NULL, &printed);
 	free_slist(&printed);
 }
 
+static void print_passed_to_states(void)
+{
+	struct state_list *printed;
+	struct sm_state *sm;
+
+	FOR_EACH_MY_SM(my_id, __get_cur_stree(), sm) {
+		printed = NULL;
+		print_passed_to_sm(sm, sm->name, &printed);
+		free_slist(&printed);
+	} END_FOR_EACH_SM(sm);
+}
+
 void smatch_passed_to(int id)
 {
 	my_id = id;
 
 	set_dynamic_states(my_id);
 	add_hook(&match_call, FUNCTION_CALL_HOOK);
+	register_ai_info(&print_passed_to_states);
 }
-- 
2.52.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH smatch-devel 1/5] docs: document selecting individual Smatch checks
  2026-08-18 13:03 [PATCH smatch-devel 1/5] docs: document selecting individual Smatch checks Harshit Mogalapalli
                   ` (3 preceding siblings ...)
  2026-08-18 13:03 ` [PATCH smatch-devel 5/5] smatch: report passed-to history for --ai Harshit Mogalapalli
@ 2026-08-18 13:11 ` Dan Carpenter
  4 siblings, 0 replies; 6+ messages in thread
From: Dan Carpenter @ 2026-08-18 13:11 UTC (permalink / raw)
  To: Harshit Mogalapalli; +Cc: smatch

Thanks!  Applied to devel.

regards,
dan carpenter


^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2026-08-18 13:11 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-18 13:03 [PATCH smatch-devel 1/5] docs: document selecting individual Smatch checks Harshit Mogalapalli
2026-08-18 13:03 ` [PATCH smatch-devel 2/5] smatch: prevent recursive --ai state dumps Harshit Mogalapalli
2026-08-18 13:03 ` [PATCH smatch-devel 3/5] smatch: track functions variables are passed to Harshit Mogalapalli
2026-08-18 13:03 ` [PATCH smatch-devel 4/5] smatch: add passed-to debug helper Harshit Mogalapalli
2026-08-18 13:03 ` [PATCH smatch-devel 5/5] smatch: report passed-to history for --ai Harshit Mogalapalli
2026-08-18 13:11 ` [PATCH smatch-devel 1/5] docs: document selecting individual Smatch checks Dan Carpenter

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox