@@ -111,6 +111,18 @@ class goto_checkt
111
111
// / the) if-condition for recursively calls)
112
112
void check_rec_if (const if_exprt &if_expr, guardt &guard);
113
113
114
+ // / Check that a member expression is valid:
115
+ // / - check the structure this expression is a member of (via pointer of its
116
+ // / dereference)
117
+ // / - run pointer-validity check on `*(s+member_offset)' instead of
118
+ // / `s->member' to avoid checking safety of `s'
119
+ // / - check all operands of the expression
120
+ // / \param member: the expression to be checked
121
+ // / \param guard: the condition for the check (unmodified here)
122
+ // / \return true if no more checks are required for \p member or its
123
+ // / sub-expressions
124
+ bool check_rec_member (const member_exprt &member, guardt &guard);
125
+
114
126
void check_rec (const exprt &expr, guardt &guard);
115
127
void check (const exprt &expr);
116
128
@@ -1546,6 +1558,46 @@ void goto_checkt::check_rec_if(const if_exprt &if_expr, guardt &guard)
1546
1558
}
1547
1559
}
1548
1560
1561
+ bool goto_checkt::check_rec_member (const member_exprt &member, guardt &guard)
1562
+ {
1563
+ const dereference_exprt &deref = to_dereference_expr (member.struct_op ());
1564
+
1565
+ check_rec (deref.pointer (), guard);
1566
+
1567
+ // avoid building the following expressions when pointer_validity_check
1568
+ // would return immediately anyway
1569
+ if (!enable_pointer_check)
1570
+ return true ;
1571
+
1572
+ // we rewrite s->member into *(s+member_offset)
1573
+ // to avoid requiring memory safety of the entire struct
1574
+ auto member_offset_opt = member_offset_expr (member, ns);
1575
+
1576
+ if (member_offset_opt.has_value ())
1577
+ {
1578
+ pointer_typet new_pointer_type = to_pointer_type (deref.pointer ().type ());
1579
+ new_pointer_type.subtype () = member.type ();
1580
+
1581
+ const exprt char_pointer = typecast_exprt::conditional_cast (
1582
+ deref.pointer (), pointer_type (char_type ()));
1583
+
1584
+ const exprt new_address_casted = typecast_exprt::conditional_cast (
1585
+ typecast_exprt{
1586
+ plus_exprt{char_pointer,
1587
+ typecast_exprt::conditional_cast (
1588
+ member_offset_opt.value (), pointer_diff_type ())},
1589
+ char_pointer.type ()},
1590
+ new_pointer_type);
1591
+
1592
+ dereference_exprt new_deref{new_address_casted};
1593
+ new_deref.add_source_location () = deref.source_location ();
1594
+ pointer_validity_check (new_deref, guard);
1595
+
1596
+ return true ;
1597
+ }
1598
+ return false ;
1599
+ }
1600
+
1549
1601
void goto_checkt::check_rec (const exprt &expr, guardt &guard)
1550
1602
{
1551
1603
// we don't look into quantifiers
@@ -1568,49 +1620,12 @@ void goto_checkt::check_rec(const exprt &expr, guardt &guard)
1568
1620
check_rec_if (to_if_expr (expr), guard);
1569
1621
return ;
1570
1622
}
1571
- else if (expr.id ()==ID_member &&
1572
- to_member_expr (expr).struct_op ().id ()==ID_dereference)
1623
+ else if (
1624
+ expr.id () == ID_member &&
1625
+ to_member_expr (expr).struct_op ().id () == ID_dereference)
1573
1626
{
1574
- const member_exprt &member=to_member_expr (expr);
1575
- const dereference_exprt &deref=
1576
- to_dereference_expr (member.struct_op ());
1577
-
1578
- check_rec (deref.pointer (), guard);
1579
-
1580
- // avoid building the following expressions when pointer_validity_check
1581
- // would return immediately anyway
1582
- if (!enable_pointer_check)
1583
- return ;
1584
-
1585
- // we rewrite s->member into *(s+member_offset)
1586
- // to avoid requiring memory safety of the entire struct
1587
- auto member_offset_opt = member_offset_expr (member, ns);
1588
-
1589
- if (member_offset_opt.has_value ())
1590
- {
1591
- pointer_typet new_pointer_type = to_pointer_type (deref.pointer ().type ());
1592
- new_pointer_type.subtype () = expr.type ();
1593
-
1594
- const exprt char_pointer =
1595
- typecast_exprt::conditional_cast (
1596
- deref.pointer (), pointer_type (char_type ()));
1597
-
1598
- const exprt new_address = typecast_exprt (
1599
- plus_exprt (
1600
- char_pointer,
1601
- typecast_exprt::conditional_cast (
1602
- member_offset_opt.value (), pointer_diff_type ())),
1603
- char_pointer.type ());
1604
-
1605
- const exprt new_address_casted =
1606
- typecast_exprt::conditional_cast (new_address, new_pointer_type);
1607
-
1608
- dereference_exprt new_deref{new_address_casted};
1609
- new_deref.add_source_location () = deref.source_location ();
1610
- pointer_validity_check (new_deref, guard);
1611
-
1627
+ if (check_rec_member (to_member_expr (expr), guard))
1612
1628
return ;
1613
- }
1614
1629
}
1615
1630
1616
1631
forall_operands (it, expr)
0 commit comments