Branch data Line data Source code
1 : : /* Modeling API uses and misuses via state machines.
2 : : Copyright (C) 2019-2024 Free Software Foundation, Inc.
3 : : Contributed by David Malcolm <dmalcolm@redhat.com>.
4 : :
5 : : This file is part of GCC.
6 : :
7 : : GCC is free software; you can redistribute it and/or modify it
8 : : under the terms of the GNU General Public License as published by
9 : : the Free Software Foundation; either version 3, or (at your option)
10 : : any later version.
11 : :
12 : : GCC is distributed in the hope that it will be useful, but
13 : : WITHOUT ANY WARRANTY; without even the implied warranty of
14 : : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 : : General Public License for more details.
16 : :
17 : : You should have received a copy of the GNU General Public License
18 : : along with GCC; see the file COPYING3. If not see
19 : : <http://www.gnu.org/licenses/>. */
20 : :
21 : : #include "config.h"
22 : : #define INCLUDE_VECTOR
23 : : #include "system.h"
24 : : #include "coretypes.h"
25 : : #include "tree.h"
26 : : #include "function.h"
27 : : #include "basic-block.h"
28 : : #include "gimple.h"
29 : : #include "options.h"
30 : : #include "function.h"
31 : : #include "diagnostic-core.h"
32 : : #include "pretty-print.h"
33 : : #include "diagnostic.h"
34 : : #include "tree-diagnostic.h"
35 : : #include "analyzer/analyzer.h"
36 : : #include "analyzer/analyzer-logging.h"
37 : : #include "analyzer/sm.h"
38 : : #include "analyzer/call-string.h"
39 : : #include "analyzer/program-point.h"
40 : : #include "analyzer/store.h"
41 : : #include "analyzer/svalue.h"
42 : : #include "analyzer/program-state.h"
43 : : #include "analyzer/pending-diagnostic.h"
44 : : #include "make-unique.h"
45 : :
46 : : #if ENABLE_ANALYZER
47 : :
48 : : namespace ana {
49 : :
50 : : /* Return true if VAR has pointer or reference type. */
51 : :
52 : : bool
53 : 35864 : any_pointer_p (tree var)
54 : : {
55 : 35864 : return POINTER_TYPE_P (TREE_TYPE (var));
56 : : }
57 : :
58 : : /* Return true if SVAL has pointer or reference type. */
59 : :
60 : : bool
61 : 55154 : any_pointer_p (const svalue *sval)
62 : : {
63 : 55154 : if (!sval->get_type ())
64 : : return false;
65 : 55154 : return POINTER_TYPE_P (sval->get_type ());
66 : : }
67 : :
68 : : /* class state_machine::state. */
69 : :
70 : : /* Base implementation of dump_to_pp vfunc. */
71 : :
72 : : void
73 : 806 : state_machine::state::dump_to_pp (pretty_printer *pp) const
74 : : {
75 : 806 : pp_string (pp, m_name);
76 : 806 : }
77 : :
78 : : /* Return a new json::string describing the state. */
79 : :
80 : : std::unique_ptr<json::value>
81 : 9 : state_machine::state::to_json () const
82 : : {
83 : 9 : pretty_printer pp;
84 : 9 : pp_format_decoder (&pp) = default_tree_printer;
85 : 9 : dump_to_pp (&pp);
86 : 9 : return ::make_unique<json::string> (pp_formatted_text (&pp));
87 : 9 : }
88 : :
89 : : /* class state_machine. */
90 : :
91 : : /* state_machine's ctor. */
92 : :
93 : 22406 : state_machine::state_machine (const char *name, logger *logger)
94 : 22406 : : log_user (logger), m_name (name), m_next_state_id (0),
95 : 22406 : m_start (add_state ("start"))
96 : : {
97 : 22406 : }
98 : :
99 : : /* Add a state with name NAME to this state_machine.
100 : : The string is required to outlive the state_machine.
101 : :
102 : : Return the state_t for the new state. */
103 : :
104 : : state_machine::state_t
105 : 131114 : state_machine::add_state (const char *name)
106 : : {
107 : 131114 : state *s = new state (name, alloc_state_id ());
108 : 131114 : m_states.safe_push (s);
109 : 131114 : return s;
110 : : }
111 : :
112 : : /* Get the state with name NAME, which must exist.
113 : : This is purely intended for use in selftests. */
114 : :
115 : : state_machine::state_t
116 : 188 : state_machine::get_state_by_name (const char *name) const
117 : : {
118 : 188 : unsigned i;
119 : 188 : state *s;
120 : 376 : FOR_EACH_VEC_ELT (m_states, i, s)
121 : 376 : if (!strcmp (name, s->get_name ()))
122 : 188 : return s;
123 : : /* Name not found. */
124 : 0 : gcc_unreachable ();
125 : : }
126 : :
127 : : /* Base implementation of state_machine::on_leak. */
128 : :
129 : : std::unique_ptr<pending_diagnostic>
130 : 437 : state_machine::on_leak (tree var ATTRIBUTE_UNUSED) const
131 : : {
132 : 437 : return NULL;
133 : : }
134 : :
135 : : /* Dump a multiline representation of this state machine to PP. */
136 : :
137 : : void
138 : 0 : state_machine::dump_to_pp (pretty_printer *pp) const
139 : : {
140 : 0 : unsigned i;
141 : 0 : state *s;
142 : 0 : FOR_EACH_VEC_ELT (m_states, i, s)
143 : : {
144 : 0 : pp_printf (pp, " state %i: ", i);
145 : 0 : s->dump_to_pp (pp);
146 : 0 : pp_newline (pp);
147 : : }
148 : 0 : }
149 : :
150 : : /* Return a new json::object of the form
151 : : {"name" : str,
152 : : "states" : [str]}. */
153 : :
154 : : std::unique_ptr<json::object>
155 : 0 : state_machine::to_json () const
156 : : {
157 : 0 : auto sm_obj = ::make_unique<json::object> ();
158 : :
159 : 0 : sm_obj->set_string ("name", m_name);
160 : 0 : {
161 : 0 : auto states_arr = ::make_unique<json::array> ();
162 : 0 : unsigned i;
163 : 0 : state *s;
164 : 0 : FOR_EACH_VEC_ELT (m_states, i, s)
165 : 0 : states_arr->append (s->to_json ());
166 : 0 : sm_obj->set ("states", std::move (states_arr));
167 : 0 : }
168 : :
169 : 0 : return sm_obj;
170 : : }
171 : :
172 : : /* class sm_context. */
173 : :
174 : : const region_model *
175 : 260497 : sm_context::get_old_region_model () const
176 : : {
177 : 260497 : if (const program_state *old_state = get_old_program_state ())
178 : 260497 : return old_state->m_region_model;
179 : : else
180 : : return NULL;
181 : : }
182 : :
183 : : /* Create instances of the various state machines, each using LOGGER,
184 : : and populate OUT with them. */
185 : :
186 : : void
187 : 3197 : make_checkers (auto_delete_vec <state_machine> &out, logger *logger)
188 : : {
189 : 3197 : out.safe_push (make_malloc_state_machine (logger));
190 : 3197 : out.safe_push (make_fileptr_state_machine (logger));
191 : 3197 : out.safe_push (make_fd_state_machine (logger));
192 : 3197 : out.safe_push (make_taint_state_machine (logger));
193 : 3197 : out.safe_push (make_sensitive_state_machine (logger));
194 : 3197 : out.safe_push (make_signal_state_machine (logger));
195 : 3197 : out.safe_push (make_va_list_state_machine (logger));
196 : :
197 : : /* We only attempt to run the pattern tests if it might have been manually
198 : : enabled (for DejaGnu purposes). */
199 : 3197 : if (flag_analyzer_checker)
200 : 10 : out.safe_push (make_pattern_test_state_machine (logger));
201 : :
202 : 3197 : if (flag_analyzer_checker)
203 : : {
204 : 10 : unsigned read_index, write_index;
205 : 10 : state_machine **sm;
206 : :
207 : : /* TODO: this leaks the machines
208 : : Would be nice to log the things that were removed. */
209 : 90 : VEC_ORDERED_REMOVE_IF (out, read_index, write_index, sm,
210 : : 0 != strcmp (flag_analyzer_checker,
211 : : (*sm)->get_name ()));
212 : : }
213 : 3197 : }
214 : :
215 : : } // namespace ana
216 : :
217 : : #endif /* #if ENABLE_ANALYZER */
|