Print this page
smatch: check libld_* allocation functions


   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 #include "smatch.h"
  19 #include "smatch_extra.h"
  20 
  21 static int my_id;
  22 
  23 struct allocator {
  24         const char *func;
  25         int param;
  26         int param2;
  27 };
  28 





  29 static struct allocator generic_allocator_table[] = {
  30         {"malloc", 0},
  31         {"memdup", 1},
  32         {"realloc", 1},
  33 };
  34 
  35 static struct allocator kernel_allocator_table[] = {
  36         {"kmalloc", 0},
  37         {"kzalloc", 0},
  38         {"vmalloc", 0},
  39         {"__vmalloc", 0},
  40         {"vzalloc", 0},
  41         {"sock_kmalloc", 1},
  42         {"kmemdup", 1},
  43         {"kmemdup_user", 1},
  44         {"dma_alloc_attrs", 1},
  45         {"pci_alloc_consistent", 1},
  46         {"pci_alloc_coherent", 1},
  47         {"devm_kmalloc", 1},
  48         {"devm_kzalloc", 1},
  49         {"krealloc", 1},
  50 };
  51 
  52 static struct allocator calloc_table[] = {

  53         {"calloc", 0, 1},
  54         {"kcalloc", 0, 1},
  55         {"kmalloc_array", 0, 1},
  56         {"devm_kcalloc", 1, 2},
  57 };
  58 










  59 static int bytes_per_element(struct expression *expr)
  60 {
  61         struct symbol *type;
  62 
  63         type = get_type(expr);
  64         if (!type)
  65                 return 0;
  66 
  67         if (type->type != SYM_PTR && type->type != SYM_ARRAY)
  68                 return 0;
  69 
  70         type = get_base_type(type);
  71         return type_bytes(type);
  72 }
  73 
  74 static void save_constraint_required(struct expression *pointer, int op, struct expression *constraint)
  75 {
  76         char *data, *limit;
  77 
  78         data = get_constraint_str(pointer);


 307         if (!tmp)
 308                 return;
 309 
 310         right = strip_expr(tmp);
 311         if (right->type != EXPR_CALL)
 312                 return;
 313 
 314         if (right->fn->type != EXPR_SYMBOL ||
 315             !right->fn->symbol ||
 316             !right->fn->symbol->ident)
 317                 return;
 318 
 319         for (i = 0; i < ARRAY_SIZE(generic_allocator_table); i++) {
 320                 if (strcmp(right->fn->symbol->ident->name,
 321                            generic_allocator_table[i].func) == 0) {
 322                         size_arg = generic_allocator_table[i].param;
 323                         goto found;
 324                 }
 325         }
 326 


























 327         if (option_project != PROJ_KERNEL)
 328                 return;
 329 
 330         for (i = 0; i < ARRAY_SIZE(kernel_allocator_table); i++) {
 331                 if (strcmp(right->fn->symbol->ident->name,
 332                            kernel_allocator_table[i].func) == 0) {
 333                         size_arg = kernel_allocator_table[i].param;
 334                         goto found;
 335                 }
 336         }
 337 
 338         for (i = 0; i < ARRAY_SIZE(calloc_table); i++) {
 339                 if (strcmp(right->fn->symbol->ident->name,
 340                            calloc_table[i].func) == 0) {
 341                         size_arg = calloc_table[i].param;
 342                         size_arg2 = calloc_table[i].param2;
 343                         goto found;
 344                 }
 345         }
 346 
 347         return;
 348 
 349 found:
 350         arg = get_argument_from_call_expr(right->args, size_arg);
 351         match_alloc_helper(expr->left, arg, 1);
 352         if (size_arg2 == -1)
 353                 return;
 354         arg = get_argument_from_call_expr(right->args, size_arg2);
 355         match_alloc_helper(expr->left, arg, 1);
 356 }
 357 
 358 static void match_assign_ARRAY_SIZE(struct expression *expr)
 359 {
 360         struct expression *array;
 361         char *data, *limit;
 362         const char *macro;


 450         free_string(right);
 451         free_string(left);
 452 }
 453 
 454 void register_constraints_required(int id)
 455 {
 456         my_id = id;
 457 
 458         add_hook(&match_assign_size, ASSIGNMENT_HOOK);
 459         add_hook(&match_assign_data, ASSIGNMENT_HOOK);
 460         add_hook(&match_assign_has_buf_comparison, ASSIGNMENT_HOOK);
 461 
 462         add_hook(&match_assign_ARRAY_SIZE, ASSIGNMENT_HOOK);
 463         add_hook(&match_assign_ARRAY_SIZE, GLOBAL_ASSIGNMENT_HOOK);
 464         add_hook(&match_assign_buf_comparison, ASSIGNMENT_HOOK);
 465         add_hook(&match_assign_constraint, ASSIGNMENT_HOOK);
 466 
 467         add_allocation_function("malloc", &match_alloc, 0);
 468         add_allocation_function("memdup", &match_alloc, 1);
 469         add_allocation_function("realloc", &match_alloc, 1);
 470         add_allocation_function("realloc", &match_calloc, 0);





 471         if (option_project == PROJ_KERNEL) {
 472                 add_allocation_function("kmalloc", &match_alloc, 0);
 473                 add_allocation_function("kzalloc", &match_alloc, 0);
 474                 add_allocation_function("vmalloc", &match_alloc, 0);
 475                 add_allocation_function("__vmalloc", &match_alloc, 0);
 476                 add_allocation_function("vzalloc", &match_alloc, 0);
 477                 add_allocation_function("sock_kmalloc", &match_alloc, 1);
 478                 add_allocation_function("kmemdup", &match_alloc, 1);
 479                 add_allocation_function("kmemdup_user", &match_alloc, 1);
 480                 add_allocation_function("dma_alloc_attrs", &match_alloc, 1);
 481                 add_allocation_function("pci_alloc_consistent", &match_alloc, 1);
 482                 add_allocation_function("pci_alloc_coherent", &match_alloc, 1);
 483                 add_allocation_function("devm_kmalloc", &match_alloc, 1);
 484                 add_allocation_function("devm_kzalloc", &match_alloc, 1);
 485                 add_allocation_function("kcalloc", &match_calloc, 0);
 486                 add_allocation_function("kmalloc_array", &match_calloc, 0);
 487                 add_allocation_function("devm_kcalloc", &match_calloc, 1);
 488                 add_allocation_function("krealloc", &match_alloc, 1);
 489         }
 490 }


   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 #include "smatch.h"
  19 #include "smatch_extra.h"
  20 
  21 static int my_id;
  22 
  23 struct allocator {
  24         const char *func;
  25         int param;
  26         int param2;
  27 };
  28 
  29 static struct allocator illumos_user_allocator_table[] = {
  30         {"libld_malloc", 0},
  31         {"libld_realloc", 1},
  32 };
  33 
  34 static struct allocator generic_allocator_table[] = {
  35         {"malloc", 0},
  36         {"memdup", 1},
  37         {"realloc", 1},
  38 };
  39 
  40 static struct allocator kernel_allocator_table[] = {
  41         {"kmalloc", 0},
  42         {"kzalloc", 0},
  43         {"vmalloc", 0},
  44         {"__vmalloc", 0},
  45         {"vzalloc", 0},
  46         {"sock_kmalloc", 1},
  47         {"kmemdup", 1},
  48         {"kmemdup_user", 1},
  49         {"dma_alloc_attrs", 1},
  50         {"pci_alloc_consistent", 1},
  51         {"pci_alloc_coherent", 1},
  52         {"devm_kmalloc", 1},
  53         {"devm_kzalloc", 1},
  54         {"krealloc", 1},
  55 };
  56 
  57 static struct allocator illumos_user_calloc_table[] = {
  58         {"libld_calloc", 0, 1},
  59         {"calloc", 0, 1},
  60         {"kcalloc", 0, 1},
  61         {"kmalloc_array", 0, 1},
  62         {"devm_kcalloc", 1, 2},
  63 };
  64 
  65 static struct allocator generic_calloc_table[] = {
  66         {"calloc", 0, 1},
  67 };
  68 
  69 static struct allocator kernel_calloc_table[] = {
  70         {"kcalloc", 0, 1},
  71         {"kmalloc_array", 0, 1},
  72         {"devm_kcalloc", 1, 2},
  73 };
  74 
  75 static int bytes_per_element(struct expression *expr)
  76 {
  77         struct symbol *type;
  78 
  79         type = get_type(expr);
  80         if (!type)
  81                 return 0;
  82 
  83         if (type->type != SYM_PTR && type->type != SYM_ARRAY)
  84                 return 0;
  85 
  86         type = get_base_type(type);
  87         return type_bytes(type);
  88 }
  89 
  90 static void save_constraint_required(struct expression *pointer, int op, struct expression *constraint)
  91 {
  92         char *data, *limit;
  93 
  94         data = get_constraint_str(pointer);


 323         if (!tmp)
 324                 return;
 325 
 326         right = strip_expr(tmp);
 327         if (right->type != EXPR_CALL)
 328                 return;
 329 
 330         if (right->fn->type != EXPR_SYMBOL ||
 331             !right->fn->symbol ||
 332             !right->fn->symbol->ident)
 333                 return;
 334 
 335         for (i = 0; i < ARRAY_SIZE(generic_allocator_table); i++) {
 336                 if (strcmp(right->fn->symbol->ident->name,
 337                            generic_allocator_table[i].func) == 0) {
 338                         size_arg = generic_allocator_table[i].param;
 339                         goto found;
 340                 }
 341         }
 342 
 343         for (i = 0; i < ARRAY_SIZE(generic_calloc_table); i++) {
 344                 if (strcmp(right->fn->symbol->ident->name,
 345                            generic_calloc_table[i].func) == 0) {
 346                         size_arg = generic_calloc_table[i].param;
 347                         size_arg2 = generic_calloc_table[i].param2;
 348                         goto found;
 349                 }
 350         }       
 351 
 352         if (option_project == PROJ_ILLUMOS_USER) {
 353                 if (strcmp(right->fn->symbol->ident->name,
 354                            illumos_user_allocator_table[i].func) == 0) {
 355                         size_arg = illumos_user_allocator_table[i].param;
 356                         goto found;
 357                 }
 358 
 359                 for (i = 0; i < ARRAY_SIZE(illumos_user_calloc_table); i++) {
 360                         if (strcmp(right->fn->symbol->ident->name,
 361                             illumos_user_calloc_table[i].func) == 0) {
 362                                 size_arg = illumos_user_calloc_table[i].param;
 363                                 size_arg2 = illumos_user_calloc_table[i].param2;
 364                                 goto found;
 365                         }
 366                 }
 367         }
 368 
 369         if (option_project != PROJ_KERNEL)
 370                 return;
 371 
 372         for (i = 0; i < ARRAY_SIZE(kernel_allocator_table); i++) {
 373                 if (strcmp(right->fn->symbol->ident->name,
 374                            kernel_allocator_table[i].func) == 0) {
 375                         size_arg = kernel_allocator_table[i].param;
 376                         goto found;
 377                 }
 378         }
 379 
 380         for (i = 0; i < ARRAY_SIZE(kernel_calloc_table); i++) {
 381                 if (strcmp(right->fn->symbol->ident->name,
 382                            kernel_calloc_table[i].func) == 0) {
 383                         size_arg = kernel_calloc_table[i].param;
 384                         size_arg2 = kernel_calloc_table[i].param2;
 385                         goto found;
 386                 }
 387         }
 388 
 389         return;
 390 
 391 found:
 392         arg = get_argument_from_call_expr(right->args, size_arg);
 393         match_alloc_helper(expr->left, arg, 1);
 394         if (size_arg2 == -1)
 395                 return;
 396         arg = get_argument_from_call_expr(right->args, size_arg2);
 397         match_alloc_helper(expr->left, arg, 1);
 398 }
 399 
 400 static void match_assign_ARRAY_SIZE(struct expression *expr)
 401 {
 402         struct expression *array;
 403         char *data, *limit;
 404         const char *macro;


 492         free_string(right);
 493         free_string(left);
 494 }
 495 
 496 void register_constraints_required(int id)
 497 {
 498         my_id = id;
 499 
 500         add_hook(&match_assign_size, ASSIGNMENT_HOOK);
 501         add_hook(&match_assign_data, ASSIGNMENT_HOOK);
 502         add_hook(&match_assign_has_buf_comparison, ASSIGNMENT_HOOK);
 503 
 504         add_hook(&match_assign_ARRAY_SIZE, ASSIGNMENT_HOOK);
 505         add_hook(&match_assign_ARRAY_SIZE, GLOBAL_ASSIGNMENT_HOOK);
 506         add_hook(&match_assign_buf_comparison, ASSIGNMENT_HOOK);
 507         add_hook(&match_assign_constraint, ASSIGNMENT_HOOK);
 508 
 509         add_allocation_function("malloc", &match_alloc, 0);
 510         add_allocation_function("memdup", &match_alloc, 1);
 511         add_allocation_function("realloc", &match_alloc, 1);
 512         add_allocation_function("calloc", &match_calloc, 0);
 513         if (option_project == PROJ_ILLUMOS_USER) {
 514                 add_allocation_function("libld_malloc", &match_alloc, 0);
 515                 add_allocation_function("libld_realloc", &match_alloc, 1);
 516                 add_allocation_function("libld_calloc", &match_calloc, 0);
 517         }
 518         if (option_project == PROJ_KERNEL) {
 519                 add_allocation_function("kmalloc", &match_alloc, 0);
 520                 add_allocation_function("kzalloc", &match_alloc, 0);
 521                 add_allocation_function("vmalloc", &match_alloc, 0);
 522                 add_allocation_function("__vmalloc", &match_alloc, 0);
 523                 add_allocation_function("vzalloc", &match_alloc, 0);
 524                 add_allocation_function("sock_kmalloc", &match_alloc, 1);
 525                 add_allocation_function("kmemdup", &match_alloc, 1);
 526                 add_allocation_function("kmemdup_user", &match_alloc, 1);
 527                 add_allocation_function("dma_alloc_attrs", &match_alloc, 1);
 528                 add_allocation_function("pci_alloc_consistent", &match_alloc, 1);
 529                 add_allocation_function("pci_alloc_coherent", &match_alloc, 1);
 530                 add_allocation_function("devm_kmalloc", &match_alloc, 1);
 531                 add_allocation_function("devm_kzalloc", &match_alloc, 1);
 532                 add_allocation_function("kcalloc", &match_calloc, 0);
 533                 add_allocation_function("kmalloc_array", &match_calloc, 0);
 534                 add_allocation_function("devm_kcalloc", &match_calloc, 1);
 535                 add_allocation_function("krealloc", &match_alloc, 1);
 536         }
 537 }