Skip to content

Commit 60c6582

Browse files
committed
goto-symex/concurrency: limit unsoundness-abort to dereferencing shared pointers
Reading and writing pointers is not not itself unsound, only the interaction with value sets may cause unsound results. Hence, do not reject programs that never dereference a shared pointer. Fixes: #8714
1 parent 1e945cd commit 60c6582

File tree

14 files changed

+95
-86
lines changed

14 files changed

+95
-86
lines changed
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
CORE
22
main.c
33
--no-standard-checks
4-
^EXIT=10$
4+
pointer handling for concurrency is unsound
5+
^EXIT=6$
56
^SIGNAL=0$
6-
^VERIFICATION FAILED$
77
--
88
^warning: ignoring
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+
pointer handling for concurrency is unsound
5+
^EXIT=6$
6+
^SIGNAL=0$
7+
--
8+
^warning: ignoring

regression/cbmc-concurrency/global_pointer1/main.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@ void *thread1(void * arg)
1212
void *thread2(void *arg)
1313
{
1414
assert(v == &g);
15+
#ifndef NO_DEREF
1516
*v = 1;
17+
#endif
1618
}
1719

1820
int main()
@@ -26,7 +28,9 @@ int main()
2628
pthread_join(t2, 0);
2729

2830
assert(v == &g);
31+
#ifndef NO_DEREF
2932
assert(*v == 1);
33+
#endif
3034

3135
return 0;
3236
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
KNOWNBUG
2+
main.c
3+
-DNO_DEREF
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^VERIFICATION SUCCESSFUL$
7+
--
8+
^warning: ignoring
9+
--
10+
Simplification with value sets causes unsound results despite the absence of
11+
dereferencing.
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
CORE
22
main.c
33
--no-malloc-may-fail
4-
^EXIT=0$
4+
pointer handling for concurrency is unsound
5+
^EXIT=6$
56
^SIGNAL=0$
6-
^VERIFICATION SUCCESSFUL$
77
--
88
^warning: ignoring
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
CORE
22
main.c
33
--no-malloc-may-fail
4-
^EXIT=0$
4+
pointer handling for concurrency is unsound
5+
^EXIT=6$
56
^SIGNAL=0$
6-
^VERIFICATION SUCCESSFUL$
77
--
88
^warning: ignoring
Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,8 @@
11
CORE
22
main.c
3-
4-
^EXIT=6$
3+
--no-malloc-may-fail
4+
^VERIFICATION SUCCESSFUL$
5+
^EXIT=0$
56
^SIGNAL=0$
6-
pointer handling for concurrency is unsound
77
--
88
^warning: ignoring
9-
--
10-
The test uses "__CPROVER_ASYNC_1:" and the async-called function foo does
11-
pointer operations over allocated memory - which is not handled in a sound way
12-
in CBMC.

src/goto-symex/field_sensitivity.cpp

Lines changed: 12 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -359,15 +359,13 @@ void field_sensitivityt::field_assignments(
359359
goto_symex_statet &state,
360360
const ssa_exprt &lhs,
361361
const exprt &rhs,
362-
symex_targett &target,
363-
bool allow_pointer_unsoundness) const
362+
symex_targett &target) const
364363
{
365364
const exprt lhs_fs = get_fields(ns, state, lhs, false);
366365

367366
if(lhs != lhs_fs)
368367
{
369-
field_assignments_rec(
370-
ns, state, lhs_fs, rhs, target, allow_pointer_unsoundness);
368+
field_assignments_rec(ns, state, lhs_fs, rhs, target);
371369
// Erase the composite symbol from our working state. Note that we need to
372370
// have it in the propagation table and the value set while doing the field
373371
// assignments, thus we cannot skip putting it in there above.
@@ -388,22 +386,18 @@ void field_sensitivityt::field_assignments(
388386
/// \param lhs_fs: expanded symbol
389387
/// \param ssa_rhs: right-hand-side value to assign
390388
/// \param target: symbolic execution equation store
391-
/// \param allow_pointer_unsoundness: allow pointer unsoundness
392389
void field_sensitivityt::field_assignments_rec(
393390
const namespacet &ns,
394391
goto_symex_statet &state,
395392
const exprt &lhs_fs,
396393
const exprt &ssa_rhs,
397-
symex_targett &target,
398-
bool allow_pointer_unsoundness) const
394+
symex_targett &target) const
399395
{
400396
if(is_ssa_expr(lhs_fs))
401397
{
402398
const ssa_exprt &l1_lhs = to_ssa_expr(lhs_fs);
403399
const ssa_exprt ssa_lhs =
404-
state
405-
.assignment(l1_lhs, ssa_rhs, ns, true, true, allow_pointer_unsoundness)
406-
.get();
400+
state.assignment(l1_lhs, ssa_rhs, ns, true, true).get();
407401

408402
// do the assignment
409403
target.assignment(
@@ -454,16 +448,10 @@ void field_sensitivityt::field_assignments_rec(
454448
expr_try_dynamic_cast<field_sensitive_ssa_exprt>(member_lhs))
455449
{
456450
field_assignments_rec(
457-
ns,
458-
state,
459-
fs_ssa->get_object_ssa(),
460-
member_rhs,
461-
target,
462-
allow_pointer_unsoundness);
451+
ns, state, fs_ssa->get_object_ssa(), member_rhs, target);
463452
}
464453

465-
field_assignments_rec(
466-
ns, state, member_lhs, member_rhs, target, allow_pointer_unsoundness);
454+
field_assignments_rec(ns, state, member_lhs, member_rhs, target);
467455
++fs_it;
468456
}
469457
}
@@ -499,16 +487,10 @@ void field_sensitivityt::field_assignments_rec(
499487
expr_try_dynamic_cast<field_sensitive_ssa_exprt>(member_lhs))
500488
{
501489
field_assignments_rec(
502-
ns,
503-
state,
504-
fs_ssa->get_object_ssa(),
505-
member_rhs,
506-
target,
507-
allow_pointer_unsoundness);
490+
ns, state, fs_ssa->get_object_ssa(), member_rhs, target);
508491
}
509492

510-
field_assignments_rec(
511-
ns, state, member_lhs, member_rhs, target, allow_pointer_unsoundness);
493+
field_assignments_rec(ns, state, member_lhs, member_rhs, target);
512494
++fs_it;
513495
}
514496
}
@@ -540,16 +522,10 @@ void field_sensitivityt::field_assignments_rec(
540522
expr_try_dynamic_cast<field_sensitive_ssa_exprt>(index_lhs))
541523
{
542524
field_assignments_rec(
543-
ns,
544-
state,
545-
fs_ssa->get_object_ssa(),
546-
index_rhs,
547-
target,
548-
allow_pointer_unsoundness);
525+
ns, state, fs_ssa->get_object_ssa(), index_rhs, target);
549526
}
550527

551-
field_assignments_rec(
552-
ns, state, index_lhs, index_rhs, target, allow_pointer_unsoundness);
528+
field_assignments_rec(ns, state, index_lhs, index_rhs, target);
553529
++fs_it;
554530
}
555531
}
@@ -565,17 +541,10 @@ void field_sensitivityt::field_assignments_rec(
565541
{
566542
if(auto fs_ssa = expr_try_dynamic_cast<field_sensitive_ssa_exprt>(*fs_it))
567543
{
568-
field_assignments_rec(
569-
ns,
570-
state,
571-
fs_ssa->get_object_ssa(),
572-
op,
573-
target,
574-
allow_pointer_unsoundness);
544+
field_assignments_rec(ns, state, fs_ssa->get_object_ssa(), op, target);
575545
}
576546

577-
field_assignments_rec(
578-
ns, state, *fs_it, op, target, allow_pointer_unsoundness);
547+
field_assignments_rec(ns, state, *fs_it, op, target);
579548
++fs_it;
580549
}
581550
}

src/goto-symex/field_sensitivity.h

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -142,14 +142,12 @@ class field_sensitivityt
142142
/// \param rhs: right-hand-side value that was used in the preceding update of
143143
/// the full object
144144
/// \param target: symbolic execution equation store
145-
/// \param allow_pointer_unsoundness: allow pointer unsoundness
146145
void field_assignments(
147146
const namespacet &ns,
148147
goto_symex_statet &state,
149148
const ssa_exprt &lhs,
150149
const exprt &rhs,
151-
symex_targett &target,
152-
bool allow_pointer_unsoundness) const;
150+
symex_targett &target) const;
153151

154152
/// Turn an expression \p expr into a field-sensitive SSA expression.
155153
/// Field-sensitive SSA expressions have individual symbols for each
@@ -215,8 +213,7 @@ class field_sensitivityt
215213
goto_symex_statet &state,
216214
const exprt &lhs_fs,
217215
const exprt &ssa_rhs,
218-
symex_targett &target,
219-
bool allow_pointer_unsoundness) const;
216+
symex_targett &target) const;
220217

221218
[[nodiscard]] exprt simplify_opt(
222219
exprt e,

src/goto-symex/goto_symex_state.cpp

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,7 @@ renamedt<ssa_exprt, L2> goto_symex_statet::assignment(
7979
const exprt &rhs, // L2
8080
const namespacet &ns,
8181
bool rhs_is_simplified,
82-
bool record_value,
83-
bool allow_pointer_unsoundness)
82+
bool record_value)
8483
{
8584
// identifier should be l0 or l1, make sure it's l1
8685
lhs = rename_ssa<L1>(std::move(lhs), ns).get();
@@ -110,11 +109,6 @@ renamedt<ssa_exprt, L2> goto_symex_statet::assignment(
110109
DATA_INVARIANT(!check_renaming(rhs), "rhs renaming failed on l2");
111110
}
112111

113-
// see #305 on GitHub for a simple example and possible discussion
114-
if(is_shared && lhs.type().id() == ID_pointer && !allow_pointer_unsoundness)
115-
throw unsupported_operation_exceptiont(
116-
"pointer handling for concurrency is unsound");
117-
118112
// Update constant propagation map -- the RHS is L2
119113
if(!is_shared && record_value && goto_symex_can_forward_propagatet(ns)(rhs))
120114
{

0 commit comments

Comments
 (0)