CBMC
uninitialized.cpp
Go to the documentation of this file.
1 /*******************************************************************\
2 
3 Module: Detection for Uninitialized Local Variables
4 
5 Author: Daniel Kroening
6 
7 Date: January 2010
8 
9 \*******************************************************************/
10 
13 
14 #include "uninitialized.h"
15 
17 
19 {
20 public:
21  explicit uninitializedt(symbol_table_baset &_symbol_table)
22  : symbol_table(_symbol_table), ns(_symbol_table)
23  {
24  }
25 
26  void add_assertions(
27  const irep_idt &function_identifer,
28  goto_programt &goto_program);
29 
30 protected:
34 
35  // The variables that need tracking,
36  // i.e., are uninitialized and may be read?
37  std::set<irep_idt> tracking;
38 
40 };
41 
44 {
45  std::list<exprt> objects=objects_read(*i_it);
46 
47  for(const auto &object : objects)
48  {
49  if(object.id() == ID_symbol)
50  {
51  const irep_idt &identifier = to_symbol_expr(object).get_identifier();
52  const std::set<irep_idt> &uninitialized=
53  uninitialized_analysis[i_it].uninitialized;
54  if(uninitialized.find(identifier)!=uninitialized.end())
55  tracking.insert(identifier);
56  }
57  else if(object.id() == ID_dereference)
58  {
59  }
60  }
61 }
62 
64  const irep_idt &function_identifier,
65  goto_programt &goto_program)
66 {
67  uninitialized_analysis(function_identifier, goto_program, ns);
68 
69  // find out which variables need tracking
70 
71  tracking.clear();
72  forall_goto_program_instructions(i_it, goto_program)
73  get_tracking(i_it);
74 
75  // add tracking symbols to symbol table
76  for(std::set<irep_idt>::const_iterator
77  it=tracking.begin();
78  it!=tracking.end();
79  it++)
80  {
81  const symbolt &symbol=ns.lookup(*it);
82 
83  symbolt new_symbol{
84  id2string(symbol.name) + "#initialized", bool_typet(), symbol.mode};
85  new_symbol.base_name=id2string(symbol.base_name)+"#initialized";
86  new_symbol.location=symbol.location;
87  new_symbol.module=symbol.module;
88  new_symbol.is_thread_local=true;
89  new_symbol.is_file_local=true;
90  new_symbol.is_lvalue=true;
91 
92  symbol_table.insert(std::move(new_symbol));
93  }
94 
95  Forall_goto_program_instructions(i_it, goto_program)
96  {
97  goto_programt::instructiont &instruction=*i_it;
98 
99  if(instruction.is_decl())
100  {
101  // if we track it, add declaration and assignment
102  // for tracking variable!
103 
104  const irep_idt &identifier = instruction.decl_symbol().get_identifier();
105 
106  if(tracking.find(identifier)!=tracking.end())
107  {
108  const irep_idt new_identifier=
109  id2string(identifier)+"#initialized";
110 
111  symbol_exprt symbol_expr(new_identifier, bool_typet());
113  goto_programt::make_decl(symbol_expr, instruction.source_location());
114 
116  symbol_expr, false_exprt(), instruction.source_location());
117 
118  goto_programt::targett i1_it =
119  goto_program.insert_after(i_it, std::move(i1));
120  goto_program.insert_after(i1_it, std::move(i2));
121  i_it++, i_it++;
122  }
123  }
124  else
125  {
126  std::list<exprt> read=objects_read(instruction);
127  std::list<exprt> written=objects_written(instruction);
128 
129  // if(instruction.is_function_call())
130  // const code_function_callt &code_function_call=
131  // to_code_function_call(instruction.code);
132 
133  const std::set<irep_idt> &uninitialized=
134  uninitialized_analysis[i_it].uninitialized;
135 
136  // check tracking variables
137  for(const auto &object : read)
138  {
139  if(object.id() == ID_symbol)
140  {
141  const irep_idt &identifier = to_symbol_expr(object).get_identifier();
142 
143  if(uninitialized.find(identifier)!=uninitialized.end())
144  {
145  INVARIANT(
146  tracking.find(identifier) != tracking.end(), "not tracked");
147  const irep_idt new_identifier=id2string(identifier)+"#initialized";
148 
149  // insert assertion
150  source_locationt annotated_location = instruction.source_location();
151  annotated_location.set_comment(
152  "use of uninitialized local variable " + id2string(identifier));
153  annotated_location.set_property_class("uninitialized local");
154  goto_programt::instructiont assertion =
156  symbol_exprt(new_identifier, bool_typet()), annotated_location);
157 
158  goto_program.insert_before_swap(i_it, assertion);
159  i_it++;
160  }
161  }
162  }
163 
164  // set tracking variables
165  for(const auto &object : written)
166  {
167  if(object.id() == ID_symbol)
168  {
169  const irep_idt &identifier = to_symbol_expr(object).get_identifier();
170 
171  if(tracking.find(identifier)!=tracking.end())
172  {
173  const irep_idt new_identifier=id2string(identifier)+"#initialized";
174 
175  goto_programt::instructiont assignment =
177  symbol_exprt(new_identifier, bool_typet()),
178  true_exprt(),
179  instruction.source_location());
180 
181  goto_program.insert_before_swap(i_it, assignment);
182  i_it++;
183  }
184  }
185  }
186  }
187  }
188 }
189 
191 {
192  for(auto &gf_entry : goto_model.goto_functions.function_map)
193  {
194  uninitializedt uninitialized(goto_model.symbol_table);
195 
196  uninitialized.add_assertions(gf_entry.first, gf_entry.second.body);
197  }
198 }
199 
201  const goto_modelt &goto_model,
202  std::ostream &out)
203 {
204  const namespacet ns(goto_model.symbol_table);
205 
206  for(const auto &gf_entry : goto_model.goto_functions.function_map)
207  {
208  if(gf_entry.second.body_available())
209  {
210  out << "////\n";
211  out << "//// Function: " << gf_entry.first << '\n';
212  out << "////\n\n";
213  uninitialized_analysist uninitialized_analysis;
214  uninitialized_analysis(gf_entry.first, gf_entry.second.body, ns);
215  uninitialized_analysis.output(
216  ns, gf_entry.first, gf_entry.second.body, out);
217  }
218  }
219 }
virtual void output(const namespacet &ns, const irep_idt &function_id, const goto_programt &goto_program, std::ostream &out) const
Output the abstract states for a single function.
Definition: ai.cpp:39
The Boolean type.
Definition: std_types.h:36
dstringt has one field, an unsigned integer no which is an index into a static table of strings.
Definition: dstring.h:38
The Boolean constant false.
Definition: std_expr.h:3064
function_mapt function_map
symbol_tablet symbol_table
Symbol table.
Definition: goto_model.h:31
goto_functionst goto_functions
GOTO functions.
Definition: goto_model.h:34
This class represents an instruction in the GOTO intermediate representation.
Definition: goto_program.h:181
const source_locationt & source_location() const
Definition: goto_program.h:333
const symbol_exprt & decl_symbol() const
Get the declared symbol for DECL.
Definition: goto_program.h:228
A generic container class for the GOTO intermediate representation of one function.
Definition: goto_program.h:73
void insert_before_swap(targett target)
Insertion that preserves jumps to "target".
Definition: goto_program.h:643
instructionst::iterator targett
Definition: goto_program.h:614
instructionst::const_iterator const_targett
Definition: goto_program.h:615
static instructiont make_assignment(const code_assignt &_code, const source_locationt &l=source_locationt::nil())
Create an assignment instruction.
targett insert_after(const_targett target)
Insertion after the instruction pointed-to by the given instruction iterator target.
Definition: goto_program.h:708
static instructiont make_decl(const symbol_exprt &symbol, const source_locationt &l=source_locationt::nil())
Definition: goto_program.h:964
static instructiont make_assertion(const exprt &g, const source_locationt &l=source_locationt::nil())
Definition: goto_program.h:933
A namespacet is essentially one or two symbol tables bound together, to allow for symbol lookups in t...
Definition: namespace.h:94
bool lookup(const irep_idt &name, const symbolt *&symbol) const override
See documentation for namespace_baset::lookup().
Definition: namespace.cpp:148
void set_comment(const irep_idt &comment)
void set_property_class(const irep_idt &property_class)
Expression to hold a symbol (variable)
Definition: std_expr.h:131
const irep_idt & get_identifier() const
Definition: std_expr.h:160
The symbol table base class interface.
virtual std::pair< symbolt &, bool > insert(symbolt symbol)=0
Move or copy a new symbol to the symbol table.
Symbol table entry.
Definition: symbol.h:28
irep_idt base_name
Base (non-scoped) name.
Definition: symbol.h:46
irep_idt module
Name of module the symbol belongs to.
Definition: symbol.h:43
source_locationt location
Source code location of definition of symbol.
Definition: symbol.h:37
irep_idt name
The unique identifier.
Definition: symbol.h:40
irep_idt mode
Language mode.
Definition: symbol.h:49
The Boolean constant true.
Definition: std_expr.h:3055
void add_assertions(const irep_idt &function_identifer, goto_programt &goto_program)
symbol_table_baset & symbol_table
std::set< irep_idt > tracking
void get_tracking(goto_programt::const_targett i_it)
which variables need tracking, i.e., are uninitialized and may be read?
uninitialized_analysist uninitialized_analysis
uninitializedt(symbol_table_baset &_symbol_table)
void objects_read(const exprt &src, std::list< exprt > &dest)
void objects_written(const exprt &src, std::list< exprt > &dest)
#define forall_goto_program_instructions(it, program)
#define Forall_goto_program_instructions(it, program)
const std::string & id2string(const irep_idt &d)
Definition: irep.h:40
int __CPROVER_ID java::java io InputStream read
Definition: java.io.c:5
const symbol_exprt & to_symbol_expr(const exprt &expr)
Cast an exprt to a symbol_exprt.
Definition: std_expr.h:272
void add_uninitialized_locals_assertions(goto_modelt &goto_model)
void show_uninitialized(const goto_modelt &goto_model, std::ostream &out)
Detection for Uninitialized Local Variables.
Detection for Uninitialized Local Variables.