Skip to content

Commit de5bf78

Browse files
committed
Concurrency: do not remove shared or dirty pointers from the value set
Just like we always add (and never replace) shared pointers in goto_symex_statet::assignment, symex_dead should not remove shared or dirty pointers. This fixes a first problem, with further problems remaining as indicated by the KNOWNBUG regression test.
1 parent 3b7e24b commit de5bf78

File tree

4 files changed

+83
-13
lines changed

4 files changed

+83
-13
lines changed
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
void worker(int *p)
2+
{
3+
__CPROVER_assert(*p == 1, "reading from dirty object");
4+
}
5+
6+
void create_thread(int **p)
7+
{
8+
#ifdef locals_bug
9+
int z = 1;
10+
__CPROVER_ASYNC_1:
11+
worker(&z);
12+
#else
13+
__CPROVER_ASYNC_1:
14+
worker(*p);
15+
#endif
16+
}
17+
18+
int main()
19+
{
20+
int y = 1;
21+
int *x[1] = {&y};
22+
create_thread(&x[0]);
23+
return 0;
24+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
KNOWNBUG
2+
main.c
3+
-Dlocals_bug
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^VERIFICATION SUCCESSFUL$
7+
--
8+
^warning: ignoring
9+
--
10+
There is a need for further debugging around copying local objects in
11+
the procedure spawning threads as we generate the following non-sensical
12+
constraint:
13+
// 28 file regression/cbmc-concurrency/dirty_local3/main.c line 3 function worker
14+
(57) CONSTRAINT(z!1@0#2 == z!1@0 || !choice_rf0)
15+
^^^^^^^^^^^^^^^^
16+
comparison of L2 and L1 SSA symbols
17+
// 28 file regression/cbmc-concurrency/dirty_local3/main.c line 3 function worker
18+
(58) CONSTRAINT(choice_rf0)
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CORE
2+
main.c
3+
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^VERIFICATION SUCCESSFUL$
7+
--
8+
^warning: ignoring

src/goto-symex/symex_dead.cpp

Lines changed: 33 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ Author: Daniel Kroening, [email protected]
1111

1212
#include "goto_symex.h"
1313

14-
#include <util/find_symbols.h>
1514
#include <util/std_expr.h>
1615

1716
void goto_symext::symex_dead(statet &state)
@@ -20,23 +19,27 @@ void goto_symext::symex_dead(statet &state)
2019
symex_dead(state, instruction.dead_symbol());
2120
}
2221

23-
void goto_symext::symex_dead(statet &state, const symbol_exprt &symbol_expr)
22+
static void remove_l1_object_rec(
23+
goto_symext::statet &state,
24+
const exprt &l1_expr,
25+
const namespacet &ns)
2426
{
25-
ssa_exprt to_rename = is_ssa_expr(symbol_expr) ? to_ssa_expr(symbol_expr)
26-
: ssa_exprt{symbol_expr};
27-
ssa_exprt ssa = state.rename_ssa<L1>(to_rename, ns).get();
28-
29-
const exprt fields = state.field_sensitivity.get_fields(ns, state, ssa);
30-
find_symbols_sett fields_set;
31-
find_symbols_or_nexts(fields, fields_set);
32-
33-
for(const irep_idt &l1_identifier : fields_set)
27+
if(is_ssa_expr(l1_expr))
3428
{
29+
const ssa_exprt &l1_ssa = to_ssa_expr(l1_expr);
30+
const irep_idt &l1_identifier = l1_ssa.get_identifier();
31+
3532
// We cannot remove the object from the L1 renaming map, because L1 renaming
3633
// information is not local to a path, but removing it from the propagation
3734
// map and value-set is safe as 1) it is local to a path and 2) this
38-
// instance can no longer appear.
39-
state.value_set.values.erase_if_exists(l1_identifier);
35+
// instance can no longer appear (unless shared across threads).
36+
if(
37+
state.threads.size() <= 1 ||
38+
state.write_is_shared(l1_ssa, ns) ==
39+
goto_symex_statet::write_is_shared_resultt::NOT_SHARED)
40+
{
41+
state.value_set.values.erase_if_exists(l1_identifier);
42+
}
4043
state.propagation.erase_if_exists(l1_identifier);
4144
// Remove from the local L2 renaming map; this means any reads from the dead
4245
// identifier will use generation 0 (e.g. x!N@M#0, where N and M are
@@ -45,4 +48,21 @@ void goto_symext::symex_dead(statet &state, const symbol_exprt &symbol_expr)
4548
// identifier is still live.
4649
state.drop_l1_name(l1_identifier);
4750
}
51+
else if(l1_expr.id() == ID_array || l1_expr.id() == ID_struct)
52+
{
53+
for(const auto &op : l1_expr.operands())
54+
remove_l1_object_rec(state, op, ns);
55+
}
56+
else
57+
UNREACHABLE;
58+
}
59+
60+
void goto_symext::symex_dead(statet &state, const symbol_exprt &symbol_expr)
61+
{
62+
ssa_exprt to_rename = is_ssa_expr(symbol_expr) ? to_ssa_expr(symbol_expr)
63+
: ssa_exprt{symbol_expr};
64+
ssa_exprt ssa = state.rename_ssa<L1>(to_rename, ns).get();
65+
66+
const exprt fields = state.field_sensitivity.get_fields(ns, state, ssa);
67+
remove_l1_object_rec(state, fields, ns);
4868
}

0 commit comments

Comments
 (0)