From f53e8d238d8d010806716a18fc1d99c055455036 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 8 May 2023 10:12:56 +0300 Subject: [PATCH] impossible: don't mark returns as impossible if threads are involved Smatch doesn't understand threads at all. So what would happen is that you set foo->bar = 0; then wait for it to be set in another thread, and then check the value again. Smatch marks the non-zero paths as impossible and CULLs them from the DB. This means that the success path is marked as impossible. Of course, that means you miss some paths and some information. But what it also means is that when the callers check "if (ret) {" then Smatch ignores the implications from that. (Smatch ignores the implications from known true/false conditions). So that leads to confusing false positives. Signed-off-by: Dan Carpenter --- smatch_impossible.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/smatch_impossible.c b/smatch_impossible.c index 12c84161..440a4c7b 100644 --- a/smatch_impossible.c +++ b/smatch_impossible.c @@ -21,6 +21,8 @@ static int my_id; static int my_return_id; +unsigned long nothing_impossible; + STATE(impossible); int is_impossible_path(void) @@ -102,6 +104,9 @@ static void match_case(struct expression *expr, struct range_list *rl) static void print_impossible_return(int return_id, char *return_ranges, struct expression *expr) { + if (nothing_impossible) + return; + if (get_state(my_return_id, "impossible", NULL) == &impossible) { if (option_debug) sm_msg("impossible return. return_id = %d return ranges = %s", return_id, return_ranges); @@ -109,6 +114,11 @@ static void print_impossible_return(int return_id, char *return_ranges, struct e } } +static void match_thread_stuff(const char *fn, struct expression *expr, void *unused) +{ + nothing_impossible = true; +} + void register_impossible(int id) { my_id = id; @@ -121,5 +131,19 @@ void register_impossible_return(int id) { my_return_id = id; + add_function_data(¬hing_impossible); + if (option_project == PROJ_KERNEL) { + add_function_hook("wait_for_completion", &match_thread_stuff, NULL); + add_function_hook("wait_for_completion_timeout", &match_thread_stuff, NULL); + add_function_hook("wait_for_completion_io", &match_thread_stuff, NULL); + add_function_hook("wait_for_completion_io_timeout", &match_thread_stuff, NULL); + add_function_hook("wait_for_completion_interruptible", &match_thread_stuff, NULL); + add_function_hook("wait_for_completion_interruptible_timeout", &match_thread_stuff, NULL); + add_function_hook("wait_for_completion_killable", &match_thread_stuff, NULL); + add_function_hook("wait_for_completion_state", &match_thread_stuff, NULL); + add_function_hook("wait_for_completion_killable_timeout", &match_thread_stuff, NULL); + add_function_hook("try_wait_for_completion", &match_thread_stuff, NULL); + } + add_split_return_callback(&print_impossible_return); } -- 2.11.4.GIT