1 /*
   2  * Copyright (C) 2009 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 /*
  19  * This is not a check.  It just saves an struct expression pointer 
  20  * whenever something is assigned.  This can be used later on by other scripts.
  21  */
  22 
  23 #include "smatch.h"
  24 #include "smatch_slist.h"
  25 #include "smatch_extra.h"
  26 
  27 int check_assigned_expr_id;
  28 static int my_id;
  29 static int link_id;
  30 
  31 static void undef(struct sm_state *sm, struct expression *mod_expr)
  32 {
  33         set_state(my_id, sm->name, sm->sym, &undefined);
  34 }
  35 
  36 struct expression *get_assigned_expr(struct expression *expr)
  37 {
  38         struct smatch_state *state;
  39 
  40         state = get_state_expr(my_id, expr);
  41         if (!state)
  42                 return NULL;
  43         return (struct expression *)state->data;
  44 }
  45 
  46 struct expression *get_assigned_expr_name_sym(const char *name, struct symbol *sym)
  47 {
  48         struct smatch_state *state;
  49 
  50         state = get_state(my_id, name, sym);
  51         if (!state)
  52                 return NULL;
  53         return (struct expression *)state->data;
  54 }
  55 
  56 static void match_assignment(struct expression *expr)
  57 {
  58         struct symbol *left_sym, *right_sym;
  59         char *left_name = NULL;
  60         char *right_name = NULL;
  61 
  62         if (expr->op != '=')
  63                 return;
  64         if (is_fake_call(expr->right))
  65                 return;
  66         if (__in_fake_struct_assign) {
  67                 struct range_list *rl;
  68 
  69                 if (!get_implied_rl(expr->right, &rl))
  70                         return;
  71                 if (is_whole_rl(rl))
  72                         return;
  73         }
  74 
  75         left_name = expr_to_var_sym(expr->left, &left_sym);
  76         if (!left_name || !left_sym)
  77                 goto free;
  78         set_state(my_id, left_name, left_sym, alloc_state_expr(strip_expr(expr->right)));
  79 
  80         right_name = expr_to_var_sym(expr->right, &right_sym);
  81         if (!right_name || !right_sym)
  82                 goto free;
  83 
  84         store_link(link_id, right_name, right_sym, left_name, left_sym);
  85 
  86 free:
  87         free_string(left_name);
  88         free_string(right_name);
  89 }
  90 
  91 static void record_param_assignment(struct expression *expr, int param, char *key, char *value)
  92 {
  93         struct expression *arg, *right;
  94         struct symbol *sym;
  95         char *name;
  96         char *p;
  97         int right_param;
  98 
  99         while (expr->type == EXPR_ASSIGNMENT)
 100                 expr = strip_expr(expr->right);
 101         if (!expr || expr->type != EXPR_CALL)
 102                 return;
 103 
 104         p = strstr(value, "[$");
 105         if (!p)
 106                 return;
 107 
 108         p += 2;
 109         right_param = strtol(p, &p, 10);
 110         if (*p != ']')
 111                 return;
 112 
 113         arg = get_argument_from_call_expr(expr->args, param);
 114         right = get_argument_from_call_expr(expr->args, right_param);
 115         if (!right || !arg)
 116                 return;
 117         name = get_variable_from_key(arg, key, &sym);
 118         if (!name || !sym)
 119                 goto free;
 120 
 121         set_state(my_id, name, sym, alloc_state_expr(right));
 122 free:
 123         free_string(name);
 124 }
 125 
 126 void register_assigned_expr(int id)
 127 {
 128         my_id = check_assigned_expr_id = id;
 129         add_hook(&match_assignment, ASSIGNMENT_HOOK_AFTER);
 130         add_modification_hook(my_id, &undef);
 131         select_return_states_hook(PARAM_SET, &record_param_assignment);
 132 }
 133 
 134 void register_assigned_expr_links(int id)
 135 {
 136         link_id = id;
 137         db_ignore_states(link_id);
 138         set_up_link_functions(my_id, link_id);
 139 }
 140