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. check_locking.c
20 * is a better real world test.
22 * The biggest short coming is that it assumes a function isn't supposed
23 * to return negative with a lock held. Also it assumes the function was
24 * called without the lock held. It would be better if it handled the stuff
28 * Another idea would be to test other kinds of locks besides just semaphores.
33 #include "smatch_slist.h" // blast this was supposed to be internal only stuff
41 * unmatched_state() deals with the case where code is known to be
42 * locked on one path but not known on the other side of a merge. Here
43 * we assume it's the opposite.
46 static struct smatch_state
*unmatched_state(struct sm_state
*sm
)
48 if (sm
->state
== &lock
)
50 if (sm
->state
== &unlock
)
55 static void match_call(struct expression
*expr
)
58 struct expression
*sem_expr
;
61 fn_name
= get_variable_from_expr(expr
->fn
, NULL
);
62 if (!fn_name
|| (strcmp(fn_name
, "down") && strcmp(fn_name
, "up")))
65 sem_expr
= get_argument_from_call_expr(expr
->args
, 0);
66 sem_name
= get_variable_from_expr(sem_expr
, NULL
);
67 if (!strcmp(fn_name
, "down")) {
68 set_state(my_id
, sem_name
, NULL
, &lock
);
70 set_state(my_id
, sem_name
, NULL
, &unlock
);
72 free_string(sem_name
);
77 static void match_return(struct statement
*stmt
)
80 struct state_list
*slist
;
83 ret_val
= get_value(stmt
->ret_value
);
84 if (ret_val
== UNDEFINED
|| ret_val
>= 0)
87 slist
= get_all_states(my_id
);
88 FOR_EACH_PTR(slist
, tmp
) {
89 if (tmp
->state
!= &unlock
)
90 sm_msg("warn: returned negative with %s semaphore held",
92 } END_FOR_EACH_PTR(tmp
);
96 void check_template(int id
)
99 add_unmatched_state_hook(my_id
, &unmatched_state
);
100 add_hook(&match_call
, FUNCTION_CALL_HOOK
);
101 add_hook(&match_return
, RETURN_HOOK
);