1 /* 2 * Copyright (C) 2012 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 point here is to store that a buffer has x bytes even if we don't know 20 * the value of x. 21 * 22 */ 23 24 #include "smatch.h" 25 #include "smatch_extra.h" 26 #include "smatch_slist.h" 27 28 static int size_id; 29 static int link_id; 30 31 /* 32 * We need this for code which does: 33 * 34 * if (size) 35 * foo = malloc(size); 36 * 37 * We want to record that the size of "foo" is "size" even after the merge. 38 * 39 */ 40 static struct smatch_state *unmatched_state(struct sm_state *sm) 41 { 42 struct expression *size_expr; 43 sval_t sval; 44 45 if (!sm->state->data) 46 return &undefined; 47 size_expr = sm->state->data; 48 if (!get_implied_value(size_expr, &sval) || sval.value != 0) 49 return &undefined; 50 return sm->state; 51 } 52 53 static struct smatch_state *merge_links(struct smatch_state *s1, struct smatch_state *s2) 54 { 55 struct expression *expr1, *expr2; 56 57 expr1 = s1->data; 58 expr2 = s2->data; 59 60 if (expr1 && expr2 && expr_equiv(expr1, expr2)) 61 return s1; 62 return &merged; 63 } 64 65 static void match_link_modify(struct sm_state *sm, struct expression *mod_expr) 66 { 67 struct expression *expr; 68 struct sm_state *tmp; 69 70 expr = sm->state->data; 71 if (expr) { 72 set_state_expr(size_id, expr, &undefined); 73 set_state(link_id, sm->name, sm->sym, &undefined); 74 return; 75 } 76 77 FOR_EACH_PTR(sm->possible, tmp) { 78 expr = tmp->state->data; 79 if (expr) 80 set_state_expr(size_id, expr, &undefined); 81 } END_FOR_EACH_PTR(tmp); 82 set_state(link_id, sm->name, sm->sym, &undefined); 83 } 84 85 static struct smatch_state *alloc_expr_state(struct expression *expr) 86 { 87 struct smatch_state *state; 88 char *name; 89 90 state = __alloc_smatch_state(0); 91 expr = strip_expr(expr); 92 name = expr_to_str(expr); 93 state->name = alloc_sname(name); 94 free_string(name); 95 state->data = expr; 96 return state; 97 } 98 99 static int bytes_per_element(struct expression *expr) 100 { 101 struct symbol *type; 102 103 type = get_type(expr); 104 if (!type) 105 return 0; 106 107 if (type->type != SYM_PTR && type->type != SYM_ARRAY) 108 return 0; 109 110 type = get_base_type(type); 111 return type_bytes(type); 112 } 113 114 static void db_save_type_links(struct expression *array, struct expression *size) 115 { 116 const char *array_name; 117 118 array_name = get_data_info_name(array); 119 if (!array_name) 120 array_name = ""; 121 sql_insert_data_info(size, ARRAY_LEN, array_name); 122 } 123 124 static void match_alloc_helper(struct expression *pointer, struct expression *size) 125 { 126 struct expression *tmp; 127 struct sm_state *sm; 128 sval_t sval; 129 int cnt = 0; 130 131 pointer = strip_expr(pointer); 132 size = strip_expr(size); 133 if (!size || !pointer) 134 return; 135 136 while ((tmp = get_assigned_expr(size))) { 137 size = strip_expr(tmp); 138 if (cnt++ > 5) 139 break; 140 } 141 142 if (size->type == EXPR_BINOP && size->op == '*') { 143 struct expression *mult_left, *mult_right; 144 145 mult_left = strip_expr(size->left); 146 mult_right = strip_expr(size->right); 147 148 if (get_implied_value(mult_left, &sval) && 149 sval.value == bytes_per_element(pointer)) 150 size = mult_right; 151 else if (get_implied_value(mult_right, &sval) && 152 sval.value == bytes_per_element(pointer)) 153 size = mult_left; 154 else 155 return; 156 } 157 158 /* Only save links to variables, not fixed sizes */ 159 if (get_value(size, &sval)) 160 return; 161 162 db_save_type_links(pointer, size); 163 sm = set_state_expr(size_id, pointer, alloc_expr_state(size)); 164 if (!sm) 165 return; 166 set_state_expr(link_id, size, alloc_expr_state(pointer)); 167 } 168 169 static void match_alloc(const char *fn, struct expression *expr, void *_size_arg) 170 { 171 int size_arg = PTR_INT(_size_arg); 172 struct expression *pointer, *call, *arg; 173 174 pointer = strip_expr(expr->left); 175 call = strip_expr(expr->right); 176 arg = get_argument_from_call_expr(call->args, size_arg); 177 match_alloc_helper(pointer, arg); 178 } 179 180 static void match_calloc(const char *fn, struct expression *expr, void *_start_arg) 181 { 182 int start_arg = PTR_INT(_start_arg); 183 struct expression *pointer, *call, *arg; 184 struct sm_state *tmp; 185 sval_t sval; 186 187 pointer = strip_expr(expr->left); 188 call = strip_expr(expr->right); 189 arg = get_argument_from_call_expr(call->args, start_arg); 190 if (get_implied_value(arg, &sval) && 191 sval.value == bytes_per_element(pointer)) 192 arg = get_argument_from_call_expr(call->args, start_arg + 1); 193 194 db_save_type_links(pointer, arg); 195 tmp = set_state_expr(size_id, pointer, alloc_expr_state(arg)); 196 if (!tmp) 197 return; 198 set_state_expr(link_id, arg, alloc_expr_state(pointer)); 199 } 200 201 struct expression *get_size_variable(struct expression *buf) 202 { 203 struct smatch_state *state; 204 205 state = get_state_expr(size_id, buf); 206 if (state) 207 return state->data; 208 return NULL; 209 } 210 211 struct expression *get_array_variable(struct expression *size) 212 { 213 struct smatch_state *state; 214 215 state = get_state_expr(link_id, size); 216 if (state) 217 return state->data; 218 return NULL; 219 } 220 221 static void array_check(struct expression *expr) 222 { 223 struct expression *array; 224 struct expression *size; 225 struct expression *offset; 226 char *array_str, *offset_str; 227 228 expr = strip_expr(expr); 229 if (!is_array(expr)) 230 return; 231 232 array = get_array_base(expr); 233 size = get_size_variable(array); 234 if (!size) 235 return; 236 offset = get_array_offset(expr); 237 if (!possible_comparison(size, SPECIAL_EQUAL, offset)) 238 return; 239 240 array_str = expr_to_str(array); 241 offset_str = expr_to_str(offset); 242 sm_warning("potentially one past the end of array '%s[%s]'", array_str, offset_str); 243 free_string(array_str); 244 free_string(offset_str); 245 } 246 247 struct db_info { 248 char *name; 249 int ret; 250 }; 251 252 static int db_limitter_callback(void *_info, int argc, char **argv, char **azColName) 253 { 254 struct db_info *info = _info; 255 256 /* 257 * If possible the limitters are tied to the struct they limit. If we 258 * aren't sure which struct they limit then we use them as limitters for 259 * everything. 260 */ 261 if (!info->name || argv[0][0] == '\0' || strcmp(info->name, argv[0]) == 0) 262 info->ret = 1; 263 return 0; 264 } 265 266 static char *vsl_to_data_info_name(const char *name, struct var_sym_list *vsl) 267 { 268 struct var_sym *vs; 269 struct symbol *type; 270 static char buf[80]; 271 const char *p; 272 273 if (ptr_list_size((struct ptr_list *)vsl) != 1) 274 return NULL; 275 vs = first_ptr_list((struct ptr_list *)vsl); 276 277 type = get_real_base_type(vs->sym); 278 if (!type || type->type != SYM_PTR) 279 goto top_level_name; 280 type = get_real_base_type(type); 281 if (!type || type->type != SYM_STRUCT) 282 goto top_level_name; 283 if (!type->ident) 284 goto top_level_name; 285 286 p = name; 287 while ((name = strstr(p, "->"))) 288 p = name + 2; 289 290 snprintf(buf, sizeof(buf),"(struct %s)->%s", type->ident->name, p); 291 return alloc_sname(buf); 292 293 top_level_name: 294 if (!(vs->sym->ctype.modifiers & MOD_TOPLEVEL)) 295 return NULL; 296 if (vs->sym->ctype.modifiers & MOD_STATIC) 297 snprintf(buf, sizeof(buf),"static %s", name); 298 else 299 snprintf(buf, sizeof(buf),"global %s", name); 300 return alloc_sname(buf); 301 } 302 303 int db_var_is_array_limit(struct expression *array, const char *name, struct var_sym_list *vsl) 304 { 305 char *size_name; 306 char *array_name = get_data_info_name(array); 307 struct db_info db_info = {.name = array_name,}; 308 309 size_name = vsl_to_data_info_name(name, vsl); 310 if (!size_name) 311 return 0; 312 313 run_sql(db_limitter_callback, &db_info, 314 "select value from data_info where type = %d and data = '%s';", 315 ARRAY_LEN, size_name); 316 317 return db_info.ret; 318 } 319 320 static int known_access_ok_comparison(struct expression *expr) 321 { 322 struct expression *array; 323 struct expression *size; 324 struct expression *offset; 325 int comparison; 326 327 array = get_array_base(expr); 328 size = get_size_variable(array); 329 if (!size) 330 return 0; 331 offset = get_array_offset(expr); 332 comparison = get_comparison(size, offset); 333 if (comparison == '>' || comparison == SPECIAL_UNSIGNED_GT) 334 return 1; 335 336 return 0; 337 } 338 339 static int known_access_ok_numbers(struct expression *expr) 340 { 341 struct expression *array; 342 struct expression *offset; 343 sval_t max; 344 int size; 345 346 array = get_array_base(expr); 347 offset = get_array_offset(expr); 348 349 size = get_array_size(array); 350 if (size <= 0) 351 return 0; 352 353 get_absolute_max(offset, &max); 354 if (max.uvalue < size) 355 return 1; 356 return 0; 357 } 358 359 static void array_check_data_info(struct expression *expr) 360 { 361 struct expression *array; 362 struct expression *offset; 363 struct state_list *slist; 364 struct sm_state *sm; 365 struct compare_data *comp; 366 char *offset_name; 367 const char *equal_name = NULL; 368 369 expr = strip_expr(expr); 370 if (!is_array(expr)) 371 return; 372 373 if (known_access_ok_numbers(expr)) 374 return; 375 if (known_access_ok_comparison(expr)) 376 return; 377 378 array = get_array_base(expr); 379 offset = get_array_offset(expr); 380 offset_name = expr_to_var(offset); 381 if (!offset_name) 382 return; 383 slist = get_all_possible_equal_comparisons(offset); 384 if (!slist) 385 goto free; 386 387 FOR_EACH_PTR(slist, sm) { 388 comp = sm->state->data; 389 if (strcmp(comp->left_var, offset_name) == 0) { 390 if (db_var_is_array_limit(array, comp->right_var, comp->right_vsl)) { 391 equal_name = comp->right_var; 392 break; 393 } 394 } else if (strcmp(comp->right_var, offset_name) == 0) { 395 if (db_var_is_array_limit(array, comp->left_var, comp->left_vsl)) { 396 equal_name = comp->left_var; 397 break; 398 } 399 } 400 } END_FOR_EACH_PTR(sm); 401 402 if (equal_name) { 403 char *array_name = expr_to_str(array); 404 405 sm_warning("potential off by one '%s[]' limit '%s'", array_name, equal_name); 406 free_string(array_name); 407 } 408 409 free: 410 free_slist(&slist); 411 free_string(offset_name); 412 } 413 414 static void add_allocation_function(const char *func, void *call_back, int param) 415 { 416 add_function_assign_hook(func, call_back, INT_PTR(param)); 417 } 418 419 static char *buf_size_param_comparison(struct expression *array, struct expression_list *args) 420 { 421 struct expression *arg; 422 struct expression *size; 423 static char buf[32]; 424 int i; 425 426 size = get_size_variable(array); 427 if (!size) 428 return NULL; 429 430 i = -1; 431 FOR_EACH_PTR(args, arg) { 432 i++; 433 if (arg == array) 434 continue; 435 if (!expr_equiv(arg, size)) 436 continue; 437 snprintf(buf, sizeof(buf), "==$%d", i); 438 return buf; 439 } END_FOR_EACH_PTR(arg); 440 441 return NULL; 442 } 443 444 static void match_call(struct expression *call) 445 { 446 struct expression *arg; 447 char *compare; 448 int param; 449 450 param = -1; 451 FOR_EACH_PTR(call->args, arg) { 452 param++; 453 if (!is_pointer(arg)) 454 continue; 455 compare = buf_size_param_comparison(arg, call->args); 456 if (!compare) 457 continue; 458 sql_insert_caller_info(call, ARRAY_LEN, param, "$", compare); 459 } END_FOR_EACH_PTR(arg); 460 } 461 462 static int get_param(int param, char **name, struct symbol **sym) 463 { 464 struct symbol *arg; 465 int i; 466 467 i = 0; 468 FOR_EACH_PTR(cur_func_sym->ctype.base_type->arguments, arg) { 469 /* 470 * this is a temporary hack to work around a bug (I think in sparse?) 471 * 2.6.37-rc1:fs/reiserfs/journal.o 472 * If there is a function definition without parameter name found 473 * after a function implementation then it causes a crash. 474 * int foo() {} 475 * int bar(char *); 476 */ 477 if (arg->ident->name < (char *)100) 478 continue; 479 if (i == param) { 480 *name = arg->ident->name; 481 *sym = arg; 482 return TRUE; 483 } 484 i++; 485 } END_FOR_EACH_PTR(arg); 486 487 return FALSE; 488 } 489 490 static void set_param_compare(const char *array_name, struct symbol *array_sym, char *key, char *value) 491 { 492 struct expression *array_expr; 493 struct expression *size_expr; 494 struct symbol *size_sym; 495 char *size_name; 496 long param; 497 struct sm_state *tmp; 498 499 if (strncmp(value, "==$", 3) != 0) 500 return; 501 param = strtol(value + 3, NULL, 10); 502 if (!get_param(param, &size_name, &size_sym)) 503 return; 504 array_expr = symbol_expression(array_sym); 505 size_expr = symbol_expression(size_sym); 506 507 tmp = set_state_expr(size_id, array_expr, alloc_expr_state(size_expr)); 508 if (!tmp) 509 return; 510 set_state_expr(link_id, size_expr, alloc_expr_state(array_expr)); 511 } 512 513 static void set_arraysize_arg(const char *array_name, struct symbol *array_sym, char *key, char *value) 514 { 515 struct expression *array_expr; 516 struct expression *size_expr; 517 struct symbol *size_sym; 518 char *size_name; 519 long param; 520 struct sm_state *tmp; 521 522 param = strtol(key, NULL, 10); 523 if (!get_param(param, &size_name, &size_sym)) 524 return; 525 array_expr = symbol_expression(array_sym); 526 size_expr = symbol_expression(size_sym); 527 528 tmp = set_state_expr(size_id, array_expr, alloc_expr_state(size_expr)); 529 if (!tmp) 530 return; 531 set_state_expr(link_id, size_expr, alloc_expr_state(array_expr)); 532 } 533 534 static void munge_start_states(struct statement *stmt) 535 { 536 struct state_list *slist = NULL; 537 struct sm_state *sm; 538 struct sm_state *poss; 539 540 FOR_EACH_MY_SM(size_id, __get_cur_stree(), sm) { 541 if (sm->state != &merged) 542 continue; 543 /* 544 * screw it. let's just assume that if one caller passes the 545 * size then they all do. 546 */ 547 FOR_EACH_PTR(sm->possible, poss) { 548 if (poss->state != &merged && 549 poss->state != &undefined) { 550 add_ptr_list(&slist, poss); 551 break; 552 } 553 } END_FOR_EACH_PTR(poss); 554 } END_FOR_EACH_SM(sm); 555 556 FOR_EACH_PTR(slist, sm) { 557 set_state(size_id, sm->name, sm->sym, sm->state); 558 } END_FOR_EACH_PTR(sm); 559 560 free_slist(&slist); 561 } 562 563 void register_buf_comparison(int id) 564 { 565 size_id = id; 566 567 add_unmatched_state_hook(size_id, &unmatched_state); 568 569 add_allocation_function("malloc", &match_alloc, 0); 570 add_allocation_function("memdup", &match_alloc, 1); 571 add_allocation_function("realloc", &match_alloc, 1); 572 if (option_project == PROJ_KERNEL) { 573 add_allocation_function("kmalloc", &match_alloc, 0); 574 add_allocation_function("kzalloc", &match_alloc, 0); 575 add_allocation_function("vmalloc", &match_alloc, 0); 576 add_allocation_function("__vmalloc", &match_alloc, 0); 577 add_allocation_function("sock_kmalloc", &match_alloc, 1); 578 add_allocation_function("kmemdup", &match_alloc, 1); 579 add_allocation_function("kmemdup_user", &match_alloc, 1); 580 add_allocation_function("dma_alloc_attrs", &match_alloc, 1); 581 add_allocation_function("pci_alloc_consistent", &match_alloc, 1); 582 add_allocation_function("pci_alloc_coherent", &match_alloc, 1); 583 add_allocation_function("devm_kmalloc", &match_alloc, 1); 584 add_allocation_function("devm_kzalloc", &match_alloc, 1); 585 add_allocation_function("kcalloc", &match_calloc, 0); 586 add_allocation_function("devm_kcalloc", &match_calloc, 1); 587 add_allocation_function("kmalloc_array", &match_calloc, 0); 588 add_allocation_function("krealloc", &match_alloc, 1); 589 } 590 591 add_hook(&array_check, OP_HOOK); 592 add_hook(&array_check_data_info, OP_HOOK); 593 594 add_hook(&match_call, FUNCTION_CALL_HOOK); 595 select_caller_info_hook(set_param_compare, ARRAY_LEN); 596 select_caller_info_hook(set_arraysize_arg, ARRAYSIZE_ARG); 597 add_hook(&munge_start_states, AFTER_DEF_HOOK); 598 } 599 600 void register_buf_comparison_links(int id) 601 { 602 link_id = id; 603 add_merge_hook(link_id, &merge_links); 604 add_modification_hook(link_id, &match_link_modify); 605 }