flow: introduce definite_inside_loop()
[smatch.git] / check_pointer_math.c
blobeb53d7f569c0d840bde06c744a9dd531b2e62053
1 /*
2 * smatch/check_pointer_math.c
4 * Copyright (C) 2012 Oracle.
6 * Licensed under the Open Software License version 1.1
8 */
10 #include "smatch.h"
12 static int my_id;
14 STATE(size_in_bytes);
16 static void set_undefined(struct sm_state *sm, struct expression *mod_expr)
18 if (sm->state == &size_in_bytes)
19 set_state(my_id, sm->name, sm->sym, &undefined);
22 static int is_sizeof(struct expression *expr)
24 return (expr->type == EXPR_SIZEOF);
27 static int is_align(struct expression *expr)
29 char *name;
30 struct expression *outside_expr;
32 /* check that we aren't inside the ALIGN() macro itself */
33 outside_expr = last_ptr_list((struct ptr_list *)big_expression_stack);
34 if (outside_expr && positions_eq(expr->pos, outside_expr->pos))
35 return 0;
37 name = get_macro_name(expr->pos);
38 if (name && strcmp(name, "ALIGN") == 0)
39 return 1;
40 return 0;
43 static int is_size_in_bytes(struct expression *expr)
45 if (is_sizeof(expr))
46 return 1;
48 if (is_align(expr))
49 return 1;
51 if (get_state_expr(my_id, expr) == &size_in_bytes)
52 return 1;
54 return 0;
57 static void match_binop(struct expression *expr)
59 struct symbol *type;
60 char *name;
62 if (expr->op != '+')
63 return;
64 type = get_pointer_type(expr->left);
65 if (!type)
66 return;
67 if (type->bit_size <= 8) /* ignore void, bool and char pointers*/
68 return;
69 if (!is_size_in_bytes(expr->right))
70 return;
72 name = expr_to_str(expr->left);
73 sm_msg("warn: potential pointer math issue ('%s' is a %d bit pointer)",
74 name, type->bit_size);
75 free_string(name);
78 static void match_assign(struct expression *expr)
80 if (expr->op != '=')
81 return;
83 if (!is_size_in_bytes(expr->right))
84 return;
85 set_state_expr(my_id, expr->left, &size_in_bytes);
88 static void check_assign(struct expression *expr)
90 struct symbol *type;
91 char *name;
93 type = get_pointer_type(expr->left);
94 if (!type)
95 return;
96 if (type_bits(type) == 8 || type_bits(type) == -1)
97 return;
98 if (!is_size_in_bytes(expr->right))
99 return;
100 name = expr_to_var(expr->left);
101 sm_msg("warn: potential pointer math issue ('%s' is a %d bit pointer)",
102 name, type_bits(type));
103 free_string(name);
106 void check_pointer_math(int id)
108 my_id = id;
109 add_hook(&match_binop, BINOP_HOOK);
110 add_hook(&match_assign, ASSIGNMENT_HOOK);
111 add_hook(&check_assign, ASSIGNMENT_HOOK);
112 add_modification_hook(my_id, &set_undefined);