@@ -46,13 +46,15 @@ class goto_check_ct
46
46
{
47
47
public:
48
48
goto_check_ct (
49
- const namespacet &_ns ,
49
+ symbol_table_baset &_symbol_table ,
50
50
const optionst &_options,
51
51
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)
53
53
{
54
54
enable_bounds_check = _options.get_bool_option (" bounds-check" );
55
55
enable_pointer_check = _options.get_bool_option (" pointer-check" );
56
+ enable_uninitialized_check =
57
+ _options.get_bool_option (" uninitialized-check" );
56
58
enable_memory_leak_check = _options.get_bool_option (" memory-leak-check" );
57
59
enable_memory_cleanup_check =
58
60
_options.get_bool_option (" memory-cleanup-check" );
@@ -94,7 +96,8 @@ class goto_check_ct
94
96
void collect_allocations (const goto_functionst &goto_functions);
95
97
96
98
protected:
97
- const namespacet &ns;
99
+ const namespacet ns;
100
+ symbol_table_baset &symbol_table;
98
101
std::unique_ptr<local_bitvector_analysist> local_bitvector_analysis;
99
102
goto_programt::const_targett current_target;
100
103
messaget log;
@@ -189,6 +192,8 @@ class goto_check_ct
189
192
void undefined_shift_check (const shift_exprt &, const guardt &);
190
193
void pointer_rel_check (const binary_exprt &, const guardt &);
191
194
void pointer_overflow_check (const exprt &, const guardt &);
195
+ void
196
+ uninitialized_check (const symbol_exprt &, const guardt &, bool is_assigned);
192
197
void memory_leak_check (const irep_idt &function_id);
193
198
194
199
// / Generates VCCs for the validity of the given dereferencing operation.
@@ -265,6 +270,7 @@ class goto_check_ct
265
270
266
271
bool enable_bounds_check;
267
272
bool enable_pointer_check;
273
+ bool enable_uninitialized_check;
268
274
bool enable_memory_leak_check;
269
275
bool enable_memory_cleanup_check;
270
276
bool enable_div_by_zero_check;
@@ -286,6 +292,7 @@ class goto_check_ct
286
292
std::map<irep_idt, bool *> name_to_flag{
287
293
{" bounds-check" , &enable_bounds_check},
288
294
{" pointer-check" , &enable_pointer_check},
295
+ {" uninitialized-check" , &enable_uninitialized_check},
289
296
{" memory-leak-check" , &enable_memory_leak_check},
290
297
{" memory-cleanup-check" , &enable_memory_cleanup_check},
291
298
{" 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)
1341
1348
guard);
1342
1349
}
1343
1350
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
+
1344
1411
void goto_check_ct::pointer_rel_check (
1345
1412
const binary_exprt &expr,
1346
1413
const guardt &guard)
@@ -2061,6 +2128,10 @@ void goto_check_ct::check_rec(
2061
2128
{
2062
2129
pointer_validity_check (to_dereference_expr (expr), expr, guard);
2063
2130
}
2131
+ else if (expr.id () == ID_symbol)
2132
+ {
2133
+ uninitialized_check (to_symbol_expr (expr), guard, is_assigned);
2134
+ }
2064
2135
else if (requires_pointer_primitive_check (expr))
2065
2136
{
2066
2137
pointer_primitive_check (expr, guard);
@@ -2469,6 +2540,7 @@ exprt goto_check_ct::is_in_bounds_of_some_explicit_allocation(
2469
2540
return disjunction (alloc_disjuncts);
2470
2541
}
2471
2542
2543
+ #if 0
2472
2544
void goto_check_c(
2473
2545
const irep_idt &function_identifier,
2474
2546
goto_functionst::goto_functiont &goto_function,
@@ -2479,14 +2551,15 @@ void goto_check_c(
2479
2551
goto_check_ct goto_check(ns, options, message_handler);
2480
2552
goto_check.goto_check(function_identifier, goto_function);
2481
2553
}
2554
+ #endif
2482
2555
2483
2556
void goto_check_c (
2484
- const namespacet &ns,
2485
2557
const optionst &options,
2558
+ symbol_table_baset &symbol_table,
2486
2559
goto_functionst &goto_functions,
2487
2560
message_handlert &message_handler)
2488
2561
{
2489
- goto_check_ct goto_check (ns , options, message_handler);
2562
+ goto_check_ct goto_check (symbol_table , options, message_handler);
2490
2563
2491
2564
goto_check.collect_allocations (goto_functions);
2492
2565
@@ -2501,8 +2574,7 @@ void goto_check_c(
2501
2574
goto_modelt &goto_model,
2502
2575
message_handlert &message_handler)
2503
2576
{
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);
2506
2578
}
2507
2579
2508
2580
void goto_check_ct::add_active_named_check_pragmas (
0 commit comments