@@ -46,13 +46,15 @@ class goto_check_ct
4646{
4747public:
4848 goto_check_ct (
49- const namespacet &_ns ,
49+ symbol_table_baset &_symbol_table ,
5050 const optionst &_options,
5151 message_handlert &_message_handler)
52- : ns(_ns ), local_bitvector_analysis(nullptr ), log(_message_handler)
52+ : ns(_symbol_table), symbol_table(_symbol_table ), local_bitvector_analysis(nullptr ), log(_message_handler)
5353 {
5454 enable_bounds_check = _options.get_bool_option (" bounds-check" );
5555 enable_pointer_check = _options.get_bool_option (" pointer-check" );
56+ enable_uninitialized_check =
57+ _options.get_bool_option (" uninitialized-check" );
5658 enable_memory_leak_check = _options.get_bool_option (" memory-leak-check" );
5759 enable_memory_cleanup_check =
5860 _options.get_bool_option (" memory-cleanup-check" );
@@ -94,7 +96,8 @@ class goto_check_ct
9496 void collect_allocations (const goto_functionst &goto_functions);
9597
9698protected:
97- const namespacet &ns;
99+ const namespacet ns;
100+ symbol_table_baset &symbol_table;
98101 std::unique_ptr<local_bitvector_analysist> local_bitvector_analysis;
99102 goto_programt::const_targett current_target;
100103 messaget log;
@@ -189,6 +192,8 @@ class goto_check_ct
189192 void undefined_shift_check (const shift_exprt &, const guardt &);
190193 void pointer_rel_check (const binary_exprt &, const guardt &);
191194 void pointer_overflow_check (const exprt &, const guardt &);
195+ void
196+ uninitialized_check (const symbol_exprt &, const guardt &, bool is_assigned);
192197 void memory_leak_check (const irep_idt &function_id);
193198
194199 // / Generates VCCs for the validity of the given dereferencing operation.
@@ -265,6 +270,7 @@ class goto_check_ct
265270
266271 bool enable_bounds_check;
267272 bool enable_pointer_check;
273+ bool enable_uninitialized_check;
268274 bool enable_memory_leak_check;
269275 bool enable_memory_cleanup_check;
270276 bool enable_div_by_zero_check;
@@ -286,6 +292,7 @@ class goto_check_ct
286292 std::map<irep_idt, bool *> name_to_flag{
287293 {" bounds-check" , &enable_bounds_check},
288294 {" pointer-check" , &enable_pointer_check},
295+ {" uninitialized-check" , &enable_uninitialized_check},
289296 {" memory-leak-check" , &enable_memory_leak_check},
290297 {" memory-cleanup-check" , &enable_memory_cleanup_check},
291298 {" div-by-zero-check" , &enable_div_by_zero_check},
@@ -1341,6 +1348,66 @@ void goto_check_ct::nan_check(const exprt &expr, const guardt &guard)
13411348 guard);
13421349}
13431350
1351+ void goto_check_ct::uninitialized_check (
1352+ const symbol_exprt &expr,
1353+ const guardt &guard,
1354+ bool is_assigned)
1355+ {
1356+ if (!enable_uninitialized_check)
1357+ return ;
1358+
1359+ // Ignore C function symbols.
1360+ if (expr.type ().id () == ID_code)
1361+ return ;
1362+
1363+ // Don't check the LHS of an assignment -- these do not
1364+ // have to be initialized
1365+ if (is_assigned)
1366+ return ;
1367+
1368+ // Look up the symbol
1369+ auto &symbol = ns.lookup (expr);
1370+
1371+ // Anything with static lifetime is initialized by the runtime,
1372+ // and is hence never uninitialized.
1373+ if (symbol.is_static_lifetime )
1374+ return ;
1375+
1376+ // Is the address taken? If so, uninitialized accesses are merely
1377+ // intederminate, but not undefined.
1378+ if (local_bitvector_analysis->dirty (expr))
1379+ return ;
1380+
1381+ // Ignore structs/union/arrays for now
1382+ if (
1383+ symbol.type .id () == ID_struct || symbol.type .id () == ID_union ||
1384+ symbol.type .id () == ID_array)
1385+ {
1386+ return ;
1387+ }
1388+
1389+ // Look up the bits that track initialization
1390+ auto init_bit_id = id2string (symbol.name ) + " $init" ;
1391+
1392+ if (!symbol_table.has_symbol (init_bit_id))
1393+ {
1394+ auxiliary_symbolt new_init_symbol{init_bit_id, bool_typet{}, symbol.mode };
1395+ new_init_symbol.is_static_lifetime = false ;
1396+ symbol_table.add (new_init_symbol);
1397+ }
1398+
1399+ const symbolt &init_symbol = ns.lookup (init_bit_id);
1400+
1401+ add_guarded_property (
1402+ init_symbol.symbol_expr (),
1403+ " reading uninitialized local" ,
1404+ " uninitialized" ,
1405+ true , // not fatal
1406+ expr.find_source_location (),
1407+ expr,
1408+ guard);
1409+ }
1410+
13441411void goto_check_ct::pointer_rel_check (
13451412 const binary_exprt &expr,
13461413 const guardt &guard)
@@ -2061,6 +2128,10 @@ void goto_check_ct::check_rec(
20612128 {
20622129 pointer_validity_check (to_dereference_expr (expr), expr, guard);
20632130 }
2131+ else if (expr.id () == ID_symbol)
2132+ {
2133+ uninitialized_check (to_symbol_expr (expr), guard, is_assigned);
2134+ }
20642135 else if (requires_pointer_primitive_check (expr))
20652136 {
20662137 pointer_primitive_check (expr, guard);
@@ -2469,6 +2540,7 @@ exprt goto_check_ct::is_in_bounds_of_some_explicit_allocation(
24692540 return disjunction (alloc_disjuncts);
24702541}
24712542
2543+ #if 0
24722544void goto_check_c(
24732545 const irep_idt &function_identifier,
24742546 goto_functionst::goto_functiont &goto_function,
@@ -2479,14 +2551,15 @@ void goto_check_c(
24792551 goto_check_ct goto_check(ns, options, message_handler);
24802552 goto_check.goto_check(function_identifier, goto_function);
24812553}
2554+ #endif
24822555
24832556void goto_check_c (
2484- const namespacet &ns,
24852557 const optionst &options,
2558+ symbol_table_baset &symbol_table,
24862559 goto_functionst &goto_functions,
24872560 message_handlert &message_handler)
24882561{
2489- goto_check_ct goto_check (ns , options, message_handler);
2562+ goto_check_ct goto_check (symbol_table , options, message_handler);
24902563
24912564 goto_check.collect_allocations (goto_functions);
24922565
@@ -2501,8 +2574,7 @@ void goto_check_c(
25012574 goto_modelt &goto_model,
25022575 message_handlert &message_handler)
25032576{
2504- const namespacet ns (goto_model.symbol_table );
2505- goto_check_c (ns, options, goto_model.goto_functions , message_handler);
2577+ goto_check_c (options, goto_model.symbol_table , goto_model.goto_functions , message_handler);
25062578}
25072579
25082580void goto_check_ct::add_active_named_check_pragmas (
0 commit comments