1 /* 2 * Copyright (C) 2013 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 /* 19 * The plan here is to save all the possible values store to a given struct 20 * member. 21 * 22 * We will load all the values in to the function_type_val table first then 23 * run a script on that and load all the resulting values into the type_val 24 * table. 25 * 26 * So in this file we want to take the union of everything assigned to the 27 * struct member and insert it into the function_type_val at the end. 28 * 29 * You would think that we could use smatch_modification_hooks.c or 30 * extra_modification_hook() here to get the information here but in the end we 31 * need to code everything again a third time. 32 * 33 */ 34 35 #include "smatch.h" 36 #include "smatch_slist.h" 37 #include "smatch_extra.h" 38 39 static int my_id; 40 41 struct stree_stack *fn_type_val_stack; 42 struct stree *fn_type_val; 43 struct stree *global_type_val; 44 45 static int get_vals(void *_db_vals, int argc, char **argv, char **azColName) 46 { 47 char **db_vals = _db_vals; 48 49 *db_vals = alloc_string(argv[0]); 50 return 0; 51 } 52 53 static void match_inline_start(struct expression *expr) 54 { 55 push_stree(&fn_type_val_stack, fn_type_val); 56 fn_type_val = NULL; 57 } 58 59 static void match_inline_end(struct expression *expr) 60 { 61 free_stree(&fn_type_val); 62 fn_type_val = pop_stree(&fn_type_val_stack); 63 } 64 65 struct expr_rl { 66 struct expression *expr; 67 struct range_list *rl; 68 }; 69 static struct expr_rl cached_results[10]; 70 static int res_idx; 71 72 static int get_cached(struct expression *expr, struct range_list **rl, int *ret) 73 { 74 int i; 75 76 *ret = 0; 77 78 for (i = 0; i < ARRAY_SIZE(cached_results); i++) { 79 if (expr == cached_results[i].expr) { 80 if (cached_results[i].rl) { 81 *rl = clone_rl(cached_results[i].rl); 82 *ret = 1; 83 } 84 return 1; 85 } 86 } 87 88 return 0; 89 } 90 91 int get_db_type_rl(struct expression *expr, struct range_list **rl) 92 { 93 char *db_vals = NULL; 94 char *member; 95 struct range_list *tmp; 96 struct symbol *type; 97 int ret; 98 99 if (get_cached(expr, rl, &ret)) 100 return ret; 101 102 member = get_member_name(expr); 103 if (!member) 104 return 0; 105 106 res_idx = (res_idx + 1) % ARRAY_SIZE(cached_results); 107 cached_results[res_idx].expr = expr; 108 cached_results[res_idx].rl = NULL; 109 110 run_sql(get_vals, &db_vals, 111 "select value from type_value where type = '%s';", member); 112 free_string(member); 113 if (!db_vals) 114 return 0; 115 type = get_type(expr); 116 str_to_rl(type, db_vals, &tmp); 117 free_string(db_vals); 118 if (is_whole_rl(tmp)) 119 return 0; 120 121 *rl = tmp; 122 cached_results[res_idx].rl = clone_rl(tmp); 123 124 return 1; 125 } 126 127 static void add_type_val(char *member, struct range_list *rl) 128 { 129 struct smatch_state *old, *add, *new; 130 131 member = alloc_string(member); 132 old = get_state_stree(fn_type_val, my_id, member, NULL); 133 add = alloc_estate_rl(rl); 134 if (old) 135 new = merge_estates(old, add); 136 else 137 new = add; 138 set_state_stree(&fn_type_val, my_id, member, NULL, new); 139 } 140 141 static void add_fake_type_val(char *member, struct range_list *rl, int ignore) 142 { 143 struct smatch_state *old, *add, *new; 144 145 member = alloc_string(member); 146 old = get_state_stree(fn_type_val, my_id, member, NULL); 147 if (old && strcmp(old->name, "min-max") == 0) 148 return; 149 if (ignore && old && strcmp(old->name, "ignore") == 0) 150 return; 151 add = alloc_estate_rl(rl); 152 if (old) { 153 new = merge_estates(old, add); 154 } else { 155 new = add; 156 if (ignore) 157 new->name = alloc_string("ignore"); 158 else 159 new->name = alloc_string("min-max"); 160 } 161 set_state_stree(&fn_type_val, my_id, member, NULL, new); 162 } 163 164 static void add_global_type_val(char *member, struct range_list *rl) 165 { 166 struct smatch_state *old, *add, *new; 167 168 member = alloc_string(member); 169 old = get_state_stree(global_type_val, my_id, member, NULL); 170 add = alloc_estate_rl(rl); 171 if (old) 172 new = merge_estates(old, add); 173 else 174 new = add; 175 new = clone_estate_perm(new); 176 set_state_stree_perm(&global_type_val, my_id, member, NULL, new); 177 } 178 179 static int has_link_cb(void *has_link, int argc, char **argv, char **azColName) 180 { 181 *(int *)has_link = 1; 182 return 0; 183 } 184 185 static int is_ignored_fake_assignment(void) 186 { 187 struct expression *expr; 188 struct symbol *type; 189 char *member_name; 190 int has_link = 0; 191 192 expr = get_faked_expression(); 193 if (!expr || expr->type != EXPR_ASSIGNMENT) 194 return 0; 195 if (!is_void_pointer(expr->right)) 196 return 0; 197 member_name = get_member_name(expr->right); 198 if (!member_name) 199 return 0; 200 201 type = get_type(expr->left); 202 if (!type || type->type != SYM_PTR) 203 return 0; 204 type = get_real_base_type(type); 205 if (!type || type->type != SYM_STRUCT) 206 return 0; 207 208 run_sql(has_link_cb, &has_link, 209 "select * from data_info where type = %d and data = '%s' and value = '%s';", 210 TYPE_LINK, member_name, type_to_str(type)); 211 return has_link; 212 } 213 214 static int is_container_of(void) 215 { 216 /* We already check the macro name in is_ignored_macro() */ 217 struct expression *expr; 218 int offset; 219 220 expr = get_faked_expression(); 221 if (!expr || expr->type != EXPR_ASSIGNMENT) 222 return 0; 223 224 offset = get_offset_from_container_of(expr->right); 225 if (offset < 0) 226 return 0; 227 return 1; 228 } 229 230 static bool is_driver_data(void) 231 { 232 static struct expression *prev_expr; 233 struct expression *expr; 234 char *name; 235 static bool prev_ret; 236 bool ret = false; 237 238 expr = get_faked_expression(); 239 if (!expr || expr->type != EXPR_ASSIGNMENT) 240 return false; 241 242 if (expr == prev_expr) 243 return prev_ret; 244 prev_expr = expr; 245 246 name = expr_to_str(expr->right); 247 if (!name) { 248 prev_ret = false; 249 return false; 250 } 251 252 if (strstr(name, "get_drvdata(") || 253 strstr(name, "dev.driver_data") || 254 strstr(name, "dev->driver_data")) 255 ret = true; 256 257 free_string(name); 258 259 prev_ret = ret; 260 return ret; 261 } 262 263 static int is_ignored_macro(void) 264 { 265 struct expression *expr; 266 char *name; 267 268 expr = get_faked_expression(); 269 if (!expr || expr->type != EXPR_ASSIGNMENT || expr->op != '=') 270 return 0; 271 name = get_macro_name(expr->right->pos); 272 if (!name) 273 return 0; 274 if (strcmp(name, "container_of") == 0) 275 return 1; 276 if (strcmp(name, "rb_entry") == 0) 277 return 1; 278 if (strcmp(name, "list_entry") == 0) 279 return 1; 280 if (strcmp(name, "list_first_entry") == 0) 281 return 1; 282 if (strcmp(name, "hlist_entry") == 0) 283 return 1; 284 if (strcmp(name, "per_cpu_ptr") == 0) 285 return 1; 286 if (strcmp(name, "raw_cpu_ptr") == 0) 287 return 1; 288 if (strcmp(name, "this_cpu_ptr") == 0) 289 return 1; 290 291 if (strcmp(name, "TRACE_EVENT") == 0) 292 return 1; 293 if (strcmp(name, "DECLARE_EVENT_CLASS") == 0) 294 return 1; 295 if (strcmp(name, "DEFINE_EVENT") == 0) 296 return 1; 297 298 if (strstr(name, "for_each")) 299 return 1; 300 return 0; 301 } 302 303 static int is_ignored_function(void) 304 { 305 struct expression *expr; 306 307 expr = get_faked_expression(); 308 if (!expr || expr->type != EXPR_ASSIGNMENT) 309 return 0; 310 expr = strip_expr(expr->right); 311 if (!expr || expr->type != EXPR_CALL || expr->fn->type != EXPR_SYMBOL) 312 return 0; 313 314 if (sym_name_is("kmalloc", expr->fn)) 315 return 1; 316 if (sym_name_is("vmalloc", expr->fn)) 317 return 1; 318 if (sym_name_is("kvmalloc", expr->fn)) 319 return 1; 320 if (sym_name_is("kmalloc_array", expr->fn)) 321 return 1; 322 if (sym_name_is("vmalloc_array", expr->fn)) 323 return 1; 324 if (sym_name_is("kvmalloc_array", expr->fn)) 325 return 1; 326 327 if (sym_name_is("mmu_memory_cache_alloc", expr->fn)) 328 return 1; 329 if (sym_name_is("kmem_alloc", expr->fn)) 330 return 1; 331 if (sym_name_is("alloc_pages", expr->fn)) 332 return 1; 333 334 if (sym_name_is("netdev_priv", expr->fn)) 335 return 1; 336 if (sym_name_is("dev_get_drvdata", expr->fn)) 337 return 1; 338 if (sym_name_is("i2c_get_clientdata", expr->fn)) 339 return 1; 340 341 return 0; 342 } 343 344 static int is_uncasted_pointer_assign(void) 345 { 346 struct expression *expr; 347 struct symbol *left_type, *right_type; 348 349 expr = get_faked_expression(); 350 if (!expr) 351 return 0; 352 if (expr->type == EXPR_PREOP || expr->type == EXPR_POSTOP) { 353 if (expr->op == SPECIAL_INCREMENT || expr->op == SPECIAL_DECREMENT) 354 return 1; 355 } 356 if (expr->type != EXPR_ASSIGNMENT) 357 return 0; 358 left_type = get_type(expr->left); 359 right_type = get_type(expr->right); 360 361 if (!left_type || !right_type) 362 return 0; 363 364 if (left_type->type == SYM_STRUCT && left_type == right_type) 365 return 1; 366 367 if (left_type->type != SYM_PTR && 368 left_type->type != SYM_ARRAY) 369 return 0; 370 if (right_type->type != SYM_PTR && 371 right_type->type != SYM_ARRAY) 372 return 0; 373 left_type = get_real_base_type(left_type); 374 right_type = get_real_base_type(right_type); 375 376 if (left_type == right_type) 377 return 1; 378 return 0; 379 } 380 381 static int set_param_type(void *_type_str, int argc, char **argv, char **azColName) 382 { 383 char **type_str = _type_str; 384 static char type_buf[128]; 385 386 if (*type_str) { 387 if (strcmp(*type_str, argv[0]) == 0) 388 return 0; 389 strncpy(type_buf, "unknown", sizeof(type_buf)); 390 return 0; 391 } 392 strncpy(type_buf, argv[0], sizeof(type_buf)); 393 *type_str = type_buf; 394 395 return 0; 396 } 397 398 static char *db_get_parameter_type(int param) 399 { 400 char *ret = NULL; 401 402 if (!cur_func_sym) 403 return NULL; 404 405 run_sql(set_param_type, &ret, 406 "select value from fn_data_link where " 407 "file = '%s' and function = '%s' and static = %d and type = %d and parameter = %d and key = '$';", 408 (cur_func_sym->ctype.modifiers & MOD_STATIC) ? get_base_file() : "extern", 409 cur_func_sym->ident->name, 410 !!(cur_func_sym->ctype.modifiers & MOD_STATIC), 411 PASSES_TYPE, param); 412 413 return ret; 414 } 415 416 static int is_uncasted_fn_param_from_db(void) 417 { 418 struct expression *expr, *right; 419 struct symbol *left_type; 420 char left_type_name[128]; 421 int param; 422 char *right_type_name; 423 static struct expression *prev_expr; 424 static int prev_ans; 425 426 expr = get_faked_expression(); 427 428 if (expr == prev_expr) 429 return prev_ans; 430 prev_expr = expr; 431 prev_ans = 0; 432 433 if (!expr || expr->type != EXPR_ASSIGNMENT) 434 return 0; 435 left_type = get_type(expr->left); 436 if (!left_type || left_type->type != SYM_PTR) 437 return 0; 438 left_type = get_real_base_type(left_type); 439 if (!left_type || left_type->type != SYM_STRUCT) 440 return 0; 441 snprintf(left_type_name, sizeof(left_type_name), "%s", type_to_str(left_type)); 442 443 right = strip_expr(expr->right); 444 param = get_param_num(right); 445 if (param < 0) 446 return 0; 447 right_type_name = db_get_parameter_type(param); 448 if (!right_type_name) 449 return 0; 450 451 if (strcmp(right_type_name, left_type_name) == 0) { 452 prev_ans = 1; 453 return 1; 454 } 455 456 return 0; 457 } 458 459 static void match_assign_value(struct expression *expr) 460 { 461 char *member, *right_member; 462 struct range_list *rl; 463 struct symbol *type; 464 465 if (!cur_func_sym) 466 return; 467 468 type = get_type(expr->left); 469 if (type && type->type == SYM_STRUCT) 470 return; 471 member = get_member_name(expr->left); 472 if (!member) 473 return; 474 475 /* if we're saying foo->mtu = bar->mtu then that doesn't add information */ 476 right_member = get_member_name(expr->right); 477 if (right_member && strcmp(right_member, member) == 0) 478 goto free; 479 480 if (is_fake_call(expr->right)) { 481 if (is_ignored_macro()) 482 goto free; 483 if (is_ignored_function()) 484 goto free; 485 if (is_uncasted_pointer_assign()) 486 goto free; 487 if (is_uncasted_fn_param_from_db()) 488 goto free; 489 if (is_container_of()) 490 goto free; 491 if (is_driver_data()) 492 goto free; 493 add_fake_type_val(member, alloc_whole_rl(get_type(expr->left)), is_ignored_fake_assignment()); 494 goto free; 495 } 496 497 if (expr->op == '=') { 498 get_absolute_rl(expr->right, &rl); 499 rl = cast_rl(type, rl); 500 } else { 501 /* 502 * This is a bit cheating. We order it so this will already be set 503 * by smatch_extra.c and we just look up the value. 504 */ 505 get_absolute_rl(expr->left, &rl); 506 } 507 add_type_val(member, rl); 508 free: 509 free_string(right_member); 510 free_string(member); 511 } 512 513 /* 514 * If we too: int *p = &my_struct->member then abandon all hope of tracking 515 * my_struct->member. 516 */ 517 static void match_assign_pointer(struct expression *expr) 518 { 519 struct expression *right; 520 char *member; 521 struct range_list *rl; 522 struct symbol *type; 523 524 right = strip_expr(expr->right); 525 if (right->type != EXPR_PREOP || right->op != '&') 526 return; 527 right = strip_expr(right->unop); 528 529 member = get_member_name(right); 530 if (!member) 531 return; 532 type = get_type(right); 533 rl = alloc_whole_rl(type); 534 add_type_val(member, rl); 535 free_string(member); 536 } 537 538 static void match_global_assign(struct expression *expr) 539 { 540 char *member; 541 struct range_list *rl; 542 struct symbol *type; 543 544 type = get_type(expr->left); 545 if (type && (type->type == SYM_ARRAY || type->type == SYM_STRUCT)) 546 return; 547 member = get_member_name(expr->left); 548 if (!member) 549 return; 550 get_absolute_rl(expr->right, &rl); 551 rl = cast_rl(type, rl); 552 add_global_type_val(member, rl); 553 free_string(member); 554 } 555 556 static void unop_expr(struct expression *expr) 557 { 558 struct range_list *rl; 559 char *member; 560 561 if (expr->op != SPECIAL_DECREMENT && expr->op != SPECIAL_INCREMENT) 562 return; 563 564 expr = strip_expr(expr->unop); 565 member = get_member_name(expr); 566 if (!member) 567 return; 568 rl = alloc_whole_rl(get_type(expr)); 569 add_type_val(member, rl); 570 free_string(member); 571 } 572 573 static void asm_expr(struct statement *stmt) 574 { 575 struct expression *expr; 576 struct range_list *rl; 577 char *member; 578 579 FOR_EACH_PTR(stmt->asm_outputs, expr) { 580 member = get_member_name(expr->expr); 581 if (!member) 582 continue; 583 rl = alloc_whole_rl(get_type(expr->expr)); 584 add_type_val(member, rl); 585 free_string(member); 586 } END_FOR_EACH_PTR(expr); 587 } 588 589 static void db_param_add(struct expression *expr, int param, char *key, char *value) 590 { 591 struct expression *arg; 592 struct symbol *type; 593 struct range_list *rl; 594 char *member; 595 596 if (strcmp(key, "*$") != 0) 597 return; 598 599 while (expr->type == EXPR_ASSIGNMENT) 600 expr = strip_expr(expr->right); 601 if (expr->type != EXPR_CALL) 602 return; 603 604 arg = get_argument_from_call_expr(expr->args, param); 605 arg = strip_expr(arg); 606 if (!arg) 607 return; 608 type = get_member_type_from_key(arg, key); 609 /* 610 * The situation here is that say we memset() a void pointer to zero 611 * then that's returned to the called as "*$ = 0;" but on the caller's 612 * side it's not void, it's a struct. 613 * 614 * So the question is should we be passing that slightly bogus 615 * information back to the caller? Maybe, maybe not, but either way we 616 * are not going to record it here because a struct can't be zero. 617 * 618 */ 619 if (type && type->type == SYM_STRUCT) 620 return; 621 622 if (arg->type != EXPR_PREOP || arg->op != '&') 623 return; 624 arg = strip_expr(arg->unop); 625 626 member = get_member_name(arg); 627 if (!member) 628 return; 629 call_results_to_rl(expr, type, value, &rl); 630 add_type_val(member, rl); 631 free_string(member); 632 } 633 634 static void match_end_func_info(struct symbol *sym) 635 { 636 struct sm_state *sm; 637 638 FOR_EACH_SM(fn_type_val, sm) { 639 sql_insert_function_type_value(sm->name, sm->state->name); 640 } END_FOR_EACH_SM(sm); 641 } 642 643 static void clear_cache(struct symbol *sym) 644 { 645 memset(cached_results, 0, sizeof(cached_results)); 646 } 647 648 static void match_after_func(struct symbol *sym) 649 { 650 free_stree(&fn_type_val); 651 } 652 653 static void match_end_file(struct symbol_list *sym_list) 654 { 655 struct sm_state *sm; 656 657 FOR_EACH_SM(global_type_val, sm) { 658 sql_insert_function_type_value(sm->name, sm->state->name); 659 } END_FOR_EACH_SM(sm); 660 } 661 662 void register_type_val(int id) 663 { 664 my_id = id; 665 add_hook(&clear_cache, AFTER_FUNC_HOOK); 666 667 if (!option_info) 668 return; 669 670 add_hook(&match_assign_value, ASSIGNMENT_HOOK_AFTER); 671 add_hook(&match_assign_pointer, ASSIGNMENT_HOOK); 672 add_hook(&unop_expr, OP_HOOK); 673 add_hook(&asm_expr, ASM_HOOK); 674 select_return_states_hook(PARAM_ADD, &db_param_add); 675 select_return_states_hook(PARAM_SET, &db_param_add); 676 677 678 add_hook(&match_inline_start, INLINE_FN_START); 679 add_hook(&match_inline_end, INLINE_FN_END); 680 681 add_hook(&match_end_func_info, END_FUNC_HOOK); 682 add_hook(&match_after_func, AFTER_FUNC_HOOK); 683 684 add_hook(&match_global_assign, GLOBAL_ASSIGNMENT_HOOK); 685 add_hook(&match_end_file, END_FILE_HOOK); 686 }