buf_size: handle empty arrays on the end of structs
[smatch.git] / smatch_buf_size.c
blob1ada81a8adcfd96575018a7bffa44e749607d91e
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 static 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->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 /* "foo + 0" is just "foo" */
305 if (expr->type == EXPR_BINOP && expr->op == '+' &&
306 get_value(expr->right, &sval) && sval.value == 0)
307 return expr->left;
309 return expr;
312 static int is_last_member_of_struct(struct symbol *sym, struct ident *member)
314 struct symbol *tmp;
315 int i;
317 i = 0;
318 FOR_EACH_PTR_REVERSE(sym->symbol_list, tmp) {
319 if (i++ || !tmp->ident)
320 return 0;
321 if (tmp->ident == member)
322 return 1;
323 return 0;
324 } END_FOR_EACH_PTR_REVERSE(tmp);
326 return 0;
329 static int get_stored_size_end_struct_bytes(struct expression *expr)
331 struct symbol *type;
332 char *name;
333 struct symbol *sym;
334 struct smatch_state *state;
335 sval_t sval;
337 if (expr->type == EXPR_BINOP) /* array elements foo[5] */
338 return 0;
340 type = get_type(expr);
341 if (!type || type->type != SYM_ARRAY)
342 return 0;
344 if (!get_implied_value(type->array_size, &sval))
345 return 0;
347 if (sval.value != 0 && sval.value != 1)
348 return 0;
350 name = expr_to_var_sym(expr, &sym);
351 free_string(name);
352 if (!sym || !sym->ident || !sym->ident->name)
353 return 0;
354 if (!sym->bit_size)
355 return 0;
357 if (sym->type != SYM_NODE)
358 return 0;
360 state = get_state(my_size_id, sym->ident->name, sym);
361 if (!state || !state->data)
362 return 0;
364 sym = get_real_base_type(sym);
365 if (!sym || sym->type != SYM_PTR)
366 return 0;
367 sym = get_real_base_type(sym);
368 if (!sym || sym->type != SYM_STRUCT)
369 return 0;
370 if (!is_last_member_of_struct(sym, expr->member))
371 return 0;
373 return PTR_INT(state->data) - bits_to_bytes(sym->bit_size) +
374 bits_to_bytes(type->bit_size);
377 int get_array_size_bytes(struct expression *expr)
379 int size;
381 expr = remove_addr_fluff(expr);
382 if (!expr)
383 return 0;
385 /* strcpy(foo, "BAR"); */
386 if (expr->type == EXPR_STRING)
387 return expr->string->length;
389 /* buf[4] */
390 size = get_real_array_size(expr);
391 if (size)
392 return elements_to_bytes(expr, size);
394 /* buf = malloc(1024); */
395 size = get_stored_size_bytes(expr);
396 if (size)
397 return size;
399 size = get_stored_size_end_struct_bytes(expr);
400 if (size)
401 return size;
403 /* char *foo = "BAR" */
404 size = get_size_from_initializer(expr);
405 if (size)
406 return elements_to_bytes(expr, size);
408 size = get_bytes_from_address(expr);
409 if (size)
410 return size;
412 /* if (strlen(foo) > 4) */
413 size = get_size_from_strlen(expr);
414 if (size)
415 return size;
417 return size_from_db(expr);
420 int get_array_size_bytes_min(struct expression *expr)
422 int size;
423 int tmp;
425 size = get_array_size_bytes(expr);
427 tmp = get_stored_size_bytes_min(expr);
428 if (size <= 0 || (tmp >= 1 && tmp < size))
429 size = tmp;
430 return size;
433 int get_array_size(struct expression *expr)
435 int bytes;
437 bytes = get_array_size_bytes(expr);
438 return bytes_to_elements(expr, bytes);
441 static void match_strlen_condition(struct expression *expr)
443 struct expression *left;
444 struct expression *right;
445 struct expression *str = NULL;
446 int strlen_left = 0;
447 int strlen_right = 0;
448 sval_t sval;
449 struct smatch_state *true_state = NULL;
450 struct smatch_state *false_state = NULL;
452 if (expr->type != EXPR_COMPARE)
453 return;
454 left = strip_expr(expr->left);
455 right = strip_expr(expr->right);
457 if (left->type == EXPR_CALL && sym_name_is("strlen", left->fn)) {
458 str = get_argument_from_call_expr(left->args, 0);
459 strlen_left = 1;
461 if (right->type == EXPR_CALL && sym_name_is("strlen", right->fn)) {
462 str = get_argument_from_call_expr(right->args, 0);
463 strlen_right = 1;
466 if (!strlen_left && !strlen_right)
467 return;
468 if (strlen_left && strlen_right)
469 return;
471 if (strlen_left) {
472 if (!get_value(right, &sval))
473 return;
475 if (strlen_right) {
476 if (!get_value(left, &sval))
477 return;
480 if (expr->op == SPECIAL_EQUAL) {
481 set_true_false_states_expr(my_size_id, str, alloc_state_num(sval.value + 1), NULL);
482 return;
484 if (expr->op == SPECIAL_NOTEQUAL) {
485 set_true_false_states_expr(my_size_id, str, NULL, alloc_state_num(sval.value + 1));
486 return;
489 switch (expr->op) {
490 case '<':
491 case SPECIAL_UNSIGNED_LT:
492 if (strlen_left)
493 true_state = alloc_state_num(sval.value);
494 else
495 false_state = alloc_state_num(sval.value + 1);
496 break;
497 case SPECIAL_LTE:
498 case SPECIAL_UNSIGNED_LTE:
499 if (strlen_left)
500 true_state = alloc_state_num(sval.value + 1);
501 else
502 false_state = alloc_state_num(sval.value);
503 break;
504 case SPECIAL_GTE:
505 case SPECIAL_UNSIGNED_GTE:
506 if (strlen_left)
507 false_state = alloc_state_num(sval.value);
508 else
509 true_state = alloc_state_num(sval.value + 1);
510 break;
511 case '>':
512 case SPECIAL_UNSIGNED_GT:
513 if (strlen_left)
514 false_state = alloc_state_num(sval.value + 1);
515 else
516 true_state = alloc_state_num(sval.value);
517 break;
519 set_true_false_states_expr(my_size_id, str, true_state, false_state);
522 static struct expression *strip_ampersands(struct expression *expr)
524 struct symbol *type;
526 if (expr->type != EXPR_PREOP)
527 return expr;
528 if (expr->op != '&')
529 return expr;
530 type = get_type(expr->unop);
531 if (!type || type->type != SYM_ARRAY)
532 return expr;
533 return expr->unop;
536 static void match_array_assignment(struct expression *expr)
538 struct expression *left;
539 struct expression *right;
540 int array_size;
542 if (expr->op != '=')
543 return;
544 left = strip_expr(expr->left);
545 right = strip_expr(expr->right);
546 right = strip_ampersands(right);
547 array_size = get_array_size_bytes(right);
548 if (array_size)
549 set_state_expr(my_size_id, left, alloc_state_num(array_size));
552 static void info_record_alloction(struct expression *buffer, struct expression *size)
554 char *name;
555 sval_t sval;
557 if (!option_info)
558 return;
560 name = get_member_name(buffer);
561 if (!name && is_static(buffer))
562 name = expr_to_var(buffer);
563 if (!name)
564 return;
565 if (get_implied_value(size, &sval))
566 sql_insert_type_size(name, sval.value);
567 else
568 sql_insert_type_size(name, -1);
570 free_string(name);
573 static void match_alloc(const char *fn, struct expression *expr, void *_size_arg)
575 int size_arg = PTR_INT(_size_arg);
576 struct expression *right;
577 struct expression *arg;
578 sval_t bytes;
580 right = strip_expr(expr->right);
581 arg = get_argument_from_call_expr(right->args, size_arg);
583 info_record_alloction(expr->left, arg);
585 if (!get_implied_value(arg, &bytes))
586 return;
587 set_state_expr(my_size_id, expr->left, alloc_state_num(bytes.value));
590 static void match_calloc(const char *fn, struct expression *expr, void *unused)
592 struct expression *right;
593 struct expression *arg;
594 sval_t elements;
595 sval_t size;
597 right = strip_expr(expr->right);
598 arg = get_argument_from_call_expr(right->args, 0);
599 if (!get_implied_value(arg, &elements))
600 return;
601 arg = get_argument_from_call_expr(right->args, 1);
602 if (!get_implied_value(arg, &size))
603 return;
604 set_state_expr(my_size_id, expr->left, alloc_state_num(elements.value * size.value));
607 static void match_strlen(const char *fn, struct expression *expr, void *unused)
609 struct expression *right;
610 struct expression *str;
611 struct expression *len_expr;
612 char *len_name;
613 struct smatch_state *state;
615 right = strip_expr(expr->right);
616 str = get_argument_from_call_expr(right->args, 0);
617 len_expr = strip_expr(expr->left);
619 len_name = expr_to_var(len_expr);
620 if (!len_name)
621 return;
623 state = __alloc_smatch_state(0);
624 state->name = len_name;
625 state->data = len_expr;
626 set_state_expr(my_strlen_id, str, state);
629 static void match_limited(const char *fn, struct expression *expr, void *_limiter)
631 struct limiter *limiter = (struct limiter *)_limiter;
632 struct expression *dest;
633 struct expression *size_expr;
634 sval_t size;
636 dest = get_argument_from_call_expr(expr->args, limiter->buf_arg);
637 size_expr = get_argument_from_call_expr(expr->args, limiter->limit_arg);
638 if (!get_implied_max(size_expr, &size))
639 return;
640 set_state_expr(my_size_id, dest, alloc_state_num(size.value));
643 static void match_strcpy(const char *fn, struct expression *expr, void *unused)
645 struct expression fake_assign;
647 fake_assign.op = '=';
648 fake_assign.left = get_argument_from_call_expr(expr->args, 0);
649 fake_assign.right = get_argument_from_call_expr(expr->args, 1);
650 match_array_assignment(&fake_assign);
653 static void match_strndup(const char *fn, struct expression *expr, void *unused)
655 struct expression *fn_expr;
656 struct expression *size_expr;
657 sval_t size;
659 fn_expr = strip_expr(expr->right);
660 size_expr = get_argument_from_call_expr(fn_expr->args, 1);
661 if (!get_implied_max(size_expr, &size))
662 return;
664 /* It's easy to forget space for the NUL char */
665 size.value++;
666 set_state_expr(my_size_id, expr->left, alloc_state_num(size.value));
669 static void match_call(struct expression *expr)
671 struct expression *arg;
672 int bytes;
673 int i;
675 i = 0;
676 FOR_EACH_PTR(expr->args, arg) {
677 bytes = get_array_size_bytes(arg);
678 if (bytes > 1) {
679 char buf[11];
681 snprintf(buf, sizeof(buf), "%d", bytes);
682 sql_insert_caller_info(expr, BUF_SIZE, i, "$$", buf);
684 i++;
685 } END_FOR_EACH_PTR(arg);
688 static void struct_member_callback(struct expression *call, int param, char *printed_name, struct smatch_state *state)
690 if (state == &merged)
691 return;
692 sql_insert_caller_info(call, BUF_SIZE, param, printed_name, state->name);
695 void register_buf_size(int id)
697 my_size_id = id;
699 add_definition_db_callback(set_param_buf_size, BUF_SIZE);
700 add_db_return_states_callback(BUF_SIZE, &db_returns_buf_size);
702 add_function_assign_hook("malloc", &match_alloc, INT_PTR(0));
703 add_function_assign_hook("calloc", &match_calloc, NULL);
704 add_function_assign_hook("memdup", &match_alloc, INT_PTR(1));
705 if (option_project == PROJ_KERNEL) {
706 add_function_assign_hook("kmalloc", &match_alloc, INT_PTR(0));
707 add_function_assign_hook("kzalloc", &match_alloc, INT_PTR(0));
708 add_function_assign_hook("vmalloc", &match_alloc, INT_PTR(0));
709 add_function_assign_hook("__vmalloc", &match_alloc, INT_PTR(0));
710 add_function_assign_hook("kcalloc", &match_calloc, NULL);
711 add_function_assign_hook("kmalloc_array", &match_calloc, NULL);
712 add_function_assign_hook("drm_malloc_ab", &match_calloc, NULL);
713 add_function_assign_hook("drm_calloc_large", &match_calloc, NULL);
714 add_function_assign_hook("sock_kmalloc", &match_alloc, INT_PTR(1));
715 add_function_assign_hook("kmemdup", &match_alloc, INT_PTR(1));
716 add_function_assign_hook("kmemdup_user", &match_alloc, INT_PTR(1));
718 add_hook(&match_array_assignment, ASSIGNMENT_HOOK);
719 add_hook(&match_strlen_condition, CONDITION_HOOK);
720 add_function_assign_hook("strlen", &match_strlen, NULL);
722 add_function_assign_hook("strndup", match_strndup, NULL);
723 if (option_project == PROJ_KERNEL)
724 add_function_assign_hook("kstrndup", match_strndup, NULL);
726 add_modification_hook(my_size_id, &set_undefined);
728 add_merge_hook(my_size_id, &merge_func);
731 void register_strlen(int id)
733 my_strlen_id = id;
734 add_modification_hook(my_strlen_id, &set_undefined);
735 add_merge_hook(my_strlen_id, &merge_func);
738 void register_buf_size_late(int id)
740 add_function_hook("strlcpy", &match_limited, &b0_l2);
741 add_function_hook("strlcat", &match_limited, &b0_l2);
742 add_function_hook("memscan", &match_limited, &b0_l2);
744 add_function_hook("strcpy", &match_strcpy, NULL);
746 add_hook(&match_call, FUNCTION_CALL_HOOK);
747 add_member_info_callback(my_size_id, struct_member_callback);