1 /*
   2  * Copyright (C) 2009 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  * In wine you aren't allowed to compare file handles with 0,
  20  * only with INVALID_HANDLE_VALUE.
  21  *
  22  */
  23 
  24 #include "smatch.h"
  25 
  26 static int my_id;
  27 
  28 STATE(filehandle);
  29 STATE(oktocheck);
  30 
  31 /* originally:
  32  *  "(?:CreateFile|CreateMailslot|CreateNamedPipe|FindFirstFile(?:Ex)?|OpenConsole|SetupOpenInfFile|socket)[AW]?"
  33  *
  34  */
  35 static const char *filehandle_funcs[] = {
  36         "CreateFile",
  37         "CreateMailslot",
  38         "CreateNamedPipe",
  39         "FindFirstFile",
  40         "FindFirstFileEx",
  41         "OpenConsole",
  42         "SetupOpenInfFile",
  43         "socket",
  44         NULL,
  45 };
  46 
  47 static void ok_to_use(struct sm_state *sm, struct expression *mod_expr)
  48 {
  49         if (sm->state != &oktocheck)
  50                 set_state(my_id, sm->name, sm->sym, &oktocheck);
  51 }
  52 
  53 static void match_returns_handle(const char *fn, struct expression *expr,
  54                              void *info)
  55 {
  56         char *left_name = NULL;
  57         struct symbol *left_sym;
  58 
  59         left_name = expr_to_var_sym(expr->left, &left_sym);
  60         if (!left_name || !left_sym)
  61                 goto free;
  62         set_state_expr(my_id, expr->left, &filehandle);
  63 free:
  64         free_string(left_name);
  65 }
  66 
  67 static void match_condition(struct expression *expr)
  68 {
  69         if (expr->type == EXPR_ASSIGNMENT)
  70                 match_condition(expr->left);
  71 
  72         if (get_state_expr(my_id, expr) == &filehandle) {
  73                 char *name;
  74 
  75                 name = expr_to_var(expr);
  76                 sm_error("comparing a filehandle against zero '%s'", name);
  77                 set_state_expr(my_id, expr, &oktocheck);
  78                 free_string(name);
  79         }
  80 }
  81 
  82 void check_wine_filehandles(int id)
  83 {
  84         int i;
  85 
  86         if (option_project != PROJ_WINE)
  87                 return;
  88 
  89         my_id = id;
  90         for (i = 0; filehandle_funcs[i]; i++) {
  91                 add_function_assign_hook(filehandle_funcs[i],
  92                                          &match_returns_handle, NULL);
  93         }
  94         add_hook(&match_condition, CONDITION_HOOK);
  95         add_modification_hook(my_id, ok_to_use);
  96 }