1 /*
   2  * Copyright (C) 2014 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 
  20 static int my_id;
  21 
  22 static void match_binop(struct expression *expr)
  23 {
  24         struct symbol *type;
  25         sval_t bits;
  26 
  27         if (expr->op != SPECIAL_RIGHTSHIFT)
  28                 return;
  29 
  30         if (!get_implied_value(expr->right, &bits))
  31                 return;
  32 
  33         type = get_type(expr->left);
  34         if (!type)
  35                 return;
  36         if (type_bits(type) == -1 || type_bits(type) > bits.value)
  37                 return;
  38         sm_warning("right shifting more than type allows %d vs %lld", type_bits(type), bits.value);
  39 }
  40 
  41 static void match_binop2(struct expression *expr)
  42 {
  43         struct expression *left;
  44         struct expression *tmp;
  45         sval_t mask, shift;
  46 
  47         if (expr->op != SPECIAL_RIGHTSHIFT)
  48                 return;
  49 
  50         left = strip_expr(expr->left);
  51         tmp = get_assigned_expr(left);
  52         if (tmp)
  53                 left = tmp;
  54         if (left->type != EXPR_BINOP || left->op != '&')
  55                 return;
  56 
  57         if (!get_implied_value(expr->right, &shift))
  58                 return;
  59         if (!get_implied_value(left->right, &mask))
  60                 return;
  61 
  62         if (mask.uvalue >> shift.uvalue)
  63                 return;
  64 
  65         sm_warning("mask and shift to zero");
  66 }
  67 
  68 static void match_assign(struct expression *expr)
  69 {
  70         struct symbol *type;
  71         sval_t bits;
  72 
  73         if (expr->op != SPECIAL_SHR_ASSIGN)
  74                 return;
  75 
  76         if (!get_implied_value(expr->right, &bits))
  77                 return;
  78         type = get_type(expr->left);
  79         if (!type)
  80                 return;
  81         if (type_bits(type) > bits.value)
  82                 return;
  83         sm_warning("right shift assign to zero");
  84 }
  85 
  86 void check_shift_to_zero(int id)
  87 {
  88         my_id = id;
  89 
  90         add_hook(&match_binop, BINOP_HOOK);
  91         add_hook(&match_binop2, BINOP_HOOK);
  92 
  93         add_hook(&match_assign, ASSIGNMENT_HOOK);
  94 
  95 }