1/* Modeling API uses and misuses via state machines. 2 Copyright (C) 2019-2020 Free Software Foundation, Inc. 3 Contributed by David Malcolm <dmalcolm@redhat.com>. 4 5This file is part of GCC. 6 7GCC is free software; you can redistribute it and/or modify it 8under the terms of the GNU General Public License as published by 9the Free Software Foundation; either version 3, or (at your option) 10any later version. 11 12GCC is distributed in the hope that it will be useful, but 13WITHOUT ANY WARRANTY; without even the implied warranty of 14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15General Public License for more details. 16 17You should have received a copy of the GNU General Public License 18along with GCC; see the file COPYING3. If not see 19<http://www.gnu.org/licenses/>. */ 20 21#ifndef GCC_ANALYZER_SM_H 22#define GCC_ANALYZER_SM_H 23 24/* Utility functions for use by state machines. */ 25 26extern tree is_zero_assignment (const gimple *stmt); 27extern bool any_pointer_p (tree var); 28 29namespace ana { 30 31class state_machine; 32class sm_context; 33class pending_diagnostic; 34 35/* An abstract base class for a state machine describing an API. 36 A mapping from state IDs to names, and various virtual functions 37 for pattern-matching on statements. */ 38 39class state_machine : public log_user 40{ 41public: 42 typedef unsigned state_t; 43 44 state_machine (const char *name, logger *logger) 45 : log_user (logger), m_name (name) {} 46 47 virtual ~state_machine () {} 48 49 /* Should states be inherited from a parent region to a child region, 50 when first accessing a child region? 51 For example we should inherit the taintedness of a subregion, 52 but we should not inherit the "malloc:non-null" state of a field 53 within a heap-allocated struct. */ 54 virtual bool inherited_state_p () const = 0; 55 56 const char *get_name () const { return m_name; } 57 58 const char *get_state_name (state_t s) const; 59 60 state_t get_state_by_name (const char *name); 61 62 /* Return true if STMT is a function call recognized by this sm. */ 63 virtual bool on_stmt (sm_context *sm_ctxt, 64 const supernode *node, 65 const gimple *stmt) const = 0; 66 67 virtual void on_phi (sm_context *sm_ctxt ATTRIBUTE_UNUSED, 68 const supernode *node ATTRIBUTE_UNUSED, 69 const gphi *phi ATTRIBUTE_UNUSED, 70 tree rhs ATTRIBUTE_UNUSED) const 71 { 72 } 73 74 virtual void on_condition (sm_context *sm_ctxt, 75 const supernode *node, 76 const gimple *stmt, 77 tree lhs, enum tree_code op, tree rhs) const = 0; 78 79 /* Return true if it safe to discard the given state (to help 80 when simplifying state objects). 81 States that need leak detection should return false. */ 82 virtual bool can_purge_p (state_t s) const = 0; 83 84 /* Called when VAR leaks (and !can_purge_p). */ 85 virtual pending_diagnostic *on_leak (tree var ATTRIBUTE_UNUSED) const 86 { 87 return NULL; 88 } 89 90 void validate (state_t s) const; 91 92 void dump_to_pp (pretty_printer *pp) const; 93 94protected: 95 state_t add_state (const char *name); 96 97private: 98 DISABLE_COPY_AND_ASSIGN (state_machine); 99 100 const char *m_name; 101 auto_vec<const char *> m_state_names; 102}; 103 104/* Is STATE the start state? (zero is hardcoded as the start state). */ 105 106static inline bool 107start_start_p (state_machine::state_t state) 108{ 109 return state == 0; 110} 111 112/* Abstract base class for state machines to pass to 113 sm_context::on_custom_transition for handling non-standard transitions 114 (e.g. adding a node and edge to simulate registering a callback and having 115 the callback be called later). */ 116 117class custom_transition 118{ 119public: 120 virtual ~custom_transition () {} 121 virtual void impl_transition (exploded_graph *eg, 122 exploded_node *src_enode, 123 int sm_idx) = 0; 124}; 125 126/* Abstract base class giving an interface for the state machine to call 127 the checker engine, at a particular stmt. */ 128 129class sm_context 130{ 131public: 132 virtual ~sm_context () {} 133 134 /* Get the fndecl used at call, or NULL_TREE. 135 Use in preference to gimple_call_fndecl (and gimple_call_addr_fndecl), 136 since it can look through function pointer assignments and 137 other callback handling. */ 138 virtual tree get_fndecl_for_call (const gcall *call) = 0; 139 140 /* Called by state_machine in response to pattern matches: 141 if VAR is in state FROM, transition it to state TO, potentially 142 recording the "origin" of the state as ORIGIN. 143 Use NODE and STMT for location information. */ 144 virtual void on_transition (const supernode *node, const gimple *stmt, 145 tree var, 146 state_machine::state_t from, 147 state_machine::state_t to, 148 tree origin = NULL_TREE) = 0; 149 150 /* Called by state_machine in response to pattern matches: 151 issue a diagnostic D if VAR is in state STATE, using NODE and STMT 152 for location information. */ 153 virtual void warn_for_state (const supernode *node, const gimple *stmt, 154 tree var, state_machine::state_t state, 155 pending_diagnostic *d) = 0; 156 157 virtual tree get_readable_tree (tree expr) 158 { 159 return expr; 160 } 161 162 virtual state_machine::state_t get_global_state () const = 0; 163 virtual void set_global_state (state_machine::state_t) = 0; 164 165 /* A vfunc for handling custom transitions, such as when registering 166 a signal handler. */ 167 virtual void on_custom_transition (custom_transition *transition) = 0; 168 169protected: 170 sm_context (int sm_idx, const state_machine &sm) 171 : m_sm_idx (sm_idx), m_sm (sm) {} 172 173 int m_sm_idx; 174 const state_machine &m_sm; 175}; 176 177 178/* The various state_machine subclasses are hidden in their respective 179 implementation files. */ 180 181extern void make_checkers (auto_delete_vec <state_machine> &out, 182 logger *logger); 183 184extern state_machine *make_malloc_state_machine (logger *logger); 185extern state_machine *make_fileptr_state_machine (logger *logger); 186extern state_machine *make_taint_state_machine (logger *logger); 187extern state_machine *make_sensitive_state_machine (logger *logger); 188extern state_machine *make_signal_state_machine (logger *logger); 189extern state_machine *make_pattern_test_state_machine (logger *logger); 190 191} // namespace ana 192 193#endif /* GCC_ANALYZER_SM_H */ 194