These days the param/key API is the preferred way to write Smatch checks. In my First Smatch Check post I wrote how to implement match_kfree() in the old way which hardcoded that the freed variable was argument 0. With the param/key API we would instead say the freed variable was param 0 and the the key is “$”.
The advantage of the param/key API is that it lets us easily specify struct members which are freed. 0/$->foo->bar.
The function would look like:
static void match_free(struct expression *expr, const char *name, struct symbol *sym, void *data)
{
set_state(my_id, name, sym, &freed);
}
And it would be registered like this:
add_function_param_key_hook("kfree", &match_free, 0, "$", NULL);
But it would be more likely that we would have a table at the top of the file with all the common free functions. We can also use the same match_free() function to handle FREE data from the cross function database.
select_return_param_key(FREE, &match_free);
To store the information in the database do something like this:
static void free_info_callback(int return_id, char *return_ranges,
struct expression *returned_expr,
int param,
const char *printed_name,
struct sm_state *sm)
{
if (sm->state != &freed)
return;
sql_insert_return_states(return_id, return_ranges, FREE,
param, printed_name, "");
}
Register that function like so:
add_return_info_callback(my_id, free_info_callback);
Passing freed pointers is dumb so we don’t need to record that in the caller_info table but if we did the functions to insert and select data are.
add_caller_info_callback(my_id, caller_info_callback);
select_caller_name_sym(&select_freed_pointer, FREE);
The param/key API only works for states which are tied to a variable. So if we’re tracking whether or not preempt is disabled then it will not work. A lot of Smatch code was written before the param/key API was available so it uses the old style. Also Smatch is not perfect at connecting data to a parameter. As always, Smatch tries to be useful and not perfect.
Leave a comment