Merge branch 'ls' into ultratmp
[smatch.git] / check_overflow.c
blob242c9e91169f13de85098d49ab7e37f57f862b72
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 int malloc_size(struct expression *expr)
18 char *name;
19 struct expression *arg;
21 if (!expr)
22 return 0;
24 if (expr->type == EXPR_CALL) {
25 name = get_variable_from_expr_simple(expr->fn, NULL);
26 if (name && !strcmp(name, "kmalloc")) {
27 arg = get_argument_from_call_expr(expr->args, 0);
28 return get_value(arg, NULL);
30 } else if (expr->type == EXPR_STRING && expr->string) {
31 return expr->string->length * 8;
33 return 0;
36 static void match_declaration(struct symbol *sym)
38 struct symbol *base_type;
39 char *name;
40 int size;
42 if (!sym->ident)
43 return;
45 name = sym->ident->name;
46 base_type = get_base_type(sym);
48 if (base_type->type == SYM_ARRAY && base_type->bit_size > 0)
49 set_state(name, my_id, NULL, base_type->bit_size / 8);
50 else {
51 size = malloc_size(sym->initializer);
52 if (size > 0)
53 set_state(name, my_id, NULL, size);
57 static void match_assignment(struct expression *expr)
59 char *name;
60 name = get_variable_from_expr_simple(expr->left, NULL);
61 name = alloc_string(name);
62 if (!name)
63 return;
64 if (malloc_size(expr->right) > 0)
65 set_state(name, my_id, NULL, malloc_size(expr->right));
68 static void match_fn_call(struct expression *expr)
70 struct expression *dest;
71 struct expression *data;
72 char *fn_name;
73 char *dest_name;
74 char *data_name;
76 fn_name = get_variable_from_expr(expr->fn, NULL);
77 if (!fn_name)
78 return;
80 if (!strcmp(fn_name, "strcpy")) {
81 dest = get_argument_from_call_expr(expr->args, 0);
82 dest_name = get_variable_from_expr(dest, NULL);
83 dest_name = alloc_string(dest_name);
85 data = get_argument_from_call_expr(expr->args, 1);
86 data_name = get_variable_from_expr(data, NULL);
87 data_name = alloc_string(data_name);
89 if (get_state(dest_name, my_id, NULL) < 0)
90 return;
91 if (get_state(dest_name, my_id, NULL)
92 < get_state(data_name, my_id, NULL))
93 smatch_msg("Error %s too large for %s", data_name,
94 dest_name);
95 } else if (!strcmp(fn_name, "strncpy")) {
96 int needed;
97 int has;
99 dest = get_argument_from_call_expr(expr->args, 0);
100 dest_name = get_variable_from_expr(dest, NULL);
101 dest_name = alloc_string(dest_name);
103 data = get_argument_from_call_expr(expr->args, 2);
104 needed = get_value(data, NULL);
105 has = get_state(dest_name, my_id, NULL);
106 if (has > 0 && has < needed)
107 smatch_msg("Error %s too small for %d bytes.",
108 dest_name, needed);
112 void register_overflow(int id)
114 my_id = id;
115 add_hook(&match_declaration, DECLARATION_HOOK);
116 add_hook(&match_assignment, ASSIGNMENT_HOOK);
117 add_hook(&match_fn_call, FUNCTION_CALL_HOOK);