Skip to content

Commit 9624d5d

Browse files
committed
goto-model validation: Validate constant_exprt
We silently accept, and sometimes handle correctly, bitvector constants that are encoded as -[absolute value] instead of two's complement. The simplifier, however, will not handle this ambiguity as equalities over constants are evaluated by comparing the value strings. Therefore, use goto-model validation to ensure we do not process bitvector constants that don't use two's complement encoding. Fixes: #6759
1 parent 1a4c66e commit 9624d5d

File tree

4 files changed

+45
-1
lines changed

4 files changed

+45
-1
lines changed

regression/cbmc/link_json_symtabs/two.json_symtab

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1077,7 +1077,7 @@
10771077
}
10781078
},
10791079
"value": {
1080-
"id": "00000000000000000000000000000000",
1080+
"id": "0",
10811081
"sub": [
10821082
],
10831083
"namedSub": {

src/util/std_expr.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ Author: Daniel Kroening, [email protected]
99
#include "std_expr.h"
1010

1111
#include "namespace.h"
12+
#include "pointer_expr.h"
1213
#include "range.h"
1314

1415
#include <map>
@@ -19,6 +20,33 @@ bool constant_exprt::value_is_zero_string() const
1920
return val.find_first_not_of('0')==std::string::npos;
2021
}
2122

23+
void constant_exprt::check(const exprt &expr, const validation_modet vm)
24+
{
25+
DATA_CHECK(
26+
vm, !expr.has_operands(), "constant expression must not have operands");
27+
28+
DATA_CHECK(
29+
vm,
30+
!can_cast_type<bitvector_typet>(expr.type()) ||
31+
!id2string(to_constant_expr(expr).get_value()).empty(),
32+
"bitvector constant must have a non-empty value");
33+
34+
DATA_CHECK(
35+
vm,
36+
!can_cast_type<bitvector_typet>(expr.type()) ||
37+
can_cast_type<pointer_typet>(expr.type()) ||
38+
id2string(to_constant_expr(expr).get_value())
39+
.find_first_not_of("0123456789ABCDEF") == std::string::npos,
40+
"negative bitvector constant must use two's complement");
41+
42+
DATA_CHECK(
43+
vm,
44+
!can_cast_type<bitvector_typet>(expr.type()) ||
45+
to_constant_expr(expr).get_value() == ID_0 ||
46+
id2string(to_constant_expr(expr).get_value())[0] != '0',
47+
"bitvector constant must not have leading zeros");
48+
}
49+
2250
exprt disjunction(const exprt::operandst &op)
2351
{
2452
if(op.empty())

src/util/std_expr.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2848,6 +2848,18 @@ class constant_exprt : public nullary_exprt
28482848
}
28492849

28502850
bool value_is_zero_string() const;
2851+
2852+
static void check(
2853+
const exprt &expr,
2854+
const validation_modet vm = validation_modet::INVARIANT);
2855+
2856+
static void validate(
2857+
const exprt &expr,
2858+
const namespacet &,
2859+
const validation_modet vm = validation_modet::INVARIANT)
2860+
{
2861+
check(expr, vm);
2862+
}
28512863
};
28522864

28532865
template <>

src/util/validate_expressions.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,10 @@ void call_on_expr(const exprt &expr, Args &&... args)
4242
{
4343
CALL_ON_EXPR(dereference_exprt);
4444
}
45+
else if(expr.id() == ID_constant)
46+
{
47+
CALL_ON_EXPR(constant_exprt);
48+
}
4549
else
4650
{
4751
#ifdef REPORT_UNIMPLEMENTED_EXPRESSION_CHECKS

0 commit comments

Comments
 (0)