math: Use function call information
[smatch.git] / smatch_buf_size.c
blob0275127e91a118c7e10bb1c7e41e740ed6f283b4
1 /*
2 * smatch/smatch_buf_size.c
4 * Copyright (C) 2010 Dan Carpenter.
6 * Licensed under the Open Software License version 1.1
8 */
10 #include <stdlib.h>
11 #include <errno.h>
12 #include "parse.h"
13 #include "smatch.h"
14 #include "smatch_slist.h"
15 #include "smatch_extra.h"
18 * This check has two smatch IDs.
19 * my_size_id - used to store the size of arrays.
20 * my_strlen_id - track the strlen() of buffers.
23 static int my_size_id;
24 static int my_strlen_id;
26 struct limiter {
27 int buf_arg;
28 int limit_arg;
30 static struct limiter b0_l2 = {0, 2};
32 static void set_undefined(struct sm_state *sm)
34 if (sm->state != &undefined)
35 set_state(sm->owner, sm->name, sm->sym, &undefined);
38 static struct smatch_state *merge_func(struct smatch_state *s1, struct smatch_state *s2)
40 if (PTR_INT(s1->data) == PTR_INT(s2->data))
41 return s1;
42 return &undefined;
45 void set_param_buf_size(const char *name, struct symbol *sym, char *key, char *value)
47 char fullname[256];
48 unsigned int size;
50 if (strncmp(key, "$$", 2))
51 return;
53 snprintf(fullname, 256, "%s%s", name, key + 2);
55 errno = 0;
56 size = strtoul(value, NULL, 10);
57 if (errno)
58 return;
60 set_state(my_size_id, fullname, sym, alloc_state_num(size));
63 static int bytes_per_element(struct expression *expr)
65 struct symbol *type;
66 int bpe;
68 if (expr->type == EXPR_STRING)
69 return 1;
70 type = get_type(expr);
71 if (!type)
72 return 0;
74 if (type->type != SYM_PTR && type->type != SYM_ARRAY)
75 return 0;
77 type = get_base_type(type);
78 bpe = bits_to_bytes(type->bit_size);
80 if (bpe == -1) /* void pointer */
81 bpe = 1;
83 return bpe;
86 static int bytes_to_elements(struct expression *expr, int bytes)
88 int bpe;
90 bpe = bytes_per_element(expr);
91 if (bpe == 0)
92 return 0;
93 return bytes / bpe;
96 static int elements_to_bytes(struct expression *expr, int elements)
98 int bpe;
100 bpe = bytes_per_element(expr);
101 return elements * bpe;
104 static int get_initializer_size(struct expression *expr)
106 switch (expr->type) {
107 case EXPR_STRING:
108 return expr->string->length;
109 case EXPR_INITIALIZER: {
110 struct expression *tmp;
111 int i = 0;
112 int max = 0;
114 FOR_EACH_PTR(expr->expr_list, tmp) {
115 if (tmp->type == EXPR_INDEX && tmp->idx_to > max)
116 max = tmp->idx_to;
117 i++;
118 } END_FOR_EACH_PTR(tmp);
119 if (max)
120 return max + 1;
121 return i;
123 case EXPR_SYMBOL:
124 return get_array_size(expr);
126 return 0;
129 static int db_size;
130 static int db_size_callback(void *unused, int argc, char **argv, char **azColName)
132 if (db_size == 0)
133 db_size = atoi(argv[0]);
134 else
135 db_size = -1;
136 return 0;
139 static int size_from_db(struct expression *expr)
141 int this_file_only = 0;
142 char *name;
144 if (!option_spammy)
145 return 0;
147 name = get_member_name(expr);
148 if (!name && is_static(expr)) {
149 name = expr_to_var(expr);
150 this_file_only = 1;
152 if (!name)
153 return 0;
155 db_size = 0;
156 run_sql(db_size_callback, "select size from type_size where type = '%s' and file = '%s'",
157 name, get_filename());
158 if (db_size == -1)
159 return 0;
160 if (db_size != 0)
161 return db_size;
162 if (this_file_only)
163 return 0;
165 run_sql(db_size_callback, "select size from type_size where type = '%s'",
166 name);
168 if (db_size == -1)
169 db_size = 0;
171 return db_size;
174 static void db_returns_buf_size(struct expression *expr, int param, char *unused, char *math)
176 struct expression *call;
177 sval_t sval;
179 if (expr->type != EXPR_ASSIGNMENT)
180 return;
181 call = strip_expr(expr->right);
183 if (!parse_call_math(call, math, &sval))
184 return;
185 set_state_expr(my_size_id, expr->left, alloc_state_num(sval.value));
188 int get_real_array_size(struct expression *expr)
190 struct symbol *type;
191 sval_t sval;
193 if (expr->type == EXPR_BINOP) /* array elements foo[5] */
194 return 0;
196 type = get_type(expr);
197 if (!type || type->type != SYM_ARRAY)
198 return 0;
200 if (!get_implied_value(type->array_size, &sval))
201 return 0;
203 /* People put one element arrays on the end of structs */
204 if (sval.value == 1)
205 return 0;
207 return sval.value;
210 static int get_size_from_initializer(struct expression *expr)
212 if (expr->type != EXPR_SYMBOL || !expr->symbol || !expr->symbol->initializer)
213 return 0;
214 if (expr->symbol->initializer == expr) /* int a = a; */
215 return 0;
216 return get_initializer_size(expr->symbol->initializer);
219 static int get_stored_size_bytes(struct expression *expr)
221 struct smatch_state *state;
223 state = get_state_expr(my_size_id, expr);
224 if (!state)
225 return 0;
226 return PTR_INT(state->data);
229 static int get_stored_size_bytes_min(struct expression *expr)
231 struct sm_state *sm, *tmp;
232 int min = 0;
234 sm = get_sm_state_expr(my_size_id, expr);
235 if (!sm)
236 return 0;
237 FOR_EACH_PTR(sm->possible, tmp) {
238 if (PTR_INT(tmp->state->data) <= 0)
239 continue;
240 if (PTR_INT(tmp->state->data) < min)
241 min = PTR_INT(tmp->state->data);
242 } END_FOR_EACH_PTR(tmp);
244 return min;
247 static int get_bytes_from_address(struct expression *expr)
249 struct symbol *type;
250 int ret;
252 if (!option_spammy)
253 return 0;
254 if (expr->type != EXPR_PREOP || expr->op != '&')
255 return 0;
256 type = get_type(expr);
257 if (!type)
258 return 0;
260 if (type->type == SYM_PTR)
261 type = get_base_type(type);
263 ret = bits_to_bytes(type->bit_size);
264 if (ret == -1)
265 return 0;
266 if (ret == 1)
267 return 0; /* ignore char pointers */
269 return ret;
272 static int get_size_from_strlen(struct expression *expr)
274 struct smatch_state *state;
275 sval_t len;
277 state = get_state_expr(my_strlen_id, expr);
278 if (!state || !state->data)
279 return 0;
280 if (!get_implied_max((struct expression *)state->data, &len))
281 return 0;
282 if (sval_is_max(len))
283 return 0;
284 return len.value + 1; /* add one because strlen doesn't include the NULL */
287 static struct expression *remove_addr_fluff(struct expression *expr)
289 struct expression *tmp;
290 sval_t sval;
292 expr = strip_expr(expr);
294 /* remove '&' and '*' operations that cancel */
295 while (expr && expr->type == EXPR_PREOP && expr->op == '&') {
296 tmp = strip_expr(expr->unop);
297 if (tmp->type != EXPR_PREOP)
298 break;
299 if (tmp->op != '*')
300 break;
301 expr = strip_expr(tmp->unop);
304 if (!expr)
305 return NULL;
307 /* "foo + 0" is just "foo" */
308 if (expr->type == EXPR_BINOP && expr->op == '+' &&
309 get_value(expr->right, &sval) && sval.value == 0)
310 return expr->left;
312 return expr;
315 static int is_last_member_of_struct(struct symbol *sym, struct ident *member)
317 struct symbol *tmp;
318 int i;
320 i = 0;
321 FOR_EACH_PTR_REVERSE(sym->symbol_list, tmp) {
322 if (i++ || !tmp->ident)
323 return 0;
324 if (tmp->ident == member)
325 return 1;
326 return 0;
327 } END_FOR_EACH_PTR_REVERSE(tmp);
329 return 0;
332 static int get_stored_size_end_struct_bytes(struct expression *expr)
334 struct symbol *type;
335 char *name;
336 struct symbol *sym;
337 struct smatch_state *state;
338 sval_t sval;
340 if (expr->type == EXPR_BINOP) /* array elements foo[5] */
341 return 0;
343 type = get_type(expr);
344 if (!type || type->type != SYM_ARRAY)
345 return 0;
347 if (!get_implied_value(type->array_size, &sval))
348 return 0;
350 if (sval.value != 0 && sval.value != 1)
351 return 0;
353 name = expr_to_var_sym(expr, &sym);
354 free_string(name);
355 if (!sym || !sym->ident || !sym->ident->name)
356 return 0;
357 if (!sym->bit_size)
358 return 0;
360 if (sym->type != SYM_NODE)
361 return 0;
363 state = get_state(my_size_id, sym->ident->name, sym);
364 if (!state || !state->data)
365 return 0;
367 sym = get_real_base_type(sym);
368 if (!sym || sym->type != SYM_PTR)
369 return 0;
370 sym = get_real_base_type(sym);
371 if (!sym || sym->type != SYM_STRUCT)
372 return 0;
373 if (!is_last_member_of_struct(sym, expr->member))
374 return 0;
376 return PTR_INT(state->data) - bits_to_bytes(sym->bit_size) +
377 bits_to_bytes(type->bit_size);
380 int get_array_size_bytes(struct expression *expr)
382 int size;
384 expr = remove_addr_fluff(expr);
385 if (!expr)
386 return 0;
388 /* strcpy(foo, "BAR"); */
389 if (expr->type == EXPR_STRING)
390 return expr->string->length;
392 /* buf[4] */
393 size = get_real_array_size(expr);
394 if (size)
395 return elements_to_bytes(expr, size);
397 /* buf = malloc(1024); */
398 size = get_stored_size_bytes(expr);
399 if (size)
400 return size;
402 size = get_stored_size_end_struct_bytes(expr);
403 if (size)
404 return size;
406 /* char *foo = "BAR" */
407 size = get_size_from_initializer(expr);
408 if (size)
409 return elements_to_bytes(expr, size);
411 size = get_bytes_from_address(expr);
412 if (size)
413 return size;
415 /* if (strlen(foo) > 4) */
416 size = get_size_from_strlen(expr);
417 if (size)
418 return size;
420 return size_from_db(expr);
423 int get_array_size_bytes_min(struct expression *expr)
425 int size;
426 int tmp;
428 size = get_array_size_bytes(expr);
430 tmp = get_stored_size_bytes_min(expr);
431 if (size <= 0 || (tmp >= 1 && tmp < size))
432 size = tmp;
433 return size;
436 int get_array_size(struct expression *expr)
438 int bytes;
440 bytes = get_array_size_bytes(expr);
441 return bytes_to_elements(expr, bytes);
444 static void match_strlen_condition(struct expression *expr)
446 struct expression *left;
447 struct expression *right;
448 struct expression *str = NULL;
449 int strlen_left = 0;
450 int strlen_right = 0;
451 sval_t sval;
452 struct smatch_state *true_state = NULL;
453 struct smatch_state *false_state = NULL;
455 if (expr->type != EXPR_COMPARE)
456 return;
457 left = strip_expr(expr->left);
458 right = strip_expr(expr->right);
460 if (left->type == EXPR_CALL && sym_name_is("strlen", left->fn)) {
461 str = get_argument_from_call_expr(left->args, 0);
462 strlen_left = 1;
464 if (right->type == EXPR_CALL && sym_name_is("strlen", right->fn)) {
465 str = get_argument_from_call_expr(right->args, 0);
466 strlen_right = 1;
469 if (!strlen_left && !strlen_right)
470 return;
471 if (strlen_left && strlen_right)
472 return;
474 if (strlen_left) {
475 if (!get_value(right, &sval))
476 return;
478 if (strlen_right) {
479 if (!get_value(left, &sval))
480 return;
483 if (expr->op == SPECIAL_EQUAL) {
484 set_true_false_states_expr(my_size_id, str, alloc_state_num(sval.value + 1), NULL);
485 return;
487 if (expr->op == SPECIAL_NOTEQUAL) {
488 set_true_false_states_expr(my_size_id, str, NULL, alloc_state_num(sval.value + 1));
489 return;
492 switch (expr->op) {
493 case '<':
494 case SPECIAL_UNSIGNED_LT:
495 if (strlen_left)
496 true_state = alloc_state_num(sval.value);
497 else
498 false_state = alloc_state_num(sval.value + 1);
499 break;
500 case SPECIAL_LTE:
501 case SPECIAL_UNSIGNED_LTE:
502 if (strlen_left)
503 true_state = alloc_state_num(sval.value + 1);
504 else
505 false_state = alloc_state_num(sval.value);
506 break;
507 case SPECIAL_GTE:
508 case SPECIAL_UNSIGNED_GTE:
509 if (strlen_left)
510 false_state = alloc_state_num(sval.value);
511 else
512 true_state = alloc_state_num(sval.value + 1);
513 break;
514 case '>':
515 case SPECIAL_UNSIGNED_GT:
516 if (strlen_left)
517 false_state = alloc_state_num(sval.value + 1);
518 else
519 true_state = alloc_state_num(sval.value);
520 break;
522 set_true_false_states_expr(my_size_id, str, true_state, false_state);
525 static struct expression *strip_ampersands(struct expression *expr)
527 struct symbol *type;
529 if (expr->type != EXPR_PREOP)
530 return expr;
531 if (expr->op != '&')
532 return expr;
533 type = get_type(expr->unop);
534 if (!type || type->type != SYM_ARRAY)
535 return expr;
536 return expr->unop;
539 static void match_array_assignment(struct expression *expr)
541 struct expression *left;
542 struct expression *right;
543 int array_size;
545 if (expr->op != '=')
546 return;
547 left = strip_expr(expr->left);
548 right = strip_expr(expr->right);
549 right = strip_ampersands(right);
550 array_size = get_array_size_bytes(right);
551 if (array_size)
552 set_state_expr(my_size_id, left, alloc_state_num(array_size));
555 static void info_record_alloction(struct expression *buffer, struct expression *size)
557 char *name;
558 sval_t sval;
560 if (!option_info)
561 return;
563 name = get_member_name(buffer);
564 if (!name && is_static(buffer))
565 name = expr_to_var(buffer);
566 if (!name)
567 return;
568 if (get_implied_value(size, &sval))
569 sql_insert_type_size(name, sval.value);
570 else
571 sql_insert_type_size(name, -1);
573 free_string(name);
576 static void match_alloc(const char *fn, struct expression *expr, void *_size_arg)
578 int size_arg = PTR_INT(_size_arg);
579 struct expression *right;
580 struct expression *arg;
581 sval_t bytes;
583 right = strip_expr(expr->right);
584 arg = get_argument_from_call_expr(right->args, size_arg);
586 info_record_alloction(expr->left, arg);
588 if (!get_implied_value(arg, &bytes))
589 return;
590 set_state_expr(my_size_id, expr->left, alloc_state_num(bytes.value));
593 static void match_calloc(const char *fn, struct expression *expr, void *unused)
595 struct expression *right;
596 struct expression *arg;
597 sval_t elements;
598 sval_t size;
600 right = strip_expr(expr->right);
601 arg = get_argument_from_call_expr(right->args, 0);
602 if (!get_implied_value(arg, &elements))
603 return;
604 arg = get_argument_from_call_expr(right->args, 1);
605 if (!get_implied_value(arg, &size))
606 return;
607 set_state_expr(my_size_id, expr->left, alloc_state_num(elements.value * size.value));
610 static void match_strlen(const char *fn, struct expression *expr, void *unused)
612 struct expression *right;
613 struct expression *str;
614 struct expression *len_expr;
615 char *len_name;
616 struct smatch_state *state;
618 right = strip_expr(expr->right);
619 str = get_argument_from_call_expr(right->args, 0);
620 len_expr = strip_expr(expr->left);
622 len_name = expr_to_var(len_expr);
623 if (!len_name)
624 return;
626 state = __alloc_smatch_state(0);
627 state->name = len_name;
628 state->data = len_expr;
629 set_state_expr(my_strlen_id, str, state);
632 static void match_limited(const char *fn, struct expression *expr, void *_limiter)
634 struct limiter *limiter = (struct limiter *)_limiter;
635 struct expression *dest;
636 struct expression *size_expr;
637 sval_t size;
639 dest = get_argument_from_call_expr(expr->args, limiter->buf_arg);
640 size_expr = get_argument_from_call_expr(expr->args, limiter->limit_arg);
641 if (!get_implied_max(size_expr, &size))
642 return;
643 set_state_expr(my_size_id, dest, alloc_state_num(size.value));
646 static void match_strcpy(const char *fn, struct expression *expr, void *unused)
648 struct expression fake_assign;
650 fake_assign.op = '=';
651 fake_assign.left = get_argument_from_call_expr(expr->args, 0);
652 fake_assign.right = get_argument_from_call_expr(expr->args, 1);
653 match_array_assignment(&fake_assign);
656 static void match_strndup(const char *fn, struct expression *expr, void *unused)
658 struct expression *fn_expr;
659 struct expression *size_expr;
660 sval_t size;
662 fn_expr = strip_expr(expr->right);
663 size_expr = get_argument_from_call_expr(fn_expr->args, 1);
664 if (!get_implied_max(size_expr, &size))
665 return;
667 /* It's easy to forget space for the NUL char */
668 size.value++;
669 set_state_expr(my_size_id, expr->left, alloc_state_num(size.value));
672 static void match_call(struct expression *expr)
674 struct expression *arg;
675 int bytes;
676 int i;
678 i = 0;
679 FOR_EACH_PTR(expr->args, arg) {
680 bytes = get_array_size_bytes(arg);
681 if (bytes > 1) {
682 char buf[11];
684 snprintf(buf, sizeof(buf), "%d", bytes);
685 sql_insert_caller_info(expr, BUF_SIZE, i, "$$", buf);
687 i++;
688 } END_FOR_EACH_PTR(arg);
691 static void struct_member_callback(struct expression *call, int param, char *printed_name, struct smatch_state *state)
693 if (state == &merged)
694 return;
695 sql_insert_caller_info(call, BUF_SIZE, param, printed_name, state->name);
698 void register_buf_size(int id)
700 my_size_id = id;
702 add_definition_db_callback(set_param_buf_size, BUF_SIZE);
703 add_db_return_states_callback(BUF_SIZE, &db_returns_buf_size);
705 add_function_assign_hook("malloc", &match_alloc, INT_PTR(0));
706 add_function_assign_hook("calloc", &match_calloc, NULL);
707 add_function_assign_hook("memdup", &match_alloc, INT_PTR(1));
708 if (option_project == PROJ_KERNEL) {
709 add_function_assign_hook("kmalloc", &match_alloc, INT_PTR(0));
710 add_function_assign_hook("kzalloc", &match_alloc, INT_PTR(0));
711 add_function_assign_hook("vmalloc", &match_alloc, INT_PTR(0));
712 add_function_assign_hook("__vmalloc", &match_alloc, INT_PTR(0));
713 add_function_assign_hook("kcalloc", &match_calloc, NULL);
714 add_function_assign_hook("kmalloc_array", &match_calloc, NULL);
715 add_function_assign_hook("drm_malloc_ab", &match_calloc, NULL);
716 add_function_assign_hook("drm_calloc_large", &match_calloc, NULL);
717 add_function_assign_hook("sock_kmalloc", &match_alloc, INT_PTR(1));
718 add_function_assign_hook("kmemdup", &match_alloc, INT_PTR(1));
719 add_function_assign_hook("kmemdup_user", &match_alloc, INT_PTR(1));
720 add_function_assign_hook("dma_alloc_attrs", &match_alloc, INT_PTR(1));
722 add_hook(&match_array_assignment, ASSIGNMENT_HOOK);
723 add_hook(&match_strlen_condition, CONDITION_HOOK);
724 add_function_assign_hook("strlen", &match_strlen, NULL);
726 add_function_assign_hook("strndup", match_strndup, NULL);
727 if (option_project == PROJ_KERNEL)
728 add_function_assign_hook("kstrndup", match_strndup, NULL);
730 add_modification_hook(my_size_id, &set_undefined);
732 add_merge_hook(my_size_id, &merge_func);
735 void register_strlen(int id)
737 my_strlen_id = id;
738 add_modification_hook(my_strlen_id, &set_undefined);
739 add_merge_hook(my_strlen_id, &merge_func);
742 void register_buf_size_late(int id)
744 add_function_hook("strlcpy", &match_limited, &b0_l2);
745 add_function_hook("strlcat", &match_limited, &b0_l2);
746 add_function_hook("memscan", &match_limited, &b0_l2);
748 add_function_hook("strcpy", &match_strcpy, NULL);
750 add_hook(&match_call, FUNCTION_CALL_HOOK);
751 add_member_info_callback(my_size_id, struct_member_callback);