-
Notifications
You must be signed in to change notification settings - Fork 269
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This introduces a variant of ASSERT instructions that are fatal when they are refuted. Execution paths through fatal assertions that are refuted are undefined. Assertions that (otherwise) pass and that are reachable from a refuted fatal assertion are now reported as UNKNOWN. The motivating use-case for fatal assertions is undefined behavior in languages such as C/C++ or Rust.
- Loading branch information
Showing
11 changed files
with
208 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
_Bool nondet_bool(); | ||
|
||
void main() | ||
{ | ||
int divisor = nondet_bool() ? 2 : 0; | ||
|
||
// possible division by zero | ||
int result = 10 / divisor; | ||
|
||
__CPROVER_assert(divisor == 2 || divisor == 0, "divisor value"); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
CORE | ||
main.c | ||
|
||
^EXIT=10$ | ||
^SIGNAL=0$ | ||
^\[main\.division-by-zero\.1\] line 8 division by zero in 10 / divisor: FAILURE$ | ||
^\[main\.assertion\.1\] line 10 divisor value: UNKNOWN$ | ||
^\*\* 1 of 2 failed | ||
^VERIFICATION FAILED$ | ||
-- | ||
^warning: ignoring |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,130 @@ | ||
/*******************************************************************\ | ||
Module: Fatal Assertions | ||
Author: Daniel Kroening, [email protected] | ||
\*******************************************************************/ | ||
|
||
/// \file | ||
/// Fatal Assertions | ||
|
||
#include "fatal_assertions.h" | ||
|
||
#include <util/irep_hash.h> | ||
|
||
#include <goto-programs/goto_functions.h> | ||
|
||
#include <stack> | ||
#include <unordered_set> | ||
|
||
struct function_loc_pairt | ||
{ | ||
using function_itt = goto_functionst::function_mapt::const_iterator; | ||
function_loc_pairt( | ||
function_itt __function_it, | ||
goto_programt::const_targett __target) | ||
: function_it(__function_it), target(__target) | ||
{ | ||
} | ||
function_itt function_it; | ||
goto_programt::const_targett target; | ||
bool operator==(const function_loc_pairt &other) const | ||
{ | ||
return function_it->first == other.function_it->first && | ||
target == other.target; | ||
} | ||
}; | ||
|
||
struct function_loc_pair_hasht | ||
{ | ||
std::size_t operator()(const function_loc_pairt &p) const | ||
{ | ||
auto h1 = p.function_it->first.hash(); | ||
auto h2 = const_target_hash{}(p.target); | ||
return hash_combine(h1, h2); | ||
} | ||
}; | ||
|
||
using loc_sett = | ||
std::unordered_set<function_loc_pairt, function_loc_pair_hasht>; | ||
|
||
static void | ||
reachable_fixpoint(loc_sett &locs, const goto_functionst &goto_functions) | ||
{ | ||
std::stack<function_loc_pairt> working; | ||
|
||
for(auto loc : locs) | ||
working.push(loc); | ||
|
||
while(!working.empty()) | ||
{ | ||
auto loc = working.top(); | ||
working.pop(); | ||
locs.insert(loc); | ||
|
||
if(loc.target->is_function_call()) | ||
{ | ||
} | ||
else | ||
{ | ||
auto &body = loc.function_it->second.body; | ||
|
||
for(auto successor : body.get_successors(loc.target)) | ||
working.emplace(loc.function_it, successor); | ||
} | ||
} | ||
} | ||
|
||
void propagate_fatal_assertions( | ||
propertiest &properties, | ||
const goto_functionst &goto_functions) | ||
{ | ||
// Iterate to find refuted fatal assertions. Anything reachalble | ||
// from there is a 'fatal loc'. | ||
loc_sett fatal_locs; | ||
|
||
for(auto function_it = goto_functions.function_map.begin(); | ||
function_it != goto_functions.function_map.end(); | ||
function_it++) | ||
{ | ||
auto &body = function_it->second.body; | ||
for(auto target = body.instructions.begin(); | ||
target != body.instructions.end(); | ||
target++) | ||
{ | ||
if(target->is_assert() && target->source_location().property_fatal()) | ||
{ | ||
auto id = target->source_location().get_property_id(); | ||
auto property = properties.find(id); | ||
CHECK_RETURN(property != properties.end()); | ||
|
||
// Status? | ||
if(property->second.status == property_statust::FAIL) | ||
{ | ||
fatal_locs.emplace(function_it, target); | ||
} | ||
} | ||
} | ||
} | ||
|
||
// Saturate fixpoint. | ||
reachable_fixpoint(fatal_locs, goto_functions); | ||
|
||
// Now mark PASS assertions as UNKNOWN. | ||
for(auto &loc : fatal_locs) | ||
{ | ||
if(loc.target->is_assert()) | ||
{ | ||
auto id = loc.target->source_location().get_property_id(); | ||
auto property = properties.find(id); | ||
CHECK_RETURN(property != properties.end()); | ||
|
||
// Status? | ||
if(property->second.status == property_statust::PASS) | ||
{ | ||
property->second.status = property_statust::UNKNOWN; | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
/*******************************************************************\ | ||
Module: Fatal Assertions | ||
Author: Daniel Kroening, [email protected] | ||
\*******************************************************************/ | ||
|
||
/// \file | ||
/// Fatal Assertions | ||
|
||
#ifndef CPROVER_GOTO_CHECKER_FATAL_ASSERTIONS_H | ||
#define CPROVER_GOTO_CHECKER_FATAL_ASSERTIONS_H | ||
|
||
#include "properties.h" | ||
|
||
class goto_functionst; | ||
|
||
/// Assertions after fatal assertions that are | ||
/// refuted do not have meaning, and passing ones | ||
/// are marked as UNKNOWN. | ||
/// Assertions that are independently refuted are left | ||
/// in that state, even though the counterexample | ||
/// might be invalid. | ||
/// This avoids ambiguity if two refuted fatal asserions | ||
/// may reach each other. | ||
void propagate_fatal_assertions(propertiest &, const goto_functionst &); | ||
|
||
#endif // CPROVER_GOTO_CHECKER_FATAL_ASSERTIONS_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters