Print this page
11506 smatch resync


  22  * are too many functions which implement that function pointer so we give up.
  23  * Also maybe we don't have the database enabled.
  24  *
  25  * The goal here is to make a call back so what if we call:
  26  *
  27  *      frob(&foo);
  28  *
  29  * but we're not able to say what happens to "foo", then let's assume that we
  30  * don't know anything about "foo" if it's an untracked call.
  31  *
  32  */
  33 
  34 #include "smatch.h"
  35 #include "smatch_slist.h"
  36 #include "smatch_extra.h"
  37 
  38 static int my_id;
  39 static int tracked;
  40 
  41 STATE(untracked);

  42 
  43 typedef void (untracked_hook)(struct expression *call, int param);
  44 DECLARE_PTR_LIST(untracked_hook_list, untracked_hook *);
  45 static struct untracked_hook_list *untracked_hooks;

  46 
  47 struct int_stack *tracked_stack;
  48 
  49 void add_untracked_param_hook(void (func)(struct expression *call, int param))
  50 {
  51         untracked_hook **p = malloc(sizeof(untracked_hook *));
  52         *p = func;
  53         add_ptr_list(&untracked_hooks, p);
  54 }
  55 
  56 static void call_untracked_callbacks(struct expression *expr, int param)
  57 {
  58         untracked_hook **fn;
  59 
  60         FOR_EACH_PTR(untracked_hooks, fn) {
  61                 (*fn)(expr, param);
  62         } END_FOR_EACH_PTR(fn);
  63 }
  64 
















  65 static void assume_tracked(struct expression *call_expr, int param, char *key, char *value)
  66 {
  67         tracked = 1;
  68 }
  69 
  70 void mark_untracked(struct expression *expr, int param, const char *key, const char *value)
  71 {

















  72         char *name;
  73         struct symbol *sym;
  74 
  75         while (expr->type == EXPR_ASSIGNMENT)
  76                 expr = strip_expr(expr->right);
  77         if (expr->type != EXPR_CALL)
  78                 return;
  79 
  80         name = return_state_to_var_sym(expr, param, key, &sym);


  81         if (!name || !sym)
  82                 goto free;

  83 


  84         call_untracked_callbacks(expr, param);
  85         set_state(my_id, name, sym, &untracked);
  86 free:
  87         free_string(name);

  88 }
  89 










  90 static int lost_in_va_args(struct expression *expr)
  91 {
  92         struct symbol *fn;
  93         char *name;
  94         int is_lost;
  95 
  96         fn = get_type(expr->fn);
  97         if (!fn || !fn->variadic)
  98                 return 0;
  99 
 100         is_lost = 1;
 101         name = expr_to_var(expr->fn);
 102         if (name && strstr(name, "print"))
 103                 is_lost = 0;
 104         free_string(name);
 105 
 106         return is_lost;
 107 }
 108 
 109 static void match_after_call(struct expression *expr)


 116                 tracked = 0;
 117 
 118         if (tracked) {
 119                 tracked = 0;
 120                 return;
 121         }
 122 
 123         i = -1;
 124         FOR_EACH_PTR(expr->args, arg) {
 125                 i++;
 126 
 127                 type = get_type(arg);
 128                 if (!type || type->type != SYM_PTR)
 129                         continue;
 130 
 131                 call_untracked_callbacks(expr, i);
 132                 set_state_expr(my_id, arg, &untracked);
 133         } END_FOR_EACH_PTR(arg);
 134 }
 135 
 136 void mark_all_params_untracked(int return_id, char *return_ranges, struct expression *expr)

 137 {
 138         struct symbol *arg;
 139         int param;
 140 
 141         param = -1;
 142         FOR_EACH_PTR(cur_func_sym->ctype.base_type->arguments, arg) {
 143                 param++;
 144 
 145                 if (!arg->ident)
 146                         continue;
 147                 sql_insert_return_states(return_id, return_ranges,
 148                                          UNTRACKED_PARAM, param, "$", "");
 149         } END_FOR_EACH_PTR(arg);
 150 }
 151 











 152 static void print_untracked_params(int return_id, char *return_ranges, struct expression *expr)
 153 {

 154         struct symbol *arg;
 155         int param;

 156 
 157         param = -1;
 158         FOR_EACH_PTR(cur_func_sym->ctype.base_type->arguments, arg) {
 159                 param++;
 160 
 161                 if (!arg->ident)
 162                         continue;
 163                 if (!get_state(my_id, arg->ident->name, arg) &&
 164                     !__bail_on_rest_of_function)  /* hairy functions are untrackable */








 165                         continue;

 166 
 167                 sql_insert_return_states(return_id, return_ranges,
 168                                          UNTRACKED_PARAM, param, "$", "");
 169         } END_FOR_EACH_PTR(arg);
 170 }
 171 
 172 static void match_param_assign(struct expression *expr)
 173 {
 174         struct expression *right;
 175         struct symbol *type;
 176         int param;
 177 
 178         if (__in_fake_assign)
 179                 return;
 180 
 181         right = strip_expr(expr->right);
 182         type = get_type(right);
 183         if (!type || type->type != SYM_PTR)
 184                 return;
 185 
 186         param = get_param_num(right);
 187         if (param < 0)
 188                 return;


 220                 }
 221         } END_FOR_EACH_PTR(expr);
 222 }
 223 
 224 static void match_inline_start(struct expression *expr)
 225 {
 226         push_int(&tracked_stack, tracked);
 227 }
 228 
 229 static void match_inline_end(struct expression *expr)
 230 {
 231         tracked = pop_int(&tracked_stack);
 232 }
 233 
 234 void register_untracked_param(int id)
 235 {
 236         my_id = id;
 237 
 238         select_return_states_hook(INTERNAL, &assume_tracked);
 239         select_return_states_hook(UNTRACKED_PARAM, &mark_untracked);

 240         add_hook(&match_after_call, FUNCTION_CALL_HOOK_AFTER_DB);
 241 
 242         add_split_return_callback(&print_untracked_params);
 243 
 244         add_hook(&match_param_assign, ASSIGNMENT_HOOK);
 245         add_hook(&match_param_assign_in_asm, ASM_HOOK);
 246 
 247         add_hook(&match_inline_start, INLINE_FN_START);
 248         add_hook(&match_inline_end, INLINE_FN_END);
 249 }


  22  * are too many functions which implement that function pointer so we give up.
  23  * Also maybe we don't have the database enabled.
  24  *
  25  * The goal here is to make a call back so what if we call:
  26  *
  27  *      frob(&foo);
  28  *
  29  * but we're not able to say what happens to "foo", then let's assume that we
  30  * don't know anything about "foo" if it's an untracked call.
  31  *
  32  */
  33 
  34 #include "smatch.h"
  35 #include "smatch_slist.h"
  36 #include "smatch_extra.h"
  37 
  38 static int my_id;
  39 static int tracked;
  40 
  41 STATE(untracked);
  42 STATE(lost);
  43 
  44 typedef void (untracked_hook)(struct expression *call, int param);
  45 DECLARE_PTR_LIST(untracked_hook_list, untracked_hook *);
  46 static struct untracked_hook_list *untracked_hooks;
  47 static struct untracked_hook_list *lost_hooks;
  48 
  49 struct int_stack *tracked_stack;
  50 
  51 void add_untracked_param_hook(void (func)(struct expression *call, int param))
  52 {
  53         untracked_hook **p = malloc(sizeof(untracked_hook *));
  54         *p = func;
  55         add_ptr_list(&untracked_hooks, p);
  56 }
  57 
  58 static void call_untracked_callbacks(struct expression *expr, int param)
  59 {
  60         untracked_hook **fn;
  61 
  62         FOR_EACH_PTR(untracked_hooks, fn) {
  63                 (*fn)(expr, param);
  64         } END_FOR_EACH_PTR(fn);
  65 }
  66 
  67 void add_lost_param_hook(void (func)(struct expression *call, int param))
  68 {
  69         untracked_hook **p = malloc(sizeof(untracked_hook *));
  70         *p = func;
  71         add_ptr_list(&lost_hooks, p);
  72 }
  73 
  74 static void call_lost_callbacks(struct expression *expr, int param)
  75 {
  76         untracked_hook **fn;
  77 
  78         FOR_EACH_PTR(lost_hooks, fn) {
  79                 (*fn)(expr, param);
  80         } END_FOR_EACH_PTR(fn);
  81 }
  82 
  83 static void assume_tracked(struct expression *call_expr, int param, char *key, char *value)
  84 {
  85         tracked = 1;
  86 }
  87 
  88 static char *get_array_from_key(struct expression *expr, int param, const char *key, struct symbol **sym)
  89 {
  90         struct expression *arg;
  91 
  92         arg = get_argument_from_call_expr(expr->args, param);
  93         if (!arg)
  94                 return NULL;
  95         if (arg->type != EXPR_PREOP || arg->op != '&')
  96                 return NULL;
  97         arg = arg->unop;
  98         if (!is_array(arg))
  99                 return NULL;
 100         arg = get_array_base(arg);
 101 
 102         return expr_to_var_sym(arg, sym);
 103 }
 104 
 105 static void mark_untracked_lost(struct expression *expr, int param, const char *key, int type)
 106 {
 107         char *name;
 108         struct symbol *sym;
 109 
 110         while (expr->type == EXPR_ASSIGNMENT)
 111                 expr = strip_expr(expr->right);
 112         if (expr->type != EXPR_CALL)
 113                 return;
 114 
 115         name = return_state_to_var_sym(expr, param, key, &sym);
 116         if (!name || !sym) {
 117                 name = get_array_from_key(expr, param, key, &sym);
 118                 if (!name || !sym)
 119                         goto free;
 120         }
 121 
 122         if (type == LOST_PARAM)
 123                 call_lost_callbacks(expr, param);
 124         call_untracked_callbacks(expr, param);
 125         set_state(my_id, name, sym, &untracked);
 126 free:
 127         free_string(name);
 128 
 129 }
 130 
 131 void mark_untracked(struct expression *expr, int param, const char *key, const char *value)
 132 {
 133         mark_untracked_lost(expr, param, key, UNTRACKED_PARAM);
 134 }
 135 
 136 void mark_lost(struct expression *expr, int param, const char *key, const char *value)
 137 {
 138         mark_untracked_lost(expr, param, key, LOST_PARAM);
 139 }
 140 
 141 static int lost_in_va_args(struct expression *expr)
 142 {
 143         struct symbol *fn;
 144         char *name;
 145         int is_lost;
 146 
 147         fn = get_type(expr->fn);
 148         if (!fn || !fn->variadic)
 149                 return 0;
 150 
 151         is_lost = 1;
 152         name = expr_to_var(expr->fn);
 153         if (name && strstr(name, "print"))
 154                 is_lost = 0;
 155         free_string(name);
 156 
 157         return is_lost;
 158 }
 159 
 160 static void match_after_call(struct expression *expr)


 167                 tracked = 0;
 168 
 169         if (tracked) {
 170                 tracked = 0;
 171                 return;
 172         }
 173 
 174         i = -1;
 175         FOR_EACH_PTR(expr->args, arg) {
 176                 i++;
 177 
 178                 type = get_type(arg);
 179                 if (!type || type->type != SYM_PTR)
 180                         continue;
 181 
 182                 call_untracked_callbacks(expr, i);
 183                 set_state_expr(my_id, arg, &untracked);
 184         } END_FOR_EACH_PTR(arg);
 185 }
 186 
 187 
 188 static void mark_all_params(int return_id, char *return_ranges, int type)
 189 {
 190         struct symbol *arg;
 191         int param;
 192 
 193         param = -1;
 194         FOR_EACH_PTR(cur_func_sym->ctype.base_type->arguments, arg) {
 195                 param++;
 196 
 197                 if (!arg->ident)
 198                         continue;
 199                 sql_insert_return_states(return_id, return_ranges,
 200                                          type, param, "$", "");
 201         } END_FOR_EACH_PTR(arg);
 202 }
 203 
 204 
 205 void mark_all_params_untracked(int return_id, char *return_ranges, struct expression *expr)
 206 {
 207         mark_all_params(return_id, return_ranges, UNTRACKED_PARAM);
 208 }
 209 
 210 void mark_all_params_lost(int return_id, char *return_ranges, struct expression *expr)
 211 {
 212         mark_all_params(return_id, return_ranges, LOST_PARAM);
 213 }
 214 
 215 static void print_untracked_params(int return_id, char *return_ranges, struct expression *expr)
 216 {
 217         struct sm_state *sm;
 218         struct symbol *arg;
 219         int param;
 220         int type;
 221 
 222         param = -1;
 223         FOR_EACH_PTR(cur_func_sym->ctype.base_type->arguments, arg) {
 224                 param++;
 225 
 226                 if (!arg->ident)
 227                         continue;
 228 
 229                 if (__bail_on_rest_of_function) {
 230                         /* hairy functions are lost */
 231                         type = LOST_PARAM;
 232                 } else if ((sm = get_sm_state(my_id, arg->ident->name, arg))) {
 233                         if (slist_has_state(sm->possible, &lost))
 234                                 type = LOST_PARAM;
 235                         else
 236                                 type = UNTRACKED_PARAM;
 237                 } else {
 238                         continue;
 239                 }
 240 
 241                 sql_insert_return_states(return_id, return_ranges,
 242                                          type, param, "$", "");
 243         } END_FOR_EACH_PTR(arg);
 244 }
 245 
 246 static void match_param_assign(struct expression *expr)
 247 {
 248         struct expression *right;
 249         struct symbol *type;
 250         int param;
 251 
 252         if (__in_fake_assign)
 253                 return;
 254 
 255         right = strip_expr(expr->right);
 256         type = get_type(right);
 257         if (!type || type->type != SYM_PTR)
 258                 return;
 259 
 260         param = get_param_num(right);
 261         if (param < 0)
 262                 return;


 294                 }
 295         } END_FOR_EACH_PTR(expr);
 296 }
 297 
 298 static void match_inline_start(struct expression *expr)
 299 {
 300         push_int(&tracked_stack, tracked);
 301 }
 302 
 303 static void match_inline_end(struct expression *expr)
 304 {
 305         tracked = pop_int(&tracked_stack);
 306 }
 307 
 308 void register_untracked_param(int id)
 309 {
 310         my_id = id;
 311 
 312         select_return_states_hook(INTERNAL, &assume_tracked);
 313         select_return_states_hook(UNTRACKED_PARAM, &mark_untracked);
 314         select_return_states_hook(LOST_PARAM, &mark_lost);
 315         add_hook(&match_after_call, FUNCTION_CALL_HOOK_AFTER_DB);
 316 
 317         add_split_return_callback(&print_untracked_params);
 318 
 319         add_hook(&match_param_assign, ASSIGNMENT_HOOK);
 320         add_hook(&match_param_assign_in_asm, ASM_HOOK);
 321 
 322         add_hook(&match_inline_start, INLINE_FN_START);
 323         add_hook(&match_inline_end, INLINE_FN_END);
 324 }