Skip to content

Commit 4156c4f

Browse files
tautschnigpeterschrammel
authored andcommitted
Fix bugs in witness output of struct assignments
Dereferencing may yield the first struct member as left-hand-side. Skipping padding must be done such as not to skip a field on the left-hand side.
1 parent 9b4ce66 commit 4156c4f

File tree

1 file changed

+37
-13
lines changed

1 file changed

+37
-13
lines changed

src/goto-programs/graphml_witness.cpp

Lines changed: 37 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ Author: Daniel Kroening
88

99
#include <iostream>
1010

11+
#include <util/base_type.h>
12+
#include <util/byte_operators.h>
1113
#include <util/config.h>
1214
#include <util/i2string.h>
1315
#include <util/arith_tools.h>
@@ -91,32 +93,53 @@ std::string graphml_witnesst::convert_assign_rec(
9193
else if(assign.rhs().id()==ID_struct ||
9294
assign.rhs().id()==ID_union)
9395
{
96+
// dereferencing may have resulted in an lhs that is the first
97+
// struct member; undo this
98+
if(assign.lhs().id()==ID_member &&
99+
!base_type_eq(assign.lhs().type(), assign.rhs().type(), ns))
100+
{
101+
code_assignt tmp=assign;
102+
tmp.lhs()=to_member_expr(assign.lhs()).struct_op();
103+
104+
return convert_assign_rec(identifier, tmp);
105+
}
106+
else if(assign.lhs().id()==ID_byte_extract_little_endian ||
107+
assign.lhs().id()==ID_byte_extract_big_endian)
108+
{
109+
code_assignt tmp=assign;
110+
tmp.lhs()=to_byte_extract_expr(assign.lhs()).op();
111+
112+
return convert_assign_rec(identifier, tmp);
113+
}
114+
94115
const struct_union_typet &type=
95116
to_struct_union_type(ns.follow(assign.lhs().type()));
96117
const struct_union_typet::componentst &components=
97118
type.components();
98119

99-
struct_union_typet::componentst::const_iterator c_it=
100-
components.begin();
101-
forall_operands(it, assign.rhs())
120+
exprt::operandst::const_iterator it=
121+
assign.rhs().operands().begin();
122+
for(const auto & comp : components)
102123
{
103-
if(c_it->type().id()==ID_code ||
104-
c_it->get_is_padding() ||
124+
if(comp.type().id()==ID_code ||
125+
comp.get_is_padding() ||
105126
// for some reason #is_padding gets lost in *some* cases
106-
has_prefix(id2string(c_it->get_name()), "$pad"))
107-
{
108-
++c_it;
127+
has_prefix(id2string(comp.get_name()), "$pad"))
109128
continue;
110-
}
111129

112-
assert(c_it!=components.end());
130+
assert(it!=assign.rhs().operands().end());
131+
113132
member_exprt member(
114133
assign.lhs(),
115-
c_it->get_name(),
134+
comp.get_name(),
116135
it->type());
117136
if(!result.empty()) result+=' ';
118137
result+=convert_assign_rec(identifier, code_assignt(member, *it));
119-
++c_it;
138+
++it;
139+
140+
// for unions just assign to the first member
141+
if(assign.rhs().id()==ID_union)
142+
break;
120143
}
121144
}
122145
else
@@ -404,7 +427,8 @@ void graphml_witnesst::operator()(const symex_target_equationt &equation)
404427

405428
if(from==sink)
406429
{
407-
++it; ++step_nr;
430+
++it;
431+
++step_nr;
408432
continue;
409433
}
410434

0 commit comments

Comments
 (0)