2 * sparse/check_deference.c
4 * Copyright (C) 2006 Dan Carpenter.
6 * Licensed under the Open Software License version 1.1
16 static struct smatch_state
*alloc_state(int val
)
18 struct smatch_state
*state
;
20 state
= malloc(sizeof(*state
));
21 state
->name
= "value";
22 state
->data
= malloc(sizeof(int));
23 *(int *)state
->data
= val
;
27 static int malloc_size(struct expression
*expr
)
30 struct expression
*arg
;
35 if (expr
->type
== EXPR_CALL
) {
36 name
= get_variable_from_expr(expr
->fn
, NULL
);
37 if (name
&& !strcmp(name
, "kmalloc")) {
38 arg
= get_argument_from_call_expr(expr
->args
, 0);
40 return get_value(arg
);
43 } else if (expr
->type
== EXPR_STRING
&& expr
->string
) {
44 return expr
->string
->length
;
49 static void match_declaration(struct symbol
*sym
)
51 struct symbol
*base_type
;
58 name
= sym
->ident
->name
;
59 base_type
= get_base_type(sym
);
61 if (base_type
->type
== SYM_ARRAY
&& base_type
->bit_size
> 0) {
62 set_state(name
, my_id
, NULL
, alloc_state(base_type
->bit_size
/ 8));
64 size
= malloc_size(sym
->initializer
);
66 set_state(name
, my_id
, NULL
, alloc_state(size
));
71 static void match_assignment(struct expression
*expr
)
74 name
= get_variable_from_expr(expr
->left
, NULL
);
77 if (malloc_size(expr
->right
) > 0)
78 set_state(name
, my_id
, NULL
, alloc_state(malloc_size(expr
->right
)));
82 static void match_strcpy(const char *fn
, struct expression
*expr
,
85 struct expression
*dest
;
86 struct expression
*data
;
87 char *dest_name
= NULL
;
88 char *data_name
= NULL
;
89 struct smatch_state
*dest_state
;
90 struct smatch_state
*data_state
;
92 dest
= get_argument_from_call_expr(expr
->args
, 0);
93 dest_name
= get_variable_from_expr(dest
, NULL
);
95 data
= get_argument_from_call_expr(expr
->args
, 1);
96 data_name
= get_variable_from_expr(data
, NULL
);
98 dest_state
= get_state(dest_name
, my_id
, NULL
);
99 if (!dest_state
|| !dest_state
->data
)
102 data_state
= get_state(data_name
, my_id
, NULL
);
103 if (!data_state
|| !data_state
->data
)
106 if (*(int *)dest_state
->data
< *(int *)data_state
->data
)
107 smatch_msg("error: %s (%d) too large for %s (%d)", data_name
,
108 *(int *)data_state
->data
,
109 dest_name
, *(int *)dest_state
->data
);
111 free_string(dest_name
);
112 free_string(data_name
);
115 static void match_limitted(const char *fn
, struct expression
*expr
,
118 struct expression
*dest
;
119 struct expression
*data
;
120 char *dest_name
= NULL
;
121 struct smatch_state
*state
;
125 dest
= get_argument_from_call_expr(expr
->args
, 0);
126 dest_name
= get_variable_from_expr(dest
, NULL
);
128 data
= get_argument_from_call_expr(expr
->args
, (int)limit_arg
);
129 needed
= get_value(data
);
130 state
= get_state(dest_name
, my_id
, NULL
);
131 if (!state
|| !state
->data
)
133 has
= *(int *)state
->data
;
135 smatch_msg("error: %s too small for %d bytes.", dest_name
,
138 free_string(dest_name
);
141 void check_overflow(int id
)
144 add_hook(&match_declaration
, DECLARATION_HOOK
);
145 add_hook(&match_assignment
, ASSIGNMENT_HOOK
);
146 add_function_hook("strcpy", &match_strcpy
, NULL
);
147 add_function_hook("strncpy", &match_limitted
, (void *)2);
148 add_function_hook("copy_to_user", &match_limitted
, (void *)2);
149 add_function_hook("copy_from_user", &match_limitted
, (void *)2);