dereference: fix a crash
[smatch.git] / check_units.c
blob90c4db657c4606cb556d458508ed0ccd6c93e221
1 /*
2 * Copyright (C) 2018 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_slist.h"
21 static int my_id;
23 static void check_mult(struct expression *expr)
25 struct smatch_state *left, *right;
26 int bit_found = 0, byte_found = 0;
27 char *name;
29 left = get_units(expr->left);
30 right = get_units(expr->right);
32 if (left == &unit_bit || right == &unit_bit)
33 bit_found++;
34 if (left == &unit_byte || right == &unit_byte)
35 byte_found++;
37 if (bit_found && byte_found) {
38 name = expr_to_str(expr);
39 sm_warning("multiplying bits * bytes '%s'", name);
40 free_string(name);
44 static void check_add_sub(struct expression *expr)
46 struct smatch_state *left, *right;
47 struct symbol *type;
48 char *str;
50 type = get_type(expr->left);
51 if (type && (type->type == SYM_PTR || type->type == SYM_ARRAY))
52 return;
54 left = get_units(expr->left);
55 right = get_units(expr->right);
57 if (!left || !right || left == right)
58 return;
59 str = expr_to_str(expr);
60 sm_warning("missing conversion: '%s' '%s %s %s'", str, left->name, show_special(expr->op), right->name);
61 free_string(str);
64 static void match_binop_check(struct expression *expr)
66 switch (expr->op) {
67 case '+':
68 case '-':
69 check_add_sub(expr);
70 return;
71 case '*':
72 check_mult(expr);
73 return;
77 static void match_condition_check(struct expression *expr)
79 struct smatch_state *left, *right;
80 char *str;
82 if (expr->type != EXPR_COMPARE)
83 return;
85 left = get_units(expr->left);
86 right = get_units(expr->right);
88 if (!left || !right)
89 return;
90 if (left == right)
91 return;
93 str = expr_to_str(expr);
94 sm_msg("warn: comparing different units: '%s' '%s %s %s'", str, left->name, show_special(expr->op), right->name);
95 free_string(str);
98 void check_units(int id)
100 my_id = id;
102 if (!option_spammy)
103 return;
105 add_hook(&match_binop_check, BINOP_HOOK);
106 add_hook(&match_condition_check, CONDITION_HOOK);