rosenberg: strip away some casting (eliminates a false positive)
[smatch.git] / check_passes_sizeof.c
blobce77fb20e00d86406448ee8987a052575b9a84a4
1 /*
2 * Copyright (C) 2012 Oracle.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see http://www.gnu.org/copyleft/gpl.txt
18 #include "smatch.h"
19 #include "smatch_extra.h"
20 #include "smatch_slist.h"
22 #define NOBUF -2
24 static int my_id;
26 static int expr_equiv(struct expression *one, struct expression *two)
28 struct symbol *one_sym, *two_sym;
29 char *one_name = NULL;
30 char *two_name = NULL;
31 int ret = 0;
33 if (!one || !two)
34 return 0;
35 if (one->type != two->type)
36 return 0;
38 one_name = expr_to_str_sym(one, &one_sym);
39 if (!one_name || !one_sym)
40 goto free;
41 two_name = expr_to_str_sym(two, &two_sym);
42 if (!two_name || !two_sym)
43 goto free;
44 if (one_sym != two_sym)
45 goto free;
46 if (strcmp(one_name, two_name) == 0)
47 ret = 1;
48 free:
49 free_string(one_name);
50 free_string(two_name);
51 return ret;
54 static struct expression *get_returned_expr(struct expression *expr)
56 struct statement *stmt;
58 stmt = last_ptr_list((struct ptr_list *)big_statement_stack);
59 if (!stmt || stmt->type != STMT_EXPRESSION)
60 return NULL;
61 if (stmt->expression->type != EXPR_ASSIGNMENT)
62 return NULL;
63 if (stmt->expression->right != expr)
64 return NULL;
65 return stmt->expression->left;
68 static struct expression *remove_dereference(struct expression *expr)
70 if (!expr || expr->type != EXPR_PREOP || expr->op != '*')
71 return expr;
72 expr = expr->unop;
73 if (!expr || expr->type != EXPR_PREOP || expr->op != '*')
74 return expr;
75 return expr->unop;
78 static int get_buf_number(struct expression *call, struct expression *size_arg)
80 struct expression *arg;
81 int idx = -1;
83 size_arg = strip_expr(size_arg->cast_expression);
84 size_arg = remove_dereference(size_arg);
86 arg = get_returned_expr(call);
87 if (arg && expr_equiv(arg, size_arg))
88 return idx;
90 FOR_EACH_PTR(call->args, arg) {
91 idx++;
92 if (expr_equiv(arg, size_arg))
93 return idx;
94 } END_FOR_EACH_PTR(arg);
96 return NOBUF;
99 static void match_call(struct expression *call)
101 struct expression *arg;
102 char *name;
103 int buf_nr;
104 int i = -1;
106 if (call->fn->type != EXPR_SYMBOL)
107 return;
109 name = expr_to_var(call->fn);
110 FOR_EACH_PTR(call->args, arg) {
111 i++;
112 if (arg->type != EXPR_SIZEOF)
113 continue;
114 buf_nr = get_buf_number(call, arg);
115 if (buf_nr == NOBUF)
116 sm_msg("info: sizeof_param '%s' %d", name, i);
117 else
118 sm_msg("info: sizeof_param '%s' %d %d", name, i, buf_nr);
119 } END_FOR_EACH_PTR(arg);
120 free_string(name);
123 void check_passes_sizeof(int id)
125 if (!option_info)
126 return;
128 my_id = id;
129 add_hook(&match_call, FUNCTION_CALL_HOOK);