145
|
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
|
|
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 #include "system.h"
|
|
23 #include "coretypes.h"
|
|
24 #include "tree.h"
|
|
25 #include "function.h"
|
|
26 #include "basic-block.h"
|
|
27 #include "gimple.h"
|
|
28 #include "options.h"
|
|
29 #include "function.h"
|
|
30 #include "diagnostic-core.h"
|
|
31 #include "pretty-print.h"
|
|
32 #include "analyzer/analyzer.h"
|
|
33 #include "analyzer/analyzer-logging.h"
|
|
34 #include "analyzer/sm.h"
|
|
35
|
|
36 #if ENABLE_ANALYZER
|
|
37
|
|
38 /* If STMT is an assignment from zero, return the LHS. */
|
|
39
|
|
40 tree
|
|
41 is_zero_assignment (const gimple *stmt)
|
|
42 {
|
|
43 const gassign *assign_stmt = dyn_cast <const gassign *> (stmt);
|
|
44 if (!assign_stmt)
|
|
45 return NULL_TREE;
|
|
46
|
|
47 enum tree_code op = gimple_assign_rhs_code (assign_stmt);
|
|
48 if (TREE_CODE_CLASS (op) != tcc_constant)
|
|
49 return NULL_TREE;
|
|
50
|
|
51 if (!zerop (gimple_assign_rhs1 (assign_stmt)))
|
|
52 return NULL_TREE;
|
|
53
|
|
54 return gimple_assign_lhs (assign_stmt);
|
|
55 }
|
|
56
|
|
57 /* Return true if VAR has pointer or reference type. */
|
|
58
|
|
59 bool
|
|
60 any_pointer_p (tree var)
|
|
61 {
|
|
62 return POINTER_TYPE_P (TREE_TYPE (var));
|
|
63 }
|
|
64
|
|
65 namespace ana {
|
|
66
|
|
67 /* Add a state with name NAME to this state_machine.
|
|
68 The string is required to outlive the state_machine.
|
|
69
|
|
70 Return the state_t for the new state. */
|
|
71
|
|
72 state_machine::state_t
|
|
73 state_machine::add_state (const char *name)
|
|
74 {
|
|
75 m_state_names.safe_push (name);
|
|
76 return m_state_names.length () - 1;
|
|
77 }
|
|
78
|
|
79 /* Get the name of state S within this state_machine. */
|
|
80
|
|
81 const char *
|
|
82 state_machine::get_state_name (state_t s) const
|
|
83 {
|
|
84 return m_state_names[s];
|
|
85 }
|
|
86
|
|
87 /* Assert that S is a valid state for this state_machine. */
|
|
88
|
|
89 void
|
|
90 state_machine::validate (state_t s) const
|
|
91 {
|
|
92 gcc_assert (s < m_state_names.length ());
|
|
93 }
|
|
94
|
|
95 /* Dump a multiline representation of this state machine to PP. */
|
|
96
|
|
97 void
|
|
98 state_machine::dump_to_pp (pretty_printer *pp) const
|
|
99 {
|
|
100 unsigned i;
|
|
101 const char *name;
|
|
102 FOR_EACH_VEC_ELT (m_state_names, i, name)
|
|
103 pp_printf (pp, " state %i: %qs\n", i, name);
|
|
104 }
|
|
105
|
|
106 /* Create instances of the various state machines, each using LOGGER,
|
|
107 and populate OUT with them. */
|
|
108
|
|
109 void
|
|
110 make_checkers (auto_delete_vec <state_machine> &out, logger *logger)
|
|
111 {
|
|
112 out.safe_push (make_malloc_state_machine (logger));
|
|
113 out.safe_push (make_fileptr_state_machine (logger));
|
|
114 out.safe_push (make_taint_state_machine (logger));
|
|
115 out.safe_push (make_sensitive_state_machine (logger));
|
|
116 out.safe_push (make_signal_state_machine (logger));
|
|
117
|
|
118 /* We only attempt to run the pattern tests if it might have been manually
|
|
119 enabled (for DejaGnu purposes). */
|
|
120 if (flag_analyzer_checker)
|
|
121 out.safe_push (make_pattern_test_state_machine (logger));
|
|
122
|
|
123 if (flag_analyzer_checker)
|
|
124 {
|
|
125 unsigned read_index, write_index;
|
|
126 state_machine **sm;
|
|
127
|
|
128 /* TODO: this leaks the machines
|
|
129 Would be nice to log the things that were removed. */
|
|
130 VEC_ORDERED_REMOVE_IF (out, read_index, write_index, sm,
|
|
131 0 != strcmp (flag_analyzer_checker,
|
|
132 (*sm)->get_name ()));
|
|
133 }
|
|
134 }
|
|
135
|
|
136 } // namespace ana
|
|
137
|
|
138 #endif /* #if ENABLE_ANALYZER */
|