1 /*
   2  * Copyright (C) 2010 Dan Carpenter.
   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  * This file is only for very generic stuff, that is reusable
  20  * between projects.  If you need something special create a
  21  * check_your_project.c.
  22  *
  23  */
  24 
  25 #include "smatch.h"
  26 #include "smatch_extra.h"
  27 #include "smatch_function_hashtable.h"
  28 
  29 static DEFINE_HASHTABLE_INSERT(insert_func, char, int);
  30 static DEFINE_HASHTABLE_SEARCH(search_func, char, int);
  31 static struct hashtable *skipped_funcs;
  32 static struct hashtable *silenced_funcs;
  33 static struct hashtable *no_inline_funcs;
  34 
  35 int is_skipped_function(void)
  36 {
  37         char *func;
  38 
  39         func = get_function();
  40         if (!func)
  41                 return 0;
  42         if (search_func(skipped_funcs, func))
  43                 return 1;
  44         return 0;
  45 }
  46 
  47 /*
  48  * A silenced function will still be processed and potentially appear in info
  49  * output, but not regular checks.
  50  */
  51 int is_silenced_function(void)
  52 {
  53         char *func;
  54 
  55         if (is_skipped_function())
  56                 return 1;
  57 
  58         func = get_function();
  59         if (!func)
  60                 return 0;
  61         if (search_func(silenced_funcs, func))
  62                 return 1;
  63         return 0;
  64 }
  65 
  66 int is_no_inline_function(const char *function)
  67 {
  68         if (search_func(no_inline_funcs, (char *)function))
  69                 return 1;
  70         return 0;
  71 }
  72 
  73 static void register_no_return_funcs(void)
  74 {
  75         struct token *token;
  76         const char *func;
  77         char name[256];
  78 
  79         snprintf(name, 256, "%s.no_return_funcs", option_project_str);
  80 
  81         token = get_tokens_file(name);
  82         if (!token)
  83                 return;
  84         if (token_type(token) != TOKEN_STREAMBEGIN)
  85                 return;
  86         token = token->next;
  87         while (token_type(token) != TOKEN_STREAMEND) {
  88                 if (token_type(token) != TOKEN_IDENT)
  89                         return;
  90                 func = show_ident(token->ident);
  91                 add_function_hook(func, &__match_nullify_path_hook, NULL);
  92                 token = token->next;
  93         }
  94         clear_token_alloc();
  95 }
  96 
  97 static void register_ignored_macros(void)
  98 {
  99         struct token *token;
 100         char *macro;
 101         char name[256];
 102 
 103         if (option_project == PROJ_NONE)
 104                 strcpy(name, "ignored_macros");
 105         else
 106                 snprintf(name, 256, "%s.ignored_macros", option_project_str);
 107 
 108         token = get_tokens_file(name);
 109         if (!token)
 110                 return;
 111         if (token_type(token) != TOKEN_STREAMBEGIN)
 112                 return;
 113         token = token->next;
 114         while (token_type(token) != TOKEN_STREAMEND) {
 115                 if (token_type(token) != TOKEN_IDENT)
 116                         return;
 117                 macro = alloc_string(show_ident(token->ident));
 118                 add_ptr_list(&__ignored_macros, macro);
 119                 token = token->next;
 120         }
 121         clear_token_alloc();
 122 }
 123 
 124 static void register_skipped_functions(void)
 125 {
 126         struct token *token;
 127         char *func;
 128         char name[256];
 129 
 130         skipped_funcs = create_function_hashtable(500);
 131 
 132         if (option_project == PROJ_NONE)
 133                 return;
 134 
 135         snprintf(name, 256, "%s.skipped_functions", option_project_str);
 136 
 137         token = get_tokens_file(name);
 138         if (!token)
 139                 return;
 140         if (token_type(token) != TOKEN_STREAMBEGIN)
 141                 return;
 142         token = token->next;
 143         while (token_type(token) != TOKEN_STREAMEND) {
 144                 if (token_type(token) != TOKEN_IDENT)
 145                         return;
 146                 func = alloc_string(show_ident(token->ident));
 147                 insert_func(skipped_funcs, func, INT_PTR(1));
 148                 token = token->next;
 149         }
 150         clear_token_alloc();
 151 }
 152 
 153 static void register_silenced_functions(void)
 154 {
 155         struct token *token;
 156         char *func;
 157         char name[256];
 158 
 159         silenced_funcs = create_function_hashtable(500);
 160 
 161         if (option_project == PROJ_NONE)
 162                 return;
 163 
 164         snprintf(name, 256, "%s.silenced_functions", option_project_str);
 165 
 166         token = get_tokens_file(name);
 167         if (!token)
 168                 return;
 169         if (token_type(token) != TOKEN_STREAMBEGIN)
 170                 return;
 171         token = token->next;
 172         while (token_type(token) != TOKEN_STREAMEND) {
 173                 if (token_type(token) != TOKEN_IDENT)
 174                         return;
 175                 func = alloc_string(show_ident(token->ident));
 176                 insert_func(silenced_funcs, func, INT_PTR(1));
 177                 token = token->next;
 178         }
 179         clear_token_alloc();
 180 }
 181 
 182 static void register_no_inline_functions(void)
 183 {
 184         struct token *token;
 185         char *func;
 186         char name[256];
 187 
 188         no_inline_funcs = create_function_hashtable(500);
 189 
 190         if (option_project == PROJ_NONE)
 191                 return;
 192 
 193         snprintf(name, 256, "%s.no_inline_functions", option_project_str);
 194 
 195         token = get_tokens_file(name);
 196         if (!token)
 197                 return;
 198         if (token_type(token) != TOKEN_STREAMBEGIN)
 199                 return;
 200         token = token->next;
 201         while (token_type(token) != TOKEN_STREAMEND) {
 202                 if (token_type(token) != TOKEN_IDENT)
 203                         return;
 204                 func = alloc_string(show_ident(token->ident));
 205                 insert_func(no_inline_funcs, func, INT_PTR(1));
 206                 token = token->next;
 207         }
 208         clear_token_alloc();
 209 }
 210 
 211 void register_project(int id)
 212 {
 213         register_no_return_funcs();
 214         register_ignored_macros();
 215         register_skipped_functions();
 216         register_silenced_functions();
 217         register_no_inline_functions();
 218 }