Print this page
12724 update smatch to 0.6.1-rc1-il-5


   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  * There are a bunch of allocation functions where we allocate some memory,
  20  * set up some struct members and then return the allocated memory.  One
  21  * nice thing about this is that we just one pointer to the allocated memory
  22  * so what we can do is we can generate a mtag alias for it in the caller.
  23  */
  24 
  25 #include "smatch.h"

  26 #include "smatch_slist.h"
  27 
  28 static int my_id;
  29 
  30 STATE(fresh);
  31 
  32 struct alloc_info *alloc_funcs;
  33 
  34 struct alloc_info kernel_allocation_funcs[] = {
  35         {"kmalloc", 0},
  36         {"kmalloc_node", 0},
  37         {"kzalloc", 0},
  38         {"kzalloc_node", 0},
  39         {"vmalloc", 0},
  40         {"__vmalloc", 0},
  41         {"kvmalloc", 0},
  42         {"kcalloc", 0, 1},
  43         {"kmalloc_array", 0, 1},
  44         {"sock_kmalloc", 1},
  45         {"kmemdup", 1},


  48         {"pci_alloc_consistent", 1},
  49         {"pci_alloc_coherent", 1},
  50         {"devm_kmalloc", 1},
  51         {"devm_kzalloc", 1},
  52         {"krealloc", 1},
  53         {"__alloc_bootmem", 0},
  54         {"alloc_bootmem", 0},
  55         {"dma_alloc_contiguous", 1},
  56         {"dma_alloc_coherent", 1},
  57         {},
  58 };
  59 
  60 struct alloc_info general_allocation_funcs[] = {
  61         {"malloc", 0},
  62         {"calloc", 0, 1},
  63         {"memdup", 1},
  64         {"realloc", 1},
  65         {},
  66 };
  67 










  68 static int fresh_callback(void *fresh, int argc, char **argv, char **azColName)
  69 {
  70         *(int *)fresh = 1;
  71         return 0;
  72 }
  73 
  74 static int fresh_from_db(struct expression *call)
  75 {
  76         int fresh = 0;
  77 
  78         /* for function pointers assume everything is used */
  79         if (call->fn->type != EXPR_SYMBOL)
  80                 return 0;
  81 
  82         run_sql(&fresh_callback, &fresh,
  83                 "select * from return_states where %s and type = %d and parameter = -1 and key = '$' limit 1;",
  84                 get_static_filter(call->fn->symbol), FRESH_ALLOC);
  85         return fresh;
  86 }
  87 


 133         if (!slist_has_state(sm->possible, &fresh))
 134                 return;
 135         // TODO call unfresh hooks
 136         set_state_expr(my_id, expr, &undefined);
 137 }
 138 
 139 static void match_assign(struct expression *expr)
 140 {
 141         set_unfresh(expr->right);
 142 }
 143 
 144 static void match_call(struct expression *expr)
 145 {
 146         struct expression *arg;
 147 
 148         FOR_EACH_PTR(expr->args, arg) {
 149                 set_unfresh(arg);
 150         } END_FOR_EACH_PTR(arg);
 151 }
 152 

 153 static void set_fresh(struct expression *expr)
 154 {


 155         expr = strip_expr(expr);
 156         if (expr->type != EXPR_SYMBOL)
 157                 return;







 158         set_state_expr(my_id, expr, &fresh);

 159 }
 160 
 161 static void returns_fresh_alloc(struct expression *expr, int param, char *key, char *value)
 162 {
 163         if (param != -1 || !key || strcmp(key, "$") != 0)
 164                 return;
 165         if (expr->type != EXPR_ASSIGNMENT)
 166                 return;
 167 
 168         set_fresh(expr->left);
 169 }
 170 
 171 static void match_alloc(const char *fn, struct expression *expr, void *_size_arg)
 172 {
 173         set_fresh(expr->left);
 174 }
 175 
 176 void register_fresh_alloc(int id)
 177 {
 178         int i;
 179 
 180         my_id = id;
 181 
 182         if (option_project == PROJ_KERNEL)
 183                 alloc_funcs = kernel_allocation_funcs;
 184         else
 185                 alloc_funcs = general_allocation_funcs;
 186 
 187         i = -1;
 188         while (alloc_funcs[++i].fn)
 189                 add_function_assign_hook(alloc_funcs[i].fn, &match_alloc, 0);
 190 
 191         add_split_return_callback(&record_alloc_func);
 192         select_return_states_hook(FRESH_ALLOC, &returns_fresh_alloc);
 193         add_hook(&match_assign, ASSIGNMENT_HOOK);
 194         add_hook(&match_call, FUNCTION_CALL_HOOK);


 195 }


   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  * There are a bunch of allocation functions where we allocate some memory,
  20  * set up some struct members and then return the allocated memory.  One
  21  * nice thing about this is that we just one pointer to the allocated memory
  22  * so what we can do is we can generate a mtag alias for it in the caller.
  23  */
  24 
  25 #include "smatch.h"
  26 #include "smatch_extra.h"
  27 #include "smatch_slist.h"
  28 
  29 static int my_id;
  30 
  31 STATE(fresh);
  32 
  33 struct alloc_info *alloc_funcs;
  34 
  35 struct alloc_info kernel_allocation_funcs[] = {
  36         {"kmalloc", 0},
  37         {"kmalloc_node", 0},
  38         {"kzalloc", 0},
  39         {"kzalloc_node", 0},
  40         {"vmalloc", 0},
  41         {"__vmalloc", 0},
  42         {"kvmalloc", 0},
  43         {"kcalloc", 0, 1},
  44         {"kmalloc_array", 0, 1},
  45         {"sock_kmalloc", 1},
  46         {"kmemdup", 1},


  49         {"pci_alloc_consistent", 1},
  50         {"pci_alloc_coherent", 1},
  51         {"devm_kmalloc", 1},
  52         {"devm_kzalloc", 1},
  53         {"krealloc", 1},
  54         {"__alloc_bootmem", 0},
  55         {"alloc_bootmem", 0},
  56         {"dma_alloc_contiguous", 1},
  57         {"dma_alloc_coherent", 1},
  58         {},
  59 };
  60 
  61 struct alloc_info general_allocation_funcs[] = {
  62         {"malloc", 0},
  63         {"calloc", 0, 1},
  64         {"memdup", 1},
  65         {"realloc", 1},
  66         {},
  67 };
  68 
  69 static void pre_merge_hook(struct sm_state *cur, struct sm_state *other)
  70 {
  71         struct smatch_state *state;
  72         sval_t sval;
  73 
  74         state = get_state(SMATCH_EXTRA, cur->name, cur->sym);
  75         if (estate_get_single_value(state, &sval) && sval.value == 0)
  76                 set_state(my_id, cur->name, cur->sym, &undefined);
  77 }
  78 
  79 static int fresh_callback(void *fresh, int argc, char **argv, char **azColName)
  80 {
  81         *(int *)fresh = 1;
  82         return 0;
  83 }
  84 
  85 static int fresh_from_db(struct expression *call)
  86 {
  87         int fresh = 0;
  88 
  89         /* for function pointers assume everything is used */
  90         if (call->fn->type != EXPR_SYMBOL)
  91                 return 0;
  92 
  93         run_sql(&fresh_callback, &fresh,
  94                 "select * from return_states where %s and type = %d and parameter = -1 and key = '$' limit 1;",
  95                 get_static_filter(call->fn->symbol), FRESH_ALLOC);
  96         return fresh;
  97 }
  98 


 144         if (!slist_has_state(sm->possible, &fresh))
 145                 return;
 146         // TODO call unfresh hooks
 147         set_state_expr(my_id, expr, &undefined);
 148 }
 149 
 150 static void match_assign(struct expression *expr)
 151 {
 152         set_unfresh(expr->right);
 153 }
 154 
 155 static void match_call(struct expression *expr)
 156 {
 157         struct expression *arg;
 158 
 159         FOR_EACH_PTR(expr->args, arg) {
 160                 set_unfresh(arg);
 161         } END_FOR_EACH_PTR(arg);
 162 }
 163 
 164 static struct expression *handled;
 165 static void set_fresh(struct expression *expr)
 166 {
 167         struct range_list *rl;
 168 
 169         expr = strip_expr(expr);
 170         if (expr->type != EXPR_SYMBOL)
 171                 return;
 172         if (expr == handled)
 173                 return;
 174 
 175         get_absolute_rl(expr, &rl);
 176         rl = rl_intersection(rl, valid_ptr_rl);
 177         if (!rl)
 178                 return;
 179         set_state_expr(my_id, expr, &fresh);
 180         handled = expr;
 181 }
 182 
 183 static void returns_fresh_alloc(struct expression *expr, int param, char *key, char *value)
 184 {
 185         if (param != -1 || !key || strcmp(key, "$") != 0)
 186                 return;
 187         if (expr->type != EXPR_ASSIGNMENT)
 188                 return;
 189 
 190         set_fresh(expr->left);
 191 }
 192 
 193 static void match_alloc(const char *fn, struct expression *expr, void *_size_arg)
 194 {
 195         set_fresh(expr->left);
 196 }
 197 
 198 void register_fresh_alloc(int id)
 199 {
 200         int i;
 201 
 202         my_id = id;
 203 
 204         if (option_project == PROJ_KERNEL)
 205                 alloc_funcs = kernel_allocation_funcs;
 206         else
 207                 alloc_funcs = general_allocation_funcs;
 208 
 209         i = -1;
 210         while (alloc_funcs[++i].fn)
 211                 add_function_assign_hook(alloc_funcs[i].fn, &match_alloc, 0);
 212 
 213         add_split_return_callback(&record_alloc_func);
 214         select_return_states_hook(FRESH_ALLOC, &returns_fresh_alloc);
 215         add_hook(&match_assign, ASSIGNMENT_HOOK);
 216         add_hook(&match_call, FUNCTION_CALL_HOOK);
 217 
 218         add_pre_merge_hook(my_id, &pre_merge_hook);
 219 }