*new* check_struct_type: if we allocate an unexpected type of struct
authorDan Carpenter <dan.carpenter@oracle.com>
Thu, 14 Feb 2013 12:13:32 +0000 (14 15:13 +0300)
committerDan Carpenter <dan.carpenter@oracle.com>
Thu, 14 Feb 2013 12:13:32 +0000 (14 15:13 +0300)
Complain about code like this:

struct foo *p;

p = kmalloc(sizeof(struct bar), GFP_KERNEL);

These are mostly real bugs, but they are allocating more memory than we
need not less.

Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
check_list.h
check_struct_type.c [new file with mode: 0644]

index d2f6125..a4de1cf 100644 (file)
@@ -83,6 +83,7 @@ CK(check_or_vs_and)
 CK(check_passes_sizeof)
 CK(check_assign_vs_compare)
 CK(check_missing_break)
+CK(check_struct_type)
 
 /* <- your test goes here */
 /* CK(register_template) */
diff --git a/check_struct_type.c b/check_struct_type.c
new file mode 100644 (file)
index 0000000..0982e72
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * sparse/check_struct_type.c
+ *
+ * Copyright (C) 2013 Oracle.
+ *
+ * Licensed under the Open Software License version 1.1
+ *
+ */
+
+#include "smatch.h"
+
+static int my_id;
+
+static void match_assign(const char *fn, struct expression *expr, void *_size_arg)
+{
+       int size_arg = PTR_INT(_size_arg);
+       struct expression *left;
+       struct expression *call;
+       struct expression *arg;
+       struct symbol *left_type;
+       struct symbol *size_type;
+
+       left = strip_expr(expr->left);
+       left_type = get_type(left);
+       if (!left_type || left_type->type != SYM_PTR)
+               return;
+       left_type = get_real_base_type(left_type);
+       if (!left_type || left_type->type != SYM_STRUCT)
+               return;
+
+       call = strip_expr(expr->right);
+       arg = get_argument_from_call_expr(call->args, size_arg);
+       if (!arg || arg->type != EXPR_SIZEOF || !arg->cast_type)
+               return;
+       size_type = arg->cast_type;
+       if (size_type->type != SYM_NODE)
+               return;
+       size_type = get_real_base_type(size_type);
+       if (size_type->type != SYM_STRUCT)
+               return;
+       if (strcmp(left_type->ident->name, size_type->ident->name) == 0)
+               return;
+       sm_msg("warn: struct type mismatch '%s vs %s'", left_type->ident->name,
+              size_type->ident->name);
+
+}
+
+void check_struct_type(int id)
+{
+       my_id = id;
+
+       if (option_project == PROJ_KERNEL) {
+               add_function_assign_hook("kmalloc", &match_assign, INT_PTR(0));
+               add_function_assign_hook("kzalloc", &match_assign, INT_PTR(0));
+       }
+}