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
25 #include "smatch_extra.h"
26 #include "smatch_slist.h"
30 bool buf_comp2_has_bytes(struct expression
*buf_expr
, struct expression
*var
)
32 char *buffer_name
, *var_name
;
37 buffer_name
= expr_to_var(buf_expr
);
40 var_name
= expr_to_var(var
);
43 snprintf(buf
, sizeof(buf
), "$size %s", buffer_name
);
44 comparison
= get_comparison_strings(buf
, var_name
);
48 if (comparison
== SPECIAL_EQUAL
||
49 show_special(comparison
)[0] == '>')
53 free_string(buffer_name
);
54 free_string(var_name
);
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
;
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
);
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
;
85 /* FIXME: hack for testing */
86 if (strcmp(info
->size_str
, "$0") != 0)
89 if (expr
->type
!= EXPR_ASSIGNMENT
|| expr
->op
!= '=')
93 while (call
&& call
->type
== EXPR_ASSIGNMENT
)
94 call
= strip_expr(expr
->right
);
95 if (!call
|| call
->type
!= EXPR_CALL
)
98 size_arg
= get_argument_from_call_expr(call
->args
, 0);
102 if (get_implied_value(size_arg
, &sval
))
105 record_size(expr
->left
, size_arg
, expr
);
108 static int get_param(int param
, char **name
, struct symbol
**sym
)
114 FOR_EACH_PTR(cur_func_sym
->ctype
.base_type
->arguments
, arg
) {
116 *name
= arg
->ident
->name
;
121 } END_FOR_EACH_PTR(arg
);
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
;
133 if (strncmp(key
, "==$", 3) != 0)
135 param
= strtol(key
+ 3, NULL
, 10);
136 if (!get_param(param
, &size_name
, &size_sym
))
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
)
148 add_allocation_hook(&match_allocation
);
149 select_caller_info_hook(set_param_compare
, BYTE_COUNT
);