@@ -53,6 +53,8 @@ class goto_check_ct
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" );
@@ -189,6 +191,8 @@ class goto_check_ct
189
191
void undefined_shift_check (const shift_exprt &, const guardt &);
190
192
void pointer_rel_check (const binary_exprt &, const guardt &);
191
193
void pointer_overflow_check (const exprt &, const guardt &);
194
+ void
195
+ uninitialized_check (const symbol_exprt &, const guardt &, bool is_assigned);
192
196
void memory_leak_check (const irep_idt &function_id);
193
197
194
198
// / Generates VCCs for the validity of the given dereferencing operation.
@@ -265,6 +269,7 @@ class goto_check_ct
265
269
266
270
bool enable_bounds_check;
267
271
bool enable_pointer_check;
272
+ bool enable_uninitialized_check;
268
273
bool enable_memory_leak_check;
269
274
bool enable_memory_cleanup_check;
270
275
bool enable_div_by_zero_check;
@@ -286,6 +291,7 @@ class goto_check_ct
286
291
std::map<irep_idt, bool *> name_to_flag{
287
292
{" bounds-check" , &enable_bounds_check},
288
293
{" pointer-check" , &enable_pointer_check},
294
+ {" uninitialized-check" , &enable_uninitialized_check},
289
295
{" memory-leak-check" , &enable_memory_leak_check},
290
296
{" memory-cleanup-check" , &enable_memory_cleanup_check},
291
297
{" div-by-zero-check" , &enable_div_by_zero_check},
@@ -1339,6 +1345,45 @@ void goto_check_ct::nan_check(const exprt &expr, const guardt &guard)
1339
1345
guard);
1340
1346
}
1341
1347
1348
+ void goto_check_ct::uninitialized_check (
1349
+ const symbol_exprt &expr,
1350
+ const guardt &guard,
1351
+ bool is_assigned)
1352
+ {
1353
+ if (!enable_uninitialized_check)
1354
+ return ;
1355
+
1356
+ // Ignore C function symbols.
1357
+ if (expr.type ().id () == ID_code)
1358
+ return ;
1359
+
1360
+ // Don't check the LHS of an assignment -- these do not
1361
+ // have to be initialized
1362
+ if (is_assigned)
1363
+ return ;
1364
+
1365
+ // Look up the symbol
1366
+ auto &symbol = ns.lookup (expr);
1367
+
1368
+ // Anything with static lifetime is initialized by the runtime,
1369
+ // and is hence never uninitialized.
1370
+ if (symbol.is_static_lifetime )
1371
+ return ;
1372
+
1373
+ // Query our abstract domain whether this might be uninitialized use.
1374
+ if (!local_bitvector_analysis->get (current_target, expr).is_uninitialized ())
1375
+ return ; // not uninitialized
1376
+
1377
+ add_guarded_property (
1378
+ false_exprt{},
1379
+ " reading uninitialized local" ,
1380
+ " uninitialized" ,
1381
+ true , // not fatal
1382
+ expr.find_source_location (),
1383
+ expr,
1384
+ guard);
1385
+ }
1386
+
1342
1387
void goto_check_ct::pointer_rel_check (
1343
1388
const binary_exprt &expr,
1344
1389
const guardt &guard)
@@ -2059,6 +2104,10 @@ void goto_check_ct::check_rec(
2059
2104
{
2060
2105
pointer_validity_check (to_dereference_expr (expr), expr, guard);
2061
2106
}
2107
+ else if (expr.id () == ID_symbol)
2108
+ {
2109
+ uninitialized_check (to_symbol_expr (expr), guard, is_assigned);
2110
+ }
2062
2111
else if (requires_pointer_primitive_check (expr))
2063
2112
{
2064
2113
pointer_primitive_check (expr, guard);
0 commit comments