1 /*
   2  * Copyright (C) 2017 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_extra.h"
  20 
  21 static int find_param_eq(struct expression *expr, int size)
  22 {
  23         struct expression *arg;
  24         sval_t val;
  25         int i;
  26 
  27         i = -1;
  28         FOR_EACH_PTR(expr->args, arg) {
  29                 i++;
  30                 if (!get_implied_value(arg, &val))
  31                         continue;
  32                 if (val.value == size)
  33                         return i;
  34         } END_FOR_EACH_PTR(arg);
  35 
  36         return -1;
  37 }
  38 
  39 static void match_call(struct expression *expr)
  40 {
  41         struct expression *arg;
  42         struct symbol *type;
  43         int size, bytes;
  44         int i, nr;
  45         char buf[16];
  46 
  47 
  48         i = -1;
  49         FOR_EACH_PTR(expr->args, arg) {
  50                 i++;
  51                 type = get_type(arg);
  52                 if (!type || (type->type != SYM_PTR && type->type != SYM_ARRAY))
  53                         continue;
  54                 size = get_array_size(arg);
  55                 if (size > 0) {
  56                         nr = find_param_eq(expr, size);
  57                         if (nr >= 0) {
  58                                 snprintf(buf, sizeof(buf), "%d", nr);
  59                                 sql_insert_caller_info(expr, ARRAYSIZE_ARG, i, buf, "");
  60                                 continue;
  61                         }
  62                 }
  63                 bytes = get_array_size_bytes(arg);
  64                 if (bytes > 0) {
  65                         nr = find_param_eq(expr, bytes);
  66                         if (nr >= 0) {
  67                                 snprintf(buf, sizeof(buf), "%d", nr);
  68                                 sql_insert_caller_info(expr, SIZEOF_ARG, i, buf, "");
  69                                 continue;
  70                         }
  71                 }
  72         } END_FOR_EACH_PTR(arg);
  73 }
  74 
  75 void register_passes_array_size(int id)
  76 {
  77         add_hook(&match_call, FUNCTION_CALL_HOOK);
  78 }
  79