From e06e11721125ea82ca5be036498008bfb9e55a34 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 17 Oct 2008 15:41:21 +0300 Subject: [PATCH] Create a check_template.c example script that looks for locking issues. Signed-off-by: Dan Carpenter --- check_template.c | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 check_template.c diff --git a/check_template.c b/check_template.c new file mode 100644 index 00000000..cc7acc8c --- /dev/null +++ b/check_template.c @@ -0,0 +1,86 @@ +/* + * sparse/check_template.c + * + * Copyright (C) 20XX Your Name. + * + * Licensed under the Open Software License version 1.1 + * + */ + +/* + * This is just a template check. It's designed for teaching + * only and doesn't even work. + * + * First of all, it's best if you lower your expectations from finding + * errors to just finding suspicious code. There tends to be a lot + * of false positives so having low expectations helps. + * + * For this test let's look for functions that return a negative value + * with a semaphore held. + * + * This test could be a lot better if it handled the stuff like this: + * ret = -ENOMEM; + * return ret; + * The correct way to handle that is to let smatch_extra store the + * value of ret. Then to use a *future* version of smatch that has + * the get_possible_states() function. The possible states will + * be saved in merge_slist(). + */ + +#include "parse.h" +#include "smatch.h" +#include "smatch_slist.h" // blast this was supposed to be internal only stuff + +static int my_id; + +STATE(lock); +STATE(unlock); + +static void match_call(struct expression *expr) +{ + char *fn_name; + struct expression *sem_expr; + char *sem_name; + + fn_name = get_variable_from_expr(expr->fn, NULL); + if (strcmp(fn_name, "down") && strcmp(fn_name, "up")) + return; + + sem_expr = get_argument_from_call_expr(expr->args, 0); + sem_name = get_variable_from_expr_simple(sem_expr, NULL); + if (strcmp(fn_name, "down")) { + printf("%d %s locked\n", get_lineno(), sem_name); + set_state(sem_name, my_id, NULL, &lock); + } else { + printf("%d %s unlocked\n", get_lineno(), sem_name); + set_state(sem_name, my_id, NULL, &unlock); + } +} + +static void match_return(struct statement *stmt) +{ + int ret_val; + struct state_list *slist; + struct sm_state *tmp; + + ret_val = get_value(stmt->ret_value); + if (ret_val == UNDEFINED || ret_val >= 0) + return; + + slist = get_all_states(my_id); + + __print_slist(slist); + + FOR_EACH_PTR(slist, tmp) { + if (tmp->state != &unlock) + smatch_msg("returned negative with %s semaphore held", + tmp->name); + } END_FOR_EACH_PTR(tmp); +} + +void register_template(int id) +{ + my_id = id; + add_hook(&match_call, FUNCTION_CALL_HOOK); + add_hook(&match_return, RETURN_HOOK); +} -- 2.11.4.GIT