__module_put_and_exit() doesn't return.
[smatch.git] / check_overflow.c
blob522536332dbae207f67b248b5846a14b0b514599
1 /*
2 * sparse/check_deference.c
4 * Copyright (C) 2006 Dan Carpenter.
6 * Licensed under the Open Software License version 1.1
8 */
10 #include <stdlib.h>
11 #include "parse.h"
12 #include "smatch.h"
14 static int my_id;
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;
24 return state;
27 static int malloc_size(struct expression *expr)
29 char *name;
30 struct expression *arg;
32 if (!expr)
33 return 0;
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);
39 free_string(name);
40 return get_value(arg);
42 free_string(name);
43 } else if (expr->type == EXPR_STRING && expr->string) {
44 return expr->string->length;
46 return 0;
49 static void match_declaration(struct symbol *sym)
51 struct symbol *base_type;
52 char *name;
53 int size;
55 if (!sym->ident)
56 return;
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));
63 } else {
64 size = malloc_size(sym->initializer);
65 if (size > 0)
66 set_state(name, my_id, NULL, alloc_state(size));
71 static void match_assignment(struct expression *expr)
73 char *name;
74 name = get_variable_from_expr(expr->left, NULL);
75 if (!name)
76 return;
77 if (malloc_size(expr->right) > 0)
78 set_state(name, my_id, NULL, alloc_state(malloc_size(expr->right)));
79 free_string(name);
82 static void match_strcpy(const char *fn, struct expression *expr,
83 void *unused)
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)
100 goto free;
102 data_state = get_state(data_name, my_id, NULL);
103 if (!data_state || !data_state->data)
104 goto free;
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);
110 free:
111 free_string(dest_name);
112 free_string(data_name);
115 static void match_limitted(const char *fn, struct expression *expr,
116 void *limit_arg)
118 struct expression *dest;
119 struct expression *data;
120 char *dest_name = NULL;
121 struct smatch_state *state;
122 int needed;
123 int has;
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)
132 goto free;
133 has = *(int *)state->data;
134 if (has < needed)
135 smatch_msg("error: %s too small for %d bytes.", dest_name,
136 needed);
137 free:
138 free_string(dest_name);
141 void check_overflow(int id)
143 my_id = 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);