Print this page
11506 smatch resync


  45                 return 0;
  46         type = get_real_base_type(type);
  47         if (type->type != SYM_STRUCT)
  48                 return 0;
  49 
  50         i = 0;
  51         FOR_EACH_PTR(type->symbol_list, tmp) {
  52                 i++;
  53                 if (!tmp->ident)
  54                         continue;
  55                 if (strcmp(expr->member->name, tmp->ident->name) == 0) {
  56                         if (i == 1)
  57                                 return 0;
  58                         return 1;
  59                 }
  60         } END_FOR_EACH_PTR(tmp);
  61 
  62         return 0;
  63 }
  64 




















  65 int get_member_offset(struct symbol *type, const char *member_name)
  66 {
  67         struct symbol *tmp;
  68         int offset;

  69 
  70         if (!type || type->type != SYM_STRUCT)
  71                 return -1;
  72 

  73         offset = 0;
  74         FOR_EACH_PTR(type->symbol_list, tmp) {




  75                 offset = ALIGN(offset, tmp->ctype.alignment);
  76                 if (tmp->ident &&
  77                     strcmp(member_name, tmp->ident->name) == 0) {
  78                         return offset;
  79                 }



  80                 offset += type_bytes(tmp);


  81         } END_FOR_EACH_PTR(tmp);
  82         return -1;
  83 }
  84 
  85 int get_member_offset_from_deref(struct expression *expr)
  86 {
  87         struct symbol *type;
  88         struct ident *member;
  89         int offset;
  90 
  91         if (expr->type != EXPR_DEREF)  /* hopefully, this doesn't happen */
  92                 return -1;
  93 
  94         if (expr->member_offset >= 0)
  95                 return expr->member_offset;
  96 
  97         member = expr->member;
  98         if (!member)
  99                 return -1;
 100 
 101         type = get_type(expr->deref);


 102         if (!type || type->type != SYM_STRUCT)
 103                 return -1;
 104 
 105         offset = get_member_offset(type, member->name);
 106         if (offset >= 0)
 107                 expr->member_offset = offset;
 108         return offset;
 109 }
 110 
 111 static struct range_list *filter_unknown_negatives(struct range_list *rl)
 112 {
 113         struct data_range *first;
 114         struct range_list *filter = NULL;
 115 
 116         first = first_ptr_list((struct ptr_list *)rl);
 117 
 118         if (sval_is_min(first->min) &&
 119             sval_is_negative(first->max) &&
 120             first->max.value == -1) {
 121                 add_ptr_list(&filter, first);
 122                 return rl_filter(rl, filter);
 123         }
 124 
 125         return rl;
 126 }
 127 
 128 static void add_offset_to_pointer(struct range_list **rl, int offset)
 129 {
 130         sval_t min, max, remove, sval;
 131         struct range_list *orig = *rl;
 132 
 133         /*
 134          * Ha ha.  Treating zero as a special case means I'm correct at least a
 135          * tiny fraction of the time.  Which is better than nothing.
 136          *
 137          */
 138         if (offset == 0)
 139                 return;
 140 



 141         /*
 142          * This function doesn't necessarily work how you might expect...
 143          *
 144          * Say you have s64min-(-1),1-s64max and you add 8 then I guess what
 145          * we want to say is maybe something like 9-s64max.  This shows that the
 146          * min it could be is 9 which is potentially useful information.  But
 147          * if we start with (-12),5000000-57777777 and we add 8 then we'd want
 148          * the result to be (-4),5000008-57777777 but (-4),5000000-57777777 is
 149          * also probably acceptable.  If you start with s64min-s64max then the
 150          * result should be 8-s64max.
 151          *
 152          */
 153 
 154         /* We do the math on void pointer type, because this isn't "&v + 16" it
 155          * is &v->sixteenth_byte.
 156          */
 157         orig = cast_rl(&ptr_ctype, orig);
 158         min = sval_type_min(&ptr_ctype);
 159         min.value = offset;
 160         max = sval_type_max(&ptr_ctype);
 161 
 162         if (!orig || is_whole_rl(orig)) {
 163                 *rl = alloc_rl(min, max);
 164                 return;
 165         }
 166 
 167         orig = filter_unknown_negatives(orig);
 168         /*
 169          * FIXME:  This is not really accurate but we're a bit screwed anyway
 170          * when we start doing pointer math with error pointers so it's probably
 171          * not important.
 172          *
 173          */
 174         if (sval_is_negative(rl_min(orig)))
 175                 return;
 176 
 177         /* no wrap around */
 178         max.uvalue = rl_max(orig).uvalue;
 179         if (max.uvalue > sval_type_max(&ptr_ctype).uvalue - offset) {
 180                 remove = sval_type_max(&ptr_ctype);
 181                 remove.uvalue -= offset;
 182                 orig = remove_range(orig, remove, max);
 183         }
 184 
 185         sval.type = &int_ctype;
 186         sval.value = offset;
 187 
 188         *rl = rl_binop(orig, '+', alloc_rl(sval, sval));
 189 }
 190 
 191 static struct range_list *where_allocated_rl(struct symbol *sym)
 192 {
 193         if (!sym)
 194                 return NULL;
 195 
 196         if (sym->ctype.modifiers & (MOD_TOPLEVEL | MOD_STATIC)) {
 197                 if (sym->initializer)
 198                         return alloc_rl(data_seg_min, data_seg_max);
 199                 else
 200                         return alloc_rl(bss_seg_min, bss_seg_max);
 201         }
 202         return alloc_rl(stack_seg_min, stack_seg_max);
 203 }
 204 
 205 int get_address_rl(struct expression *expr, struct range_list **rl)
 206 {


 207         expr = strip_expr(expr);
 208         if (!expr)
 209                 return 0;
 210 
 211         if (expr->type == EXPR_STRING) {
 212                 *rl = alloc_rl(text_seg_min, text_seg_max);
 213                 return 1;
 214         }
 215 
 216         if (expr->type == EXPR_PREOP && expr->op == '&') {
 217                 struct expression *unop;


 218 
 219                 unop = strip_expr(expr->unop);
 220                 if (unop->type == EXPR_SYMBOL) {
 221                         *rl = where_allocated_rl(unop->symbol);




 222                         return 1;
 223                 }
 224 
 225                 if (unop->type == EXPR_DEREF) {
 226                         int offset = get_member_offset_from_deref(unop);




 227 
 228                         unop = strip_expr(unop->unop);
 229                         if (unop->type == EXPR_SYMBOL) {
 230                                 *rl = where_allocated_rl(unop->symbol);
 231                         } else if (unop->type == EXPR_PREOP && unop->op == '*') {
 232                                 unop = strip_expr(unop->unop);
 233                                 get_absolute_rl(unop, rl);
 234                         } else {


















 235                                 return 0;
 236                         }
 237 













 238                         add_offset_to_pointer(rl, offset);
 239                         return 1;
 240                 }





 241 
 242                 return 0;
 243         }
 244 
 245         if (is_non_null_array(expr)) {
 246                 *rl = alloc_rl(array_min_sval, array_max_sval);
 247                 return 1;
 248         }
 249 
 250         return 0;
 251 }


  45                 return 0;
  46         type = get_real_base_type(type);
  47         if (type->type != SYM_STRUCT)
  48                 return 0;
  49 
  50         i = 0;
  51         FOR_EACH_PTR(type->symbol_list, tmp) {
  52                 i++;
  53                 if (!tmp->ident)
  54                         continue;
  55                 if (strcmp(expr->member->name, tmp->ident->name) == 0) {
  56                         if (i == 1)
  57                                 return 0;
  58                         return 1;
  59                 }
  60         } END_FOR_EACH_PTR(tmp);
  61 
  62         return 0;
  63 }
  64 
  65 static bool matches_anonymous_union(struct symbol *sym, const char *member_name)
  66 {
  67         struct symbol *type, *tmp;
  68 
  69         if (sym->ident)
  70                 return false;
  71         type = get_real_base_type(sym);
  72         if (!type || type->type != SYM_UNION)
  73                 return false;
  74 
  75         FOR_EACH_PTR(type->symbol_list, tmp) {
  76                 if (tmp->ident &&
  77                     strcmp(member_name, tmp->ident->name) == 0) {
  78                         return true;
  79                 }
  80         } END_FOR_EACH_PTR(tmp);
  81 
  82         return false;
  83 }
  84 
  85 int get_member_offset(struct symbol *type, const char *member_name)
  86 {
  87         struct symbol *tmp;
  88         int offset;
  89         int bits;
  90 
  91         if (!type || type->type != SYM_STRUCT)
  92                 return -1;
  93 
  94         bits = 0;
  95         offset = 0;
  96         FOR_EACH_PTR(type->symbol_list, tmp) {
  97                 if (bits_to_bytes(bits + type_bits(tmp)) > tmp->ctype.alignment) {
  98                         offset += bits_to_bytes(bits);
  99                         bits = 0;
 100                 }
 101                 offset = ALIGN(offset, tmp->ctype.alignment);
 102                 if (tmp->ident &&
 103                     strcmp(member_name, tmp->ident->name) == 0) {
 104                         return offset;
 105                 }
 106                 if (matches_anonymous_union(tmp, member_name))
 107                         return offset;
 108                 if (!(type_bits(tmp) % 8) && type_bits(tmp) / 8 == type_bytes(tmp))
 109                         offset += type_bytes(tmp);
 110                 else
 111                         bits += type_bits(tmp);
 112         } END_FOR_EACH_PTR(tmp);
 113         return -1;
 114 }
 115 
 116 int get_member_offset_from_deref(struct expression *expr)
 117 {
 118         struct symbol *type;
 119         struct ident *member;
 120         int offset;
 121 
 122         if (expr->type != EXPR_DEREF)  /* hopefully, this doesn't happen */
 123                 return -1;
 124 
 125         if (expr->member_offset >= 0)
 126                 return expr->member_offset;
 127 
 128         member = expr->member;
 129         if (!member)
 130                 return -1;
 131 
 132         type = get_type(expr->deref);
 133         if (type_is_ptr(type))
 134                 type = get_real_base_type(type);
 135         if (!type || type->type != SYM_STRUCT)
 136                 return -1;
 137 
 138         offset = get_member_offset(type, member->name);
 139         if (offset >= 0)
 140                 expr->member_offset = offset;
 141         return offset;
 142 }
 143 

















 144 static void add_offset_to_pointer(struct range_list **rl, int offset)
 145 {
 146         sval_t min, max, remove, sval;
 147         struct range_list *orig = *rl;
 148 
 149         /*
 150          * Ha ha.  Treating zero as a special case means I'm correct at least a
 151          * tiny fraction of the time.  Which is better than nothing.
 152          *
 153          */
 154         if (offset == 0)
 155                 return;
 156 
 157         if (is_unknown_ptr(orig))
 158                 return;
 159 
 160         /*
 161          * This function doesn't necessarily work how you might expect...
 162          *
 163          * Say you have s64min-(-1),1-s64max and you add 8 then I guess what
 164          * we want to say is maybe something like 9-s64max.  This shows that the
 165          * min it could be is 9 which is potentially useful information.  But
 166          * if we start with (-12),5000000-57777777 and we add 8 then we'd want
 167          * the result to be (-4),5000008-57777777 but (-4),5000000-57777777 is
 168          * also probably acceptable.  If you start with s64min-s64max then the
 169          * result should be 8-s64max.
 170          *
 171          */
 172 
 173         /* We do the math on void pointer type, because this isn't "&v + 16" it
 174          * is &v->sixteenth_byte.
 175          */
 176         orig = cast_rl(&ptr_ctype, orig);
 177         min = sval_type_min(&ptr_ctype);
 178         min.value = offset;
 179         max = sval_type_max(&ptr_ctype);
 180 
 181         if (!orig || is_whole_rl(orig)) {
 182                 *rl = alloc_rl(min, max);
 183                 return;
 184         }
 185 










 186         /* no wrap around */
 187         max.uvalue = rl_max(orig).uvalue;
 188         if (max.uvalue > sval_type_max(&ptr_ctype).uvalue - offset) {
 189                 remove = sval_type_max(&ptr_ctype);
 190                 remove.uvalue -= offset;
 191                 orig = remove_range(orig, remove, max);
 192         }
 193 
 194         sval.type = &int_ctype;
 195         sval.value = offset;
 196 
 197         *rl = rl_binop(orig, '+', alloc_rl(sval, sval));
 198 }
 199 
 200 static struct range_list *where_allocated_rl(struct symbol *sym)
 201 {
 202         if (!sym)
 203                 return NULL;
 204 
 205         return alloc_rl(valid_ptr_min_sval, valid_ptr_max_sval);






 206 }
 207 
 208 int get_address_rl(struct expression *expr, struct range_list **rl)
 209 {
 210         struct expression *unop;
 211 
 212         expr = strip_expr(expr);
 213         if (!expr)
 214                 return 0;
 215 
 216         if (expr->type == EXPR_STRING) {
 217                 *rl = alloc_rl(valid_ptr_min_sval, valid_ptr_max_sval);
 218                 return 1;
 219         }
 220 
 221         if (expr->type == EXPR_PREOP && expr->op == '&')
 222                 expr = strip_expr(expr->unop);
 223         else {
 224                 struct symbol *type;
 225 
 226                 type = get_type(expr);
 227                 if (!type || type->type != SYM_ARRAY)
 228                         return 0;
 229         }
 230 
 231         if (expr->type == EXPR_SYMBOL) {
 232                 *rl = where_allocated_rl(expr->symbol);
 233                 return 1;
 234         }
 235 
 236         if (is_array(expr)) {
 237                 struct expression *array;
 238                 struct expression *offset_expr;
 239                 struct range_list *array_rl, *offset_rl, *bytes_rl, *res;
 240                 struct symbol *type;
 241                 sval_t bytes;
 242 
 243                 array = get_array_base(expr);
 244                 offset_expr = get_array_offset(expr);
 245 
 246                 type = get_type(array);
 247                 type = get_real_base_type(type);
 248                 bytes.type = ssize_t_ctype;
 249                 bytes.uvalue = type_bytes(type);
 250                 bytes_rl = alloc_rl(bytes, bytes);
 251 
 252                 get_absolute_rl(array, &array_rl);
 253                 get_absolute_rl(offset_expr, &offset_rl);
 254 
 255                 if (type_bytes(type)) {
 256                         res = rl_binop(offset_rl, '*', bytes_rl);
 257                         res = rl_binop(res, '+', array_rl);
 258                         *rl = res;
 259                         return true;
 260                 }
 261 
 262                 if (implied_not_equal(array, 0) ||
 263                     implied_not_equal(offset_expr, 0)) {
 264                         *rl = alloc_rl(valid_ptr_min_sval, valid_ptr_max_sval);
 265                         return 1;
 266                 }
 267 
 268                 return 0;
 269         }
 270 
 271         if (expr->type == EXPR_DEREF && expr->member) {
 272                 struct range_list *unop_rl;
 273                 int offset;
 274 
 275                 offset = get_member_offset_from_deref(expr);
 276                 unop = strip_expr(expr->unop);
 277                 if (unop->type == EXPR_PREOP && unop->op == '*')
 278                         unop = strip_expr(unop->unop);
 279 
 280                 if (offset >= 0 &&
 281                     get_implied_rl(unop, &unop_rl) &&
 282                     !is_whole_rl(unop_rl)) {
 283                         *rl = unop_rl;
 284                         add_offset_to_pointer(rl, offset);
 285                         return 1;
 286                 }
 287 
 288                 if (implied_not_equal(unop, 0) || offset > 0) {
 289                         *rl = alloc_rl(valid_ptr_min_sval, valid_ptr_max_sval);
 290                         return 1;
 291                 }
 292 
 293                 return 0;
 294         }
 295 
 296         if (is_non_null_array(expr)) {
 297                 *rl = alloc_rl(array_min_sval, array_max_sval);
 298                 return 1;
 299         }
 300 
 301         return 0;
 302 }