Skip to content

Commit 3df1868

Browse files
author
Remi Delmas
committed
CONTRACTS: track multiple malloc'd regions
For malloc we were fetching the address range from the malloc_return_value which is a unique global variable. As a result we would only track a single malloc'd location at a time. we now track a list of objects, from all occurrences of the variable.
1 parent 8a41865 commit 3df1868

File tree

5 files changed

+79
-28
lines changed

5 files changed

+79
-28
lines changed
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#include <stdlib.h>
2+
3+
void foo() __CPROVER_assigns()
4+
{
5+
char *loc1 = malloc(1);
6+
char *loc2 = malloc(1);
7+
int c;
8+
if(c)
9+
*loc1 = 0;
10+
else
11+
*loc2 = 0;
12+
}
13+
14+
int main()
15+
{
16+
foo();
17+
return 0;
18+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
CORE
2+
main.c
3+
--enforce-contract foo
4+
^\[foo.assigns.\d+\].* Check that \*loc1 is assignable: SUCCESS$
5+
^\[foo.assigns.\d+\].* Check that \*loc2 is assignable: SUCCESS$
6+
^VERIFICATION SUCCESSFUL$
7+
^EXIT=0$
8+
^SIGNAL=0$
9+
--
10+
--
11+
Checks that multiple malloc'd objects are tracked by assigns clause checking.

src/goto-instrument/contracts/havoc_assigns_clause_targets.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,8 @@ void havoc_assigns_clause_targetst::get_instructions(goto_programt &dest)
4848
for(const auto &pair : from_stack_alloc)
4949
havoc_if_valid(pair.second, havoc_program);
5050

51-
for(const auto &pair : from_heap_alloc)
52-
havoc_if_valid(pair.second, havoc_program);
51+
for(const auto &car : from_heap_alloc)
52+
havoc_if_valid(car, havoc_program);
5353

5454
for(const auto &pair : from_static_local)
5555
{

src/goto-instrument/contracts/instrument_spec_assigns.cpp

Lines changed: 40 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,14 @@ void instrument_spec_assignst::track_heap_allocated(
131131
const exprt &expr,
132132
goto_programt &dest)
133133
{
134-
create_snapshot(create_car_from_heap_alloc(expr), dest);
134+
// insert in tracking set
135+
const auto &car = create_car_from_heap_alloc(expr);
136+
137+
// generate target validity check for this target.
138+
target_validity_assertion(car, true, dest);
139+
140+
// generate snapshot instructions for this target.
141+
create_snapshot(car, dest);
135142
}
136143

137144
void instrument_spec_assignst::check_inclusion_assignment(
@@ -416,7 +423,7 @@ void instrument_spec_assignst::track_spec_target_group(
416423
cleanert cleaner(st, log.get_message_handler());
417424
exprt condition(group.condition());
418425
if(has_subexpr(condition, ID_side_effect))
419-
cleaner.clean(condition, dest, st.lookup_ref(function_id).mode);
426+
cleaner.clean(condition, dest, mode);
420427

421428
// create conditional address ranges by distributing the condition
422429
for(const auto &target : group.targets())
@@ -451,8 +458,7 @@ const symbolt instrument_spec_assignst::create_fresh_symbol(
451458
const typet &type,
452459
const source_locationt &location) const
453460
{
454-
return new_tmp_symbol(
455-
type, location, st.lookup_ref(function_id).mode, st, suffix);
461+
return new_tmp_symbol(type, location, mode, st, suffix);
456462
}
457463

458464
car_exprt instrument_spec_assignst::create_car_expr(
@@ -714,12 +720,25 @@ exprt instrument_spec_assignst::inclusion_check_full(
714720

715721
// Build a disjunction over all tracked locations
716722
exprt::operandst disjuncts;
723+
log.debug() << LOG_HEADER << " inclusion check: \n"
724+
<< from_expr_using_mode(ns, mode, car.target()) << " in {"
725+
<< messaget::eom;
717726

718727
for(const auto &pair : from_spec_assigns)
728+
{
719729
disjuncts.push_back(inclusion_check_single(car, pair.second));
730+
log.debug() << "\t(spec) "
731+
<< from_expr_using_mode(ns, mode, pair.second.target())
732+
<< messaget::eom;
733+
}
720734

721-
for(const auto &pair : from_heap_alloc)
722-
disjuncts.push_back(inclusion_check_single(car, pair.second));
735+
for(const auto &heap_car : from_heap_alloc)
736+
{
737+
disjuncts.push_back(inclusion_check_single(car, heap_car));
738+
log.debug() << "\t(heap) "
739+
<< from_expr_using_mode(ns, mode, heap_car.target())
740+
<< messaget::eom;
741+
}
723742

724743
if(include_stack_allocated)
725744
{
@@ -732,12 +751,21 @@ exprt instrument_spec_assignst::inclusion_check_full(
732751
continue;
733752

734753
disjuncts.push_back(inclusion_check_single(car, pair.second));
754+
log.debug() << "\t(stack) "
755+
<< from_expr_using_mode(ns, mode, pair.second.target())
756+
<< messaget::eom;
735757
}
736758

737759
// static locals are stack allocated and can never be DEAD
738760
for(const auto &pair : from_static_local)
761+
{
739762
disjuncts.push_back(inclusion_check_single(car, pair.second));
763+
log.debug() << "\t(static) "
764+
<< from_expr_using_mode(ns, mode, pair.second.target())
765+
<< messaget::eom;
766+
}
740767
}
768+
log.debug() << "}" << messaget::eom;
741769

742770
if(allow_null_lhs)
743771
return or_exprt{
@@ -793,21 +821,10 @@ const car_exprt &instrument_spec_assignst::create_car_from_stack_alloc(
793821
const car_exprt &
794822
instrument_spec_assignst::create_car_from_heap_alloc(const exprt &target)
795823
{
796-
const auto &found = from_heap_alloc.find(target);
797-
if(found != from_heap_alloc.end())
798-
{
799-
log.warning() << "Ignored duplicate heap-allocated target '"
800-
<< from_expr(ns, target.id(), target) << "' at "
801-
<< target.source_location().as_string() << messaget::eom;
802-
return found->second;
803-
}
804-
else
805-
{
806-
log.debug() << LOG_HEADER << "creating CAR for heap-allocated target "
807-
<< format(target) << messaget::eom;
808-
from_heap_alloc.insert({target, create_car_expr(true_exprt{}, target)});
809-
return from_heap_alloc.find(target)->second;
810-
}
824+
log.debug() << LOG_HEADER << "creating CAR for heap-allocated target "
825+
<< format(target) << messaget::eom;
826+
from_heap_alloc.emplace_back(create_car_expr(true_exprt{}, target));
827+
return from_heap_alloc.back();
811828
}
812829

813830
const car_exprt &instrument_spec_assignst::create_car_from_static_local(
@@ -854,8 +871,8 @@ void instrument_spec_assignst::invalidate_heap_and_spec_aliases(
854871
for(const auto &pair : from_spec_assigns)
855872
invalidate_car(pair.second, freed_car, dest);
856873

857-
for(const auto &pair : from_heap_alloc)
858-
invalidate_car(pair.second, freed_car, dest);
874+
for(const auto &car : from_heap_alloc)
875+
invalidate_car(car, freed_car, dest);
859876
}
860877

861878
/// Returns true iff an `ASSIGN lhs := rhs` instruction must be instrumented.

src/goto-instrument/contracts/instrument_spec_assigns.h

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,8 @@ class instrument_spec_assignst
209209
functions(_functions),
210210
st(_st),
211211
ns(_st),
212-
log(_message_handler)
212+
log(_message_handler),
213+
mode(st.lookup_ref(function_id).mode)
213214
{
214215
}
215216

@@ -507,6 +508,9 @@ class instrument_spec_assignst
507508
/// Logger
508509
messaget log;
509510

511+
/// Language mode
512+
const irep_idt &mode;
513+
510514
/// Track and generate snaphsot instructions and target validity
511515
/// checking assertions for a conditional target group from an assigns clause
512516
void track_spec_target_group(
@@ -655,8 +659,9 @@ class instrument_spec_assignst
655659
using exprt_to_car_mapt =
656660
std::unordered_map<const exprt, const car_exprt, irep_hash>;
657661

658-
/// Map from malloc'd symbols to corresponding conditional address ranges.
659-
exprt_to_car_mapt from_heap_alloc;
662+
/// List of malloc'd conditional address ranges.
663+
using car_expr_listt = std::list<car_exprt>;
664+
car_expr_listt from_heap_alloc;
660665

661666
const car_exprt &create_car_from_heap_alloc(const exprt &target);
662667

0 commit comments

Comments
 (0)