1*1f5207b7SJohn Levon /*
2*1f5207b7SJohn Levon * Copyright (C) 2012 Oracle.
3*1f5207b7SJohn Levon *
4*1f5207b7SJohn Levon * This program is free software; you can redistribute it and/or
5*1f5207b7SJohn Levon * modify it under the terms of the GNU General Public License
6*1f5207b7SJohn Levon * as published by the Free Software Foundation; either version 2
7*1f5207b7SJohn Levon * of the License, or (at your option) any later version.
8*1f5207b7SJohn Levon *
9*1f5207b7SJohn Levon * This program is distributed in the hope that it will be useful,
10*1f5207b7SJohn Levon * but WITHOUT ANY WARRANTY; without even the implied warranty of
11*1f5207b7SJohn Levon * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12*1f5207b7SJohn Levon * GNU General Public License for more details.
13*1f5207b7SJohn Levon *
14*1f5207b7SJohn Levon * You should have received a copy of the GNU General Public License
15*1f5207b7SJohn Levon * along with this program; if not, see http://www.gnu.org/copyleft/gpl.txt
16*1f5207b7SJohn Levon */
17*1f5207b7SJohn Levon
18*1f5207b7SJohn Levon #include "smatch.h"
19*1f5207b7SJohn Levon #include "smatch_extra.h"
20*1f5207b7SJohn Levon #include "smatch_slist.h"
21*1f5207b7SJohn Levon
22*1f5207b7SJohn Levon #define NOBUF -2
23*1f5207b7SJohn Levon
24*1f5207b7SJohn Levon static int my_id;
25*1f5207b7SJohn Levon
get_returned_expr(struct expression * expr)26*1f5207b7SJohn Levon static struct expression *get_returned_expr(struct expression *expr)
27*1f5207b7SJohn Levon {
28*1f5207b7SJohn Levon struct statement *stmt;
29*1f5207b7SJohn Levon
30*1f5207b7SJohn Levon stmt = last_ptr_list((struct ptr_list *)big_statement_stack);
31*1f5207b7SJohn Levon if (!stmt || stmt->type != STMT_EXPRESSION || !stmt->expression)
32*1f5207b7SJohn Levon return NULL;
33*1f5207b7SJohn Levon if (stmt->expression->type != EXPR_ASSIGNMENT)
34*1f5207b7SJohn Levon return NULL;
35*1f5207b7SJohn Levon if (stmt->expression->right != expr)
36*1f5207b7SJohn Levon return NULL;
37*1f5207b7SJohn Levon return stmt->expression->left;
38*1f5207b7SJohn Levon }
39*1f5207b7SJohn Levon
remove_dereference(struct expression * expr)40*1f5207b7SJohn Levon static struct expression *remove_dereference(struct expression *expr)
41*1f5207b7SJohn Levon {
42*1f5207b7SJohn Levon if (!expr || expr->type != EXPR_PREOP || expr->op != '*')
43*1f5207b7SJohn Levon return expr;
44*1f5207b7SJohn Levon expr = expr->unop;
45*1f5207b7SJohn Levon if (!expr || expr->type != EXPR_PREOP || expr->op != '*')
46*1f5207b7SJohn Levon return expr;
47*1f5207b7SJohn Levon return expr->unop;
48*1f5207b7SJohn Levon }
49*1f5207b7SJohn Levon
get_buf_number(struct expression * call,struct expression * size_arg)50*1f5207b7SJohn Levon static int get_buf_number(struct expression *call, struct expression *size_arg)
51*1f5207b7SJohn Levon {
52*1f5207b7SJohn Levon struct expression *arg;
53*1f5207b7SJohn Levon int idx = -1;
54*1f5207b7SJohn Levon
55*1f5207b7SJohn Levon size_arg = strip_expr(size_arg->cast_expression);
56*1f5207b7SJohn Levon size_arg = remove_dereference(size_arg);
57*1f5207b7SJohn Levon
58*1f5207b7SJohn Levon arg = get_returned_expr(call);
59*1f5207b7SJohn Levon if (arg && expr_equiv(arg, size_arg))
60*1f5207b7SJohn Levon return idx;
61*1f5207b7SJohn Levon
62*1f5207b7SJohn Levon FOR_EACH_PTR(call->args, arg) {
63*1f5207b7SJohn Levon idx++;
64*1f5207b7SJohn Levon if (expr_equiv(arg, size_arg))
65*1f5207b7SJohn Levon return idx;
66*1f5207b7SJohn Levon } END_FOR_EACH_PTR(arg);
67*1f5207b7SJohn Levon
68*1f5207b7SJohn Levon return NOBUF;
69*1f5207b7SJohn Levon }
70*1f5207b7SJohn Levon
match_call(struct expression * call)71*1f5207b7SJohn Levon static void match_call(struct expression *call)
72*1f5207b7SJohn Levon {
73*1f5207b7SJohn Levon struct expression *arg;
74*1f5207b7SJohn Levon char *name;
75*1f5207b7SJohn Levon int buf_nr;
76*1f5207b7SJohn Levon int i = -1;
77*1f5207b7SJohn Levon
78*1f5207b7SJohn Levon if (call->fn->type != EXPR_SYMBOL)
79*1f5207b7SJohn Levon return;
80*1f5207b7SJohn Levon
81*1f5207b7SJohn Levon name = expr_to_var(call->fn);
82*1f5207b7SJohn Levon FOR_EACH_PTR(call->args, arg) {
83*1f5207b7SJohn Levon i++;
84*1f5207b7SJohn Levon if (arg->type != EXPR_SIZEOF)
85*1f5207b7SJohn Levon continue;
86*1f5207b7SJohn Levon buf_nr = get_buf_number(call, arg);
87*1f5207b7SJohn Levon if (buf_nr == NOBUF)
88*1f5207b7SJohn Levon sm_msg("info: sizeof_param '%s' %d", name, i);
89*1f5207b7SJohn Levon else
90*1f5207b7SJohn Levon sm_msg("info: sizeof_param '%s' %d %d", name, i, buf_nr);
91*1f5207b7SJohn Levon } END_FOR_EACH_PTR(arg);
92*1f5207b7SJohn Levon free_string(name);
93*1f5207b7SJohn Levon }
94*1f5207b7SJohn Levon
check_passes_sizeof(int id)95*1f5207b7SJohn Levon void check_passes_sizeof(int id)
96*1f5207b7SJohn Levon {
97*1f5207b7SJohn Levon if (!option_info)
98*1f5207b7SJohn Levon return;
99*1f5207b7SJohn Levon
100*1f5207b7SJohn Levon my_id = id;
101*1f5207b7SJohn Levon add_hook(&match_call, FUNCTION_CALL_HOOK);
102*1f5207b7SJohn Levon }
103