1 /* 2 * Copyright (C) 2012 Oracle. 3 * 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. 8 * 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. 13 * 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 16 */ 17 18 #include "smatch.h" 19 #include "smatch_function_hashtable.h" 20 21 static int my_id; 22 23 DEFINE_STRING_HASHTABLE_STATIC(unconstant_macros); 24 25 static int does_inc_dec(struct expression *expr) 26 { 27 if (expr->type == EXPR_PREOP || expr->type == EXPR_POSTOP) { 28 if (expr->op == SPECIAL_INCREMENT || expr->op == SPECIAL_DECREMENT) 29 return 1; 30 return does_inc_dec(expr->unop); 31 } 32 return 0; 33 } 34 35 static int expr_equiv_no_inc_dec(struct expression *one, struct expression *two) 36 { 37 if (does_inc_dec(one) || does_inc_dec(two)) 38 return 0; 39 return expr_equiv(one, two); 40 } 41 42 static int inconsistent_check(struct expression *left, struct expression *right) 43 { 44 sval_t sval; 45 46 if (get_value(left->left, &sval)) { 47 if (get_value(right->left, &sval)) 48 return expr_equiv_no_inc_dec(left->right, right->right); 49 if (get_value(right->right, &sval)) 50 return expr_equiv_no_inc_dec(left->right, right->left); 51 return 0; 52 } 53 if (get_value(left->right, &sval)) { 54 if (get_value(right->left, &sval)) 55 return expr_equiv_no_inc_dec(left->left, right->right); 56 if (get_value(right->right, &sval)) 57 return expr_equiv_no_inc_dec(left->left, right->left); 58 return 0; 59 } 60 61 return 0; 62 } 63 64 static void check_or(struct expression *expr) 65 { 66 struct expression *left, *right; 67 68 left = strip_expr(expr->left); 69 right = strip_expr(expr->right); 70 71 if (left->type != EXPR_COMPARE || left->op != SPECIAL_NOTEQUAL) 72 return; 73 if (right->type != EXPR_COMPARE || right->op != SPECIAL_NOTEQUAL) 74 return; 75 if (!inconsistent_check(left, right)) 76 return; 77 78 sm_warning("was && intended here instead of ||?"); 79 } 80 81 static int is_kernel_min_macro(struct expression *expr) 82 { 83 char *macro; 84 85 if (option_project != PROJ_KERNEL) 86 return 0; 87 macro = get_macro_name(expr->pos); 88 if (!macro) 89 return 0; 90 if (strcmp(macro, "min") == 0 || 91 strcmp(macro, "min_t") == 0 || 92 strcmp(macro, "max") == 0 || 93 strcmp(macro, "max_t") == 0) 94 return 1; 95 return 0; 96 } 97 98 static void check_and(struct expression *expr) 99 { 100 struct expression *left, *right; 101 102 if (is_kernel_min_macro(expr)) 103 return; 104 105 left = strip_expr(expr->left); 106 right = strip_expr(expr->right); 107 108 if (left->type != EXPR_COMPARE || left->op != SPECIAL_EQUAL) 109 return; 110 if (right->type != EXPR_COMPARE || right->op != SPECIAL_EQUAL) 111 return; 112 if (!inconsistent_check(left, right)) 113 return; 114 115 sm_warning("was || intended here instead of &&?"); 116 } 117 118 static void match_logic(struct expression *expr) 119 { 120 if (expr->type != EXPR_LOGICAL) 121 return; 122 123 if (expr->op == SPECIAL_LOGICAL_OR) 124 check_or(expr); 125 if (expr->op == SPECIAL_LOGICAL_AND) 126 check_and(expr); 127 } 128 129 static int is_unconstant_macro(struct expression *expr) 130 { 131 char *macro; 132 133 macro = get_macro_name(expr->pos); 134 if (!macro) 135 return 0; 136 if (search_unconstant_macros(unconstant_macros, macro)) 137 return 1; 138 return 0; 139 } 140 141 static void match_condition(struct expression *expr) 142 { 143 sval_t sval; 144 145 if (expr->type != EXPR_BINOP) 146 return; 147 if (expr->op == '|') { 148 if (get_value(expr->left, &sval) || get_value(expr->right, &sval)) 149 sm_warning("suspicious bitop condition"); 150 return; 151 } 152 153 if (expr->op != '&') 154 return; 155 156 if (get_macro_name(expr->pos)) 157 return; 158 if (is_unconstant_macro(expr->left) || is_unconstant_macro(expr->right)) 159 return; 160 161 if ((get_value(expr->left, &sval) && sval.value == 0) || 162 (get_value(expr->right, &sval) && sval.value == 0)) 163 sm_warning("bitwise AND condition is false here"); 164 } 165 166 static void match_binop(struct expression *expr) 167 { 168 sval_t left, right, sval; 169 170 if (expr->op != '&') 171 return; 172 if (!get_value(expr, &sval) || sval.value != 0) 173 return; 174 if (get_macro_name(expr->pos)) 175 return; 176 if (!get_value(expr->left, &left) || !get_value(expr->right, &right)) 177 return; 178 sm_warning("odd binop '0x%llx & 0x%llx'", left.uvalue, right.uvalue); 179 } 180 181 void check_or_vs_and(int id) 182 { 183 my_id = id; 184 185 unconstant_macros = create_function_hashtable(100); 186 load_strings("unconstant_macros", unconstant_macros); 187 188 add_hook(&match_logic, LOGIC_HOOK); 189 add_hook(&match_condition, CONDITION_HOOK); 190 if (option_spammy) 191 add_hook(&match_binop, BINOP_HOOK); 192 } 193