unconstant_macros: Add FAULT_FLAG_TRANSHUGE
[smatch.git] / smatch_capped.c
blob71d88787f8f75d442832e7caa0f47dac8fc3019b
1 /*
2 * smatch/smatch_capped.c
4 * Copyright (C) 2011 Oracle. All rights reserved.
6 * Licensed under the Open Software License version 1.1
8 */
11 * This is trying to make a list of the variables which
12 * have capped values. Sometimes we don't know what the
13 * cap is, for example if we are comparing variables but
14 * we don't know the values of the variables. In that
15 * case we only know that our variable is capped and we
16 * sort that information here.
19 #include "smatch.h"
20 #include "smatch_slist.h"
22 static int my_id;
24 STATE(capped);
25 STATE(uncapped);
27 static int is_capped_macro(struct expression *expr)
29 char *name;
31 name = get_macro_name(expr->pos);
32 if (!name)
33 return 0;
35 if (strcmp(name, "min") == 0)
36 return 1;
37 if (strcmp(name, "MIN") == 0)
38 return 1;
39 if (strcmp(name, "min_t") == 0)
40 return 1;
42 return 0;
45 int is_capped(struct expression *expr)
47 sval_t dummy;
49 expr = strip_expr(expr);
50 while (expr && expr->type == EXPR_POSTOP) {
51 expr = strip_expr(expr->unop);
53 if (!expr)
54 return 0;
56 if (get_hard_max(expr, &dummy))
57 return 1;
59 if (is_capped_macro(expr))
60 return 1;
62 if (expr->type == EXPR_BINOP) {
63 if (expr->op == '&')
64 return 1;
65 if (expr->op == SPECIAL_RIGHTSHIFT)
66 return 1;
67 if (expr->op == '%')
68 return is_capped(expr->right);
69 if (!is_capped(expr->left))
70 return 0;
71 if (expr->op == '/')
72 return 1;
73 if (!is_capped(expr->right))
74 return 0;
75 return 1;
77 if (get_state_expr(my_id, expr) == &capped)
78 return 1;
79 return 0;
82 int is_capped_var_sym(const char *name, struct symbol *sym)
84 if (get_state(my_id, name, sym) == &capped)
85 return 1;
86 return 0;
89 void set_param_capped_data(const char *name, struct symbol *sym, char *key, char *value)
91 char fullname[256];
93 if (strncmp(key, "$$", 2))
94 return;
95 snprintf(fullname, 256, "%s%s", name, key + 2);
96 set_state(my_id, fullname, sym, &capped);
99 static void match_condition(struct expression *expr)
101 struct smatch_state *left_true = NULL;
102 struct smatch_state *left_false = NULL;
103 struct smatch_state *right_true = NULL;
104 struct smatch_state *right_false = NULL;
107 if (expr->type != EXPR_COMPARE)
108 return;
110 switch (expr->op) {
111 case '<':
112 case SPECIAL_LTE:
113 case SPECIAL_UNSIGNED_LT:
114 case SPECIAL_UNSIGNED_LTE:
115 left_true = &capped;
116 right_false = &capped;
117 break;
118 case '>':
119 case SPECIAL_GTE:
120 case SPECIAL_UNSIGNED_GT:
121 case SPECIAL_UNSIGNED_GTE:
122 left_false = &capped;
123 right_true = &capped;
124 break;
125 case SPECIAL_EQUAL:
126 left_true = &capped;
127 right_true = &capped;
128 break;
129 case SPECIAL_NOTEQUAL:
130 left_false = &capped;
131 right_false = &capped;
132 break;
134 default:
135 return;
138 set_true_false_states_expr(my_id, expr->right, right_true, right_false);
139 set_true_false_states_expr(my_id, expr->left, left_true, left_false);
142 static void match_assign(struct expression *expr)
144 if (is_capped(expr->right)) {
145 set_state_expr(my_id, expr->left, &capped);
146 } else {
147 if (get_state_expr(my_id, expr->left))
148 set_state_expr(my_id, expr->left, &uncapped);
152 static void match_caller_info(struct expression *expr)
154 struct expression *tmp;
155 int i;
157 i = 0;
158 FOR_EACH_PTR(expr->args, tmp) {
159 if (is_capped(tmp))
160 sql_insert_caller_info(expr, CAPPED_DATA, i, "$$", "1");
161 i++;
162 } END_FOR_EACH_PTR(tmp);
165 static void struct_member_callback(struct expression *call, int param, char *printed_name, struct smatch_state *state)
167 if (state != &capped)
168 return;
169 sql_insert_caller_info(call, CAPPED_DATA, param, printed_name, "1");
172 static int is_unmodified(const char *name)
174 char orig[256];
176 snprintf(orig, sizeof(orig), "%s orig", name);
178 if (get_comparison_strings(name, orig) == SPECIAL_EQUAL)
179 return 1;
180 return 0;
183 static void print_return_implies_capped(int return_id, char *return_ranges, struct expression *expr)
185 struct smatch_state *orig;
186 struct sm_state *sm;
187 const char *param_name;
188 int param;
190 FOR_EACH_PTR(__get_cur_slist(), sm) {
191 if (sm->owner != my_id)
192 continue;
193 if (sm->state != &capped)
194 continue;
196 param = get_param_num_from_sym(sm->sym);
197 if (param < 0)
198 continue;
200 orig = get_state_slist(get_start_states(), my_id, sm->name, sm->sym);
201 if (orig == &capped)
202 continue;
204 if (!is_unmodified(sm->name))
205 continue;
207 param_name = get_param_name(sm);
208 if (!param_name)
209 continue;
211 sql_insert_return_states(return_id, return_ranges, CAPPED_DATA,
212 param, param_name, "1");
213 } END_FOR_EACH_PTR(sm);
216 static void db_return_states_capped(struct expression *expr, int param, char *key, char *value)
218 char *name;
219 struct symbol *sym;
221 name = return_state_to_var_sym(expr, param, key, &sym);
222 if (!name || !sym)
223 goto free;
225 set_state(my_id, name, sym, &capped);
226 free:
227 free_string(name);
230 void register_capped(int id)
232 my_id = id;
234 select_caller_info_hook(set_param_capped_data, CAPPED_DATA);
235 add_hook(&match_condition, CONDITION_HOOK);
236 add_hook(&match_assign, ASSIGNMENT_HOOK);
238 add_hook(&match_caller_info, FUNCTION_CALL_HOOK);
239 add_member_info_callback(my_id, struct_member_callback);
241 add_split_return_callback(print_return_implies_capped);
242 select_return_states_hook(CAPPED_DATA, &db_return_states_capped);