11f5207b7SJohn Levon /* 21f5207b7SJohn Levon * Copyright (C) 2009 Dan Carpenter. 31f5207b7SJohn Levon * 41f5207b7SJohn Levon * This program is free software; you can redistribute it and/or 51f5207b7SJohn Levon * modify it under the terms of the GNU General Public License 61f5207b7SJohn Levon * as published by the Free Software Foundation; either version 2 71f5207b7SJohn Levon * of the License, or (at your option) any later version. 81f5207b7SJohn Levon * 91f5207b7SJohn Levon * This program is distributed in the hope that it will be useful, 101f5207b7SJohn Levon * but WITHOUT ANY WARRANTY; without even the implied warranty of 111f5207b7SJohn Levon * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 121f5207b7SJohn Levon * GNU General Public License for more details. 131f5207b7SJohn Levon * 141f5207b7SJohn Levon * You should have received a copy of the GNU General Public License 151f5207b7SJohn Levon * along with this program; if not, see http://www.gnu.org/copyleft/gpl.txt 161f5207b7SJohn Levon */ 171f5207b7SJohn Levon 181f5207b7SJohn Levon #include "smatch.h" 191f5207b7SJohn Levon #include "smatch_extra.h" 201f5207b7SJohn Levon 211f5207b7SJohn Levon static int my_id; 221f5207b7SJohn Levon 231f5207b7SJohn Levon STATE(derefed); 241f5207b7SJohn Levon 251f5207b7SJohn Levon static void underef(struct sm_state *sm, struct expression *mod_expr) 261f5207b7SJohn Levon { 271f5207b7SJohn Levon set_state(my_id, sm->name, sm->sym, &undefined); 281f5207b7SJohn Levon } 291f5207b7SJohn Levon 301f5207b7SJohn Levon static void match_dereference(struct expression *expr) 311f5207b7SJohn Levon { 321f5207b7SJohn Levon if (__in_fake_assign) 331f5207b7SJohn Levon return; 341f5207b7SJohn Levon 351f5207b7SJohn Levon if (expr->type != EXPR_PREOP) 361f5207b7SJohn Levon return; 371f5207b7SJohn Levon expr = strip_expr(expr->unop); 381f5207b7SJohn Levon if (!is_pointer(expr)) 391f5207b7SJohn Levon return; 401f5207b7SJohn Levon if (implied_not_equal(expr, 0)) 411f5207b7SJohn Levon return; 421f5207b7SJohn Levon 431f5207b7SJohn Levon if (is_impossible_path()) 441f5207b7SJohn Levon return; 451f5207b7SJohn Levon 461f5207b7SJohn Levon set_state_expr(my_id, expr, &derefed); 471f5207b7SJohn Levon } 481f5207b7SJohn Levon 491f5207b7SJohn Levon static void set_param_dereferenced(struct expression *call, struct expression *arg, char *key, char *unused) 501f5207b7SJohn Levon { 511f5207b7SJohn Levon struct symbol *sym; 521f5207b7SJohn Levon char *name; 531f5207b7SJohn Levon 541f5207b7SJohn Levon name = get_variable_from_key(arg, key, &sym); 551f5207b7SJohn Levon if (!name || !sym) 561f5207b7SJohn Levon goto free; 571f5207b7SJohn Levon 581f5207b7SJohn Levon if (implied_not_equal_name_sym(name, sym, 0)) 591f5207b7SJohn Levon goto free; 601f5207b7SJohn Levon set_state(my_id, name, sym, &derefed); 611f5207b7SJohn Levon 621f5207b7SJohn Levon free: 631f5207b7SJohn Levon free_string(name); 641f5207b7SJohn Levon } 651f5207b7SJohn Levon 661f5207b7SJohn Levon static void match_condition(struct expression *expr) 671f5207b7SJohn Levon { 681f5207b7SJohn Levon struct sm_state *sm; 69*c85f09ccSJohn Levon char *name; 701f5207b7SJohn Levon 711f5207b7SJohn Levon if (__in_pre_condition) 721f5207b7SJohn Levon return; 731f5207b7SJohn Levon 74*c85f09ccSJohn Levon name = get_macro_name(expr->pos); 75*c85f09ccSJohn Levon if (name && 76*c85f09ccSJohn Levon (strcmp(name, "likely") != 0 && strcmp(name, "unlikely") != 0)) 771f5207b7SJohn Levon return; 781f5207b7SJohn Levon 791f5207b7SJohn Levon if (!is_pointer(expr)) 801f5207b7SJohn Levon return; 811f5207b7SJohn Levon 821f5207b7SJohn Levon sm = get_sm_state_expr(my_id, expr); 831f5207b7SJohn Levon if (!sm || sm->state != &derefed) 841f5207b7SJohn Levon return; 851f5207b7SJohn Levon 861f5207b7SJohn Levon sm_warning("variable dereferenced before check '%s' (see line %d)", sm->name, sm->line); 871f5207b7SJohn Levon set_state_expr(my_id, expr, &undefined); 881f5207b7SJohn Levon } 891f5207b7SJohn Levon 901f5207b7SJohn Levon void check_deref_check(int id) 911f5207b7SJohn Levon { 921f5207b7SJohn Levon my_id = id; 931f5207b7SJohn Levon add_hook(&match_dereference, DEREF_HOOK); 941f5207b7SJohn Levon add_hook(&match_condition, CONDITION_HOOK); 951f5207b7SJohn Levon select_return_implies_hook(DEREFERENCE, &set_param_dereferenced); 961f5207b7SJohn Levon add_modification_hook(my_id, &underef); 971f5207b7SJohn Levon } 98