expressions: add cast_expression()
[smatch.git] / smatch_buf_comparison2.c
blob66fb5c4f4a953bb4668dd90cf168d8e54522496e
1 /*
2 * Copyright (C) 2022 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
19 * The point here is to store that a buffer has x bytes even if we don't know
20 * the value of x.
24 #include "smatch.h"
25 #include "smatch_extra.h"
26 #include "smatch_slist.h"
28 static int my_id;
30 bool buf_comp2_has_bytes(struct expression *buf_expr, struct expression *var)
32 char *buffer_name, *var_name;
33 bool ret = false;
34 int comparison;
35 char buf[64];
37 buffer_name = expr_to_var(buf_expr);
38 if (!buffer_name)
39 return false;
40 var_name = expr_to_var(var);
41 if (!var_name)
42 goto free;
43 snprintf(buf, sizeof(buf), "$size %s", buffer_name);
44 comparison = get_comparison_strings(buf, var_name);
45 if (!comparison)
46 goto free;
48 if (comparison == SPECIAL_EQUAL ||
49 show_special(comparison)[0] == '>')
50 ret = true;
52 free:
53 free_string(buffer_name);
54 free_string(var_name);
55 return ret;
58 static void record_size(struct expression *buffer, struct expression *size, struct expression *mod_expr)
60 struct var_sym_list *buffer_vsl, *size_vsl;
61 char *buffer_name, *size_name;
62 char buf[64];
64 buffer_name = expr_to_chunk_sym_vsl(buffer, NULL, &buffer_vsl);
65 size_name = expr_to_chunk_sym_vsl(size, NULL, &size_vsl);
66 if (!buffer_name || !size_name) {
67 free_string(buffer_name);
68 free_string(size_name);
69 return;
72 snprintf(buf, sizeof(buf), "$size %s", buffer_name);
73 free_string(buffer_name);
74 add_comparison_var_sym(buffer, buf, buffer_vsl, SPECIAL_EQUAL,
75 size, size_name, size_vsl, mod_expr);
78 static void match_allocation(struct expression *expr,
79 const char *name, struct symbol *sym,
80 struct allocation_info *info)
82 struct expression *call, *size_arg;
83 sval_t sval;
85 /* FIXME: hack for testing */
86 if (strcmp(info->size_str, "$0") != 0)
87 return;
89 if (expr->type != EXPR_ASSIGNMENT || expr->op != '=')
90 return;
92 call = expr;
93 while (call && call->type == EXPR_ASSIGNMENT)
94 call = strip_expr(expr->right);
95 if (!call || call->type != EXPR_CALL)
96 return;
98 size_arg = get_argument_from_call_expr(call->args, 0);
99 if (!size_arg)
100 return;
102 if (get_implied_value(size_arg, &sval))
103 return;
105 record_size(expr->left, size_arg, expr);
108 static int get_param(int param, char **name, struct symbol **sym)
110 struct symbol *arg;
111 int i;
113 i = 0;
114 FOR_EACH_PTR(cur_func_sym->ctype.base_type->arguments, arg) {
115 if (i == param) {
116 *name = arg->ident->name;
117 *sym = arg;
118 return TRUE;
120 i++;
121 } END_FOR_EACH_PTR(arg);
123 return FALSE;
126 static void set_param_compare(const char *buffer_name, struct symbol *buffer_sym, char *key, char *value)
128 struct expression *buffer, *size;
129 struct symbol *size_sym;
130 char *size_name;
131 long param;
133 if (strncmp(key, "==$", 3) != 0)
134 return;
135 param = strtol(key + 3, NULL, 10);
136 if (!get_param(param, &size_name, &size_sym))
137 return;
138 buffer = symbol_expression(buffer_sym);
139 size = symbol_expression(size_sym);
141 record_size(buffer, size, NULL);
144 void register_buf_comparison2(int id)
146 my_id = id;
148 add_allocation_hook(&match_allocation);
149 select_caller_info_hook(set_param_compare, BYTE_COUNT);