1 /*
   2  * Copyright (C) 2010 Dan Carpenter.
   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 void match_strcpy(const char *fn, struct expression *expr, void *unused)
  21 {
  22         struct expression *dest;
  23         struct expression *data;
  24         char *dest_name = NULL;
  25         char *data_name = NULL;
  26         int dest_size;
  27         int data_size;
  28 
  29         dest = get_argument_from_call_expr(expr->args, 0);
  30         data = get_argument_from_call_expr(expr->args, 1);
  31         dest_size = get_array_size_bytes(dest);
  32         if (!dest_size)
  33                 return;
  34 
  35         data_size = get_size_from_strlen(data);
  36         if (!data_size)
  37                 data_size = get_array_size_bytes(data);
  38 
  39         /* If the size of both arrays is known and the destination
  40          * buffer is larger than the source buffer, we're okay.
  41          */
  42         if (data_size && dest_size >= data_size)
  43                 return;
  44 
  45         dest_name = expr_to_str(dest);
  46         data_name = expr_to_str(data);
  47 
  48         if (data_size)
  49                 sm_error("%s() '%s' too large for '%s' (%d vs %d)",
  50                         fn, data_name, dest_name, data_size, dest_size);
  51         else if (option_spammy)
  52                 sm_warning("%s() '%s' of unknown size might be too large for '%s'",
  53                         fn, data_name, dest_name);
  54 
  55         free_string(dest_name);
  56         free_string(data_name);
  57 }
  58 
  59 void check_strcpy_overflow(int id)
  60 {
  61         add_function_hook("strcpy", &match_strcpy, NULL);
  62 }