Skip to content

Commit 1b24efd

Browse files
committed
Verify member expressions
This checks that the component they refer to really exists, and the expression and component's types match (are base_type_eq).
1 parent c74d257 commit 1b24efd

File tree

3 files changed

+52
-3
lines changed

3 files changed

+52
-3
lines changed

src/util/std_expr.cpp

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,7 @@ Author: Daniel Kroening, kroening@kroening.com
1313
#include "arith_tools.h"
1414
#include "byte_operators.h"
1515
#include "c_types.h"
16-
#include "expr_util.h"
17-
#include "mathematical_types.h"
16+
#include "namespace.h"
1817
#include "pointer_offset_size.h"
1918

2019
bool constant_exprt::value_is_zero_string() const
@@ -223,3 +222,35 @@ const exprt &object_descriptor_exprt::root_object() const
223222

224223
return *p;
225224
}
225+
226+
void member_exprt::validate(
227+
const exprt &expr,
228+
const namespacet &ns,
229+
const validation_modet vm)
230+
{
231+
check(expr, vm);
232+
233+
const auto &member_expr = to_member_expr(expr);
234+
235+
const typet &compound_type = ns.follow(member_expr.compound().type());
236+
DATA_CHECK(
237+
vm,
238+
can_cast_type<struct_union_typet>(compound_type),
239+
"member must address a struct, union or compatible type");
240+
241+
const auto &component =
242+
to_struct_union_type(compound_type).get_component(
243+
member_expr.get_component_name());
244+
245+
DATA_CHECK(
246+
vm,
247+
component.is_not_nil(),
248+
"member component '" + id2string(member_expr.get_component_name()) +
249+
"' must exist on addressed type");
250+
251+
DATA_CHECK(
252+
vm,
253+
base_type_eq(component.type(), member_expr.type(), ns),
254+
"member expression's type must match the addressed struct or union "
255+
"component");
256+
}

src/util/std_expr.h

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3897,6 +3897,21 @@ class member_exprt:public unary_exprt
38973897
{
38983898
return op0();
38993899
}
3900+
3901+
static void check(
3902+
const exprt &expr,
3903+
const validation_modet vm = validation_modet::INVARIANT)
3904+
{
3905+
DATA_CHECK(
3906+
vm,
3907+
expr.operands().size() == 1,
3908+
"member expression must have one operand");
3909+
}
3910+
3911+
static void validate(
3912+
const exprt &expr,
3913+
const namespacet &ns,
3914+
const validation_modet vm = validation_modet::INVARIANT);
39003915
};
39013916

39023917
/// \brief Cast an exprt to a \ref member_exprt
@@ -3933,7 +3948,6 @@ inline void validate_expr(const member_exprt &value)
39333948
validate_operands(value, 1, "Extract member must have one operand");
39343949
}
39353950

3936-
39373951
/// \brief Evaluates to true if the operand is NaN
39383952
class isnan_exprt:public unary_predicate_exprt
39393953
{

src/util/validate_expressions.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@ void call_on_expr(const exprt &expr, Args &&... args)
3737
{
3838
CALL_ON_EXPR(ssa_exprt);
3939
}
40+
else if(expr.id() == ID_member)
41+
{
42+
CALL_ON_EXPR(member_exprt);
43+
}
4044
else
4145
{
4246
#ifdef REPORT_UNIMPLEMENTED_EXPRESSION_CHECKS

0 commit comments

Comments
 (0)