2 * sparse/check_template.c
4 * Copyright (C) 20XX Your Name.
6 * Licensed under the Open Software License version 1.1
11 * First of all, it's best if you lower your expectations from finding
12 * errors to just finding suspicious code. There tends to be a lot
13 * of false positives so having low expectations helps.
15 * For this test let's look for functions that return a negative value
16 * with a semaphore held.
18 * This is just a template check. It's designed for teaching
19 * only and is deliberately less useful than it could be.
21 * This test could be a lot better if it handled the stuff like this:
24 * The correct way to handle that is to let smatch_extra store the
25 * value of ret. Then to use a *future* version of smatch that has
26 * the get_possible_states(name, SMATCH_EXTRA, sym) function. The
27 * possible states will be saved in merge_slist() in that future version.
29 * Another short coming is that it assumes a function isn't supposed
30 * to return negative with a lock held. Perhaps the function was
31 * called with the lock held. A more complicated script could check that.
33 * Also it would be more effective to check for other types of locks
34 * especially spinlocks.
40 #include "smatch_slist.h" // blast this was supposed to be internal only stuff
48 * merge_func() can go away when we fix the core to just store all the possible
51 * The parameters are passed in alphabetical order with NULL at the beginning
52 * of the alphabet. (s2 is never NULL).
55 static struct smatch_state
*merge_func(const char *name
, struct symbol
*sym
,
56 struct smatch_state
*s1
,
57 struct smatch_state
*s2
)
65 static void match_call(struct expression
*expr
)
68 struct expression
*sem_expr
;
71 fn_name
= get_variable_from_expr(expr
->fn
, NULL
);
72 if (!fn_name
|| (strcmp(fn_name
, "down") && strcmp(fn_name
, "up")))
75 sem_expr
= get_argument_from_call_expr(expr
->args
, 0);
76 sem_name
= get_variable_from_expr(sem_expr
, NULL
);
77 if (!strcmp(fn_name
, "down")) {
78 set_state(sem_name
, my_id
, NULL
, &lock
);
80 set_state(sem_name
, my_id
, NULL
, &unlock
);
85 static void match_return(struct statement
*stmt
)
88 struct state_list
*slist
;
91 ret_val
= get_value(stmt
->ret_value
);
92 if (ret_val
== UNDEFINED
|| ret_val
>= 0)
95 slist
= get_all_states(my_id
);
97 FOR_EACH_PTR(slist
, tmp
) {
98 if (tmp
->state
!= &unlock
)
99 smatch_msg("returned negative with %s semaphore held",
101 } END_FOR_EACH_PTR(tmp
);
104 void register_template(int id
)
107 add_merge_hook(my_id
, &merge_func
);
108 add_hook(&match_call
, FUNCTION_CALL_HOOK
);
109 add_hook(&match_return
, RETURN_HOOK
);