Skip to content

Commit fe8e589

Browse files
Avoid infinite recursion in has_subtype
Type containing themselves, through pointers for instance, could lead to infinite recursions in this function. We solve the porblem by keeping track of the visited types.
1 parent 00b9bf6 commit fe8e589

File tree

1 file changed

+29
-20
lines changed

1 file changed

+29
-20
lines changed

src/util/expr_util.cpp

+29-20
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ Author: Daniel Kroening, [email protected]
99

1010
#include "expr_util.h"
1111

12+
#include <unordered_set>
1213
#include "expr.h"
1314
#include "expr_iterator.h"
1415
#include "fixedbv.h"
@@ -140,28 +141,36 @@ bool has_subtype(
140141
const std::function<bool(const typet &)> &pred,
141142
const namespacet &ns)
142143
{
143-
if(pred(type))
144-
return true;
145-
else if(type.id() == ID_symbol)
146-
return has_subtype(ns.follow(type), pred, ns);
147-
else if(type.id() == ID_c_enum_tag)
148-
return has_subtype(ns.follow_tag(to_c_enum_tag_type(type)), pred, ns);
149-
else if(type.id() == ID_struct || type.id() == ID_union)
150-
{
151-
const struct_union_typet &struct_union_type = to_struct_union_type(type);
144+
std::vector<std::reference_wrapper<const typet>> stack;
145+
std::unordered_set<typet, irep_hash> visited;
152146

153-
for(const auto &comp : struct_union_type.components())
154-
if(has_subtype(comp.type(), pred, ns))
155-
return true;
156-
}
157-
// do not look into pointer subtypes as this could cause unbounded recursion
158-
else if(type.id() == ID_array || type.id() == ID_vector)
159-
return has_subtype(type.subtype(), pred, ns);
160-
else if(type.has_subtypes())
147+
const auto push_if_not_visited = [&](const typet &t) {
148+
if(visited.insert(t).second)
149+
stack.emplace_back(t);
150+
};
151+
152+
push_if_not_visited(type);
153+
while(!stack.empty())
161154
{
162-
for(const auto &subtype : type.subtypes())
163-
if(has_subtype(subtype, pred, ns))
164-
return true;
155+
const typet &top = stack.back().get();
156+
stack.pop_back();
157+
158+
if(pred(top))
159+
return true;
160+
else if(top.id() == ID_symbol)
161+
push_if_not_visited(ns.follow(top));
162+
else if(top.id() == ID_c_enum_tag)
163+
push_if_not_visited(ns.follow_tag(to_c_enum_tag_type(top)));
164+
else if(top.id() == ID_struct || top.id() == ID_union)
165+
{
166+
for(const auto &comp : to_struct_union_type(top).components())
167+
push_if_not_visited(comp.type());
168+
}
169+
else
170+
{
171+
for(const auto &subtype : top.subtypes())
172+
push_if_not_visited(subtype);
173+
}
165174
}
166175

167176
return false;

0 commit comments

Comments
 (0)