2 * smatch/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"
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 expression
*ret_value
)
80 struct state_list
*slist
;
83 if (!get_value_sval(ret_value
, &ret_val
) || sval_cmp_val(ret_val
, 0) >= 0)
86 slist
= get_all_states(my_id
);
87 FOR_EACH_PTR(slist
, tmp
) {
88 if (tmp
->state
!= &unlock
)
89 sm_msg("warn: returned negative with %s semaphore held",
91 } END_FOR_EACH_PTR(tmp
);
95 void check_template(int id
)
98 add_unmatched_state_hook(my_id
, &unmatched_state
);
99 add_hook(&match_call
, FUNCTION_CALL_HOOK
);
100 add_hook(&match_return
, RETURN_HOOK
);