Print this page
new smatch
*** 225,241 ****
if (offset < 0)
return 0;
return 1;
}
! static int is_ignored_macro(void)
{
struct expression *expr;
char *name;
expr = get_faked_expression();
if (!expr || expr->type != EXPR_ASSIGNMENT)
return 0;
name = get_macro_name(expr->right->pos);
if (!name)
return 0;
if (strcmp(name, "container_of") == 0)
--- 225,274 ----
if (offset < 0)
return 0;
return 1;
}
! static bool is_driver_data(void)
{
+ static struct expression *prev_expr;
struct expression *expr;
char *name;
+ static bool prev_ret;
+ bool ret = false;
expr = get_faked_expression();
if (!expr || expr->type != EXPR_ASSIGNMENT)
+ return false;
+
+ if (expr == prev_expr)
+ return prev_ret;
+ prev_expr = expr;
+
+ name = expr_to_str(expr->right);
+ if (!name) {
+ prev_ret = false;
+ return false;
+ }
+
+ if (strstr(name, "get_drvdata(") ||
+ strstr(name, "dev.driver_data") ||
+ strstr(name, "dev->driver_data"))
+ ret = true;
+
+ free_string(name);
+
+ prev_ret = ret;
+ return ret;
+ }
+
+ static int is_ignored_macro(void)
+ {
+ struct expression *expr;
+ char *name;
+
+ expr = get_faked_expression();
+ if (!expr || expr->type != EXPR_ASSIGNMENT || expr->op != '=')
return 0;
name = get_macro_name(expr->right->pos);
if (!name)
return 0;
if (strcmp(name, "container_of") == 0)
*** 246,255 ****
--- 279,302 ----
return 1;
if (strcmp(name, "list_first_entry") == 0)
return 1;
if (strcmp(name, "hlist_entry") == 0)
return 1;
+ if (strcmp(name, "per_cpu_ptr") == 0)
+ return 1;
+ if (strcmp(name, "raw_cpu_ptr") == 0)
+ return 1;
+ if (strcmp(name, "this_cpu_ptr") == 0)
+ return 1;
+
+ if (strcmp(name, "TRACE_EVENT") == 0)
+ return 1;
+ if (strcmp(name, "DECLARE_EVENT_CLASS") == 0)
+ return 1;
+ if (strcmp(name, "DEFINE_EVENT") == 0)
+ return 1;
+
if (strstr(name, "for_each"))
return 1;
return 0;
}
*** 264,277 ****
--- 311,344 ----
if (!expr || expr->type != EXPR_CALL || expr->fn->type != EXPR_SYMBOL)
return 0;
if (sym_name_is("kmalloc", expr->fn))
return 1;
+ if (sym_name_is("vmalloc", expr->fn))
+ return 1;
+ if (sym_name_is("kvmalloc", expr->fn))
+ return 1;
+ if (sym_name_is("kmalloc_array", expr->fn))
+ return 1;
+ if (sym_name_is("vmalloc_array", expr->fn))
+ return 1;
+ if (sym_name_is("kvmalloc_array", expr->fn))
+ return 1;
+
+ if (sym_name_is("mmu_memory_cache_alloc", expr->fn))
+ return 1;
+ if (sym_name_is("kmem_alloc", expr->fn))
+ return 1;
+ if (sym_name_is("alloc_pages", expr->fn))
+ return 1;
+
if (sym_name_is("netdev_priv", expr->fn))
return 1;
if (sym_name_is("dev_get_drvdata", expr->fn))
return 1;
+ if (sym_name_is("i2c_get_clientdata", expr->fn))
+ return 1;
return 0;
}
static int is_uncasted_pointer_assign(void)
*** 292,301 ****
--- 359,371 ----
right_type = get_type(expr->right);
if (!left_type || !right_type)
return 0;
+ if (left_type->type == SYM_STRUCT && left_type == right_type)
+ return 1;
+
if (left_type->type != SYM_PTR &&
left_type->type != SYM_ARRAY)
return 0;
if (right_type->type != SYM_PTR &&
right_type->type != SYM_ARRAY)
*** 394,403 ****
--- 464,475 ----
if (!cur_func_sym)
return;
type = get_type(expr->left);
+ if (type && type->type == SYM_STRUCT)
+ return;
member = get_member_name(expr->left);
if (!member)
return;
/* if we're saying foo->mtu = bar->mtu then that doesn't add information */
*** 414,423 ****
--- 486,497 ----
goto free;
if (is_uncasted_fn_param_from_db())
goto free;
if (is_container_of())
goto free;
+ if (is_driver_data())
+ goto free;
add_fake_type_val(member, alloc_whole_rl(get_type(expr->left)), is_ignored_fake_assignment());
goto free;
}
if (expr->op == '=') {
*** 499,526 ****
static void asm_expr(struct statement *stmt)
{
struct expression *expr;
struct range_list *rl;
char *member;
- int state = 0;
FOR_EACH_PTR(stmt->asm_outputs, expr) {
! switch (state) {
! case 0: /* identifier */
! case 1: /* constraint */
! state++;
! continue;
! case 2: /* expression */
! state = 0;
! member = get_member_name(expr);
if (!member)
continue;
! rl = alloc_whole_rl(get_type(expr));
add_type_val(member, rl);
free_string(member);
- continue;
- }
} END_FOR_EACH_PTR(expr);
}
static void db_param_add(struct expression *expr, int param, char *key, char *value)
{
--- 573,590 ----
static void asm_expr(struct statement *stmt)
{
struct expression *expr;
struct range_list *rl;
char *member;
FOR_EACH_PTR(stmt->asm_outputs, expr) {
! member = get_member_name(expr->expr);
if (!member)
continue;
! rl = alloc_whole_rl(get_type(expr->expr));
add_type_val(member, rl);
free_string(member);
} END_FOR_EACH_PTR(expr);
}
static void db_param_add(struct expression *expr, int param, char *key, char *value)
{
*** 540,549 ****
--- 604,626 ----
arg = get_argument_from_call_expr(expr->args, param);
arg = strip_expr(arg);
if (!arg)
return;
type = get_member_type_from_key(arg, key);
+ /*
+ * The situation here is that say we memset() a void pointer to zero
+ * then that's returned to the called as "*$ = 0;" but on the caller's
+ * side it's not void, it's a struct.
+ *
+ * So the question is should we be passing that slightly bogus
+ * information back to the caller? Maybe, maybe not, but either way we
+ * are not going to record it here because a struct can't be zero.
+ *
+ */
+ if (type && type->type == SYM_STRUCT)
+ return;
+
if (arg->type != EXPR_PREOP || arg->op != '&')
return;
arg = strip_expr(arg->unop);
member = get_member_name(arg);