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