Skip to content

Commit 0c1973c

Browse files
authored
Merge pull request diffblue#496 from diffblue/resolve_performance_issues_in_instrumenter
SEC-542: Replaced edge labels of propagation chains graph by global set of functions.
2 parents 114bcb4 + 4826db9 commit 0c1973c

File tree

3 files changed

+46
-59
lines changed

3 files changed

+46
-59
lines changed

src/taint-slicer/instrumentation_props.cpp

+4-18
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ static void perform_BFS(
9595
reachable.insert(nid);
9696
if(do_fwd_search)
9797
for(const auto &nid_fns : chains.get_successors_map().at(nid))
98-
work.push_back(nid_fns.first);
98+
work.push_back(nid_fns);
9999
else
100100
for(const auto pred_nid : chains.get_predecessors_map().at(nid))
101101
work.push_back(pred_nid);
@@ -232,28 +232,14 @@ void taint_build_instrumentation_props(
232232
{
233233
TMPROF_BLOCK();
234234

235-
// First we collect all functions mentioned in the graph of chains.
236-
std::set<irep_idt> functions;
237-
{
238-
// Here we collect functions mentioned in individual nodes
239-
for(const auto &node : chains.get_nodes())
240-
functions.insert(node.get_function_id());
241-
// Here we collect functions appearing in sets labelling edges of
242-
// chains graph.
243-
for(const auto &elem : chains.get_successors_map()) // For each node
244-
for(const auto &nid_fns : elem.second) // For each out-edge from the node
245-
for(const auto &fn : nid_fns.second) // For each label on the edge
246-
functions.insert(fn);
247-
}
248-
249-
// Now we compute root functions - they are exactly all nearest common
235+
// First we compute root functions - they are exactly all nearest common
250236
// callers of all functions collected from the graph of chains.
251237
// Explanation: A common caller of a set of functions is one that can reach
252238
// all of them in the call graph; a nearest common caller has no
253239
// callees which are themselves common callers.
254240
std::set<irep_idt> roots;
255241
find_nearest_common_callees(
256-
program.get_inverted_call_graph(), functions, roots);
242+
program.get_inverted_call_graph(), chains.get_functions(), roots);
257243

258244
for(const auto &root : roots)
259245
{
@@ -277,7 +263,7 @@ void taint_build_instrumentation_props(
277263
// (those corrensponding to applications of transition rules.)
278264
for(const auto &node : chains.get_nodes())
279265
{
280-
if(functions.count(node.get_function_id())!=0UL)
266+
if(chains.get_functions().count(node.get_function_id())!=0UL)
281267
{
282268
goto_programt::instructiont const& I=*node.get_instruction_id();
283269
INVARIANT(I.type==FUNCTION_CALL, "");

src/taint-slicer/propagation_chains.cpp

+36-35
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@ taint_propagation_chainst::taint_propagation_chainst(
141141
// In breadth-first manner from the sources we build propagation chains toward
142142
// sinks. We only build successor edges of chains in this breadth-first
143143
// construnction.
144+
std::unordered_map<taint_function_idt, function_ids_sett> cfg_reach_cache;
144145
std::deque<node_idt> bfs_queue(sources.cbegin(),sources.cend());
145146
std::unordered_set<nodet> visited;
146147
while(!bfs_queue.empty())
@@ -173,7 +174,8 @@ taint_propagation_chainst::taint_propagation_chainst(
173174
fn_vec.first,
174175
iit,
175176
inverted_call_graph,
176-
tokens_propagation_graph);
177+
tokens_propagation_graph,
178+
cfg_reach_cache);
177179
if(succ_nid!=nodes.size())
178180
bfs_queue.push_back(succ_nid);
179181
}
@@ -190,7 +192,7 @@ taint_propagation_chainst::taint_propagation_chainst(
190192
// Build predecessors of nodes of chains.
191193
for(const auto &elem : successors)
192194
for(const auto &nid_fns : elem.second)
193-
predecessors[nid_fns.first].insert(elem.first);
195+
predecessors[nid_fns].insert(elem.first);
194196
resolve_conditional_rule_applications(
195197
program,
196198
numbering,
@@ -208,7 +210,8 @@ taint_propagation_chainst::extend_chain_by_transition(
208210
const taint_function_idt &fid,
209211
const taint_instruction_idt &iid,
210212
const call_grapht &inverted_call_graph,
211-
const taint_tokens_propagation_grapht &tokens_propagation_graph)
213+
const taint_tokens_propagation_grapht &tokens_propagation_graph,
214+
std::unordered_map<taint_function_idt, function_ids_sett> &cfg_reach_cache)
212215
{
213216
TMPROF_BLOCK();
214217

@@ -218,32 +221,38 @@ taint_propagation_chainst::extend_chain_by_transition(
218221
// in the chain is generated). Otherwise we record the set of intermediate
219222
// functions (callers and/or callees), through which the paths must go (we
220223
// save union of the functions from different paths).
221-
function_ids_sett functions;
222224
{
223-
function_ids_sett src_fns, dst_fns;
224-
std::unordered_set<irep_idt,dstring_hash> fns;
225-
find_direct_or_indirect_callees_of_function(
226-
inverted_call_graph,
227-
nodes.at(nid).get_function_id(),
228-
fns);
229-
for(const auto &fname : fns)
230-
src_fns.insert(as_string(fname));
231-
fns.clear();
232-
find_direct_or_indirect_callees_of_function(inverted_call_graph, fid, fns);
233-
for(const auto &fname : fns)
234-
dst_fns.insert(as_string(fname));
225+
const auto collect_callers =
226+
[this, &inverted_call_graph](
227+
std::unordered_map<taint_function_idt, function_ids_sett> &cache,
228+
const taint_function_idt &fid)
229+
{
230+
if(cache.count(fid) == 0UL)
231+
{
232+
std::unordered_set<irep_idt,dstring_hash> fns;
233+
find_direct_or_indirect_callees_of_function(
234+
inverted_call_graph, fid, fns);
235+
function_ids_sett &dst_set = cache[fid];
236+
for(const auto &fname : fns)
237+
dst_set.insert(fname);
238+
}
239+
};
240+
collect_callers(cfg_reach_cache, nodes.at(nid).get_function_id());
241+
collect_callers(cfg_reach_cache, fid);
242+
const function_ids_sett &src_fns =
243+
cfg_reach_cache.at(nodes.at(nid).get_function_id());
244+
const function_ids_sett &dst_fns = cfg_reach_cache.at(fid);
245+
function_ids_sett intersect_functions;
235246
std::set_intersection(
236247
src_fns.cbegin(), src_fns.cend(),
237248
dst_fns.cbegin(), dst_fns.cend(),
238-
std::inserter(functions, functions.cend()));
239-
if(functions.empty())
249+
std::inserter(intersect_functions, intersect_functions.cend()));
250+
if(intersect_functions.empty())
240251
return nodes.size();
241252
std::set_union(
242253
src_fns.cbegin(), src_fns.cend(),
243254
dst_fns.cbegin(), dst_fns.cend(),
244255
std::inserter(functions, functions.cend()));
245-
functions.erase(nodes.at(nid).get_function_id());
246-
functions.erase(fid);
247256
}
248257
// Now we compute the target instrumentation node.
249258
node_idt dst_nid;
@@ -263,7 +272,7 @@ taint_propagation_chainst::extend_chain_by_transition(
263272
}
264273
// Now we perform the the insertion of the transition to the new node and
265274
// we consider the case of the target node being sink.
266-
const auto res=successors[nid].insert({dst_nid, functions});
275+
const auto res=successors[nid].insert(dst_nid);
267276
const std::vector<taint_rule_idt> &to_sink_rules=
268277
tokens_propagation_graph.get_backward_rules_from_token(
269278
tokens_propagation_graph.get_sink_token());
@@ -319,17 +328,17 @@ taint_propagation_chainst::erase_node(const node_idt nid)
319328
// predecessor. We handle that situation later.
320329
{
321330
auto &edges=successors.at(pred_nid);
322-
edges[nid].insert(edges[nodes.size()].begin(), edges[nodes.size()].end());
331+
edges.insert(nid);
323332
edges.erase(nodes.size());
324333
}
325334
for(const auto &nid_fns : get_successors_map().at(nodes.size()))
326-
if(nid_fns.first!=nodes.size()) // We have to exclude here the situation,
335+
if(nid_fns!=nodes.size()) // We have to exclude here the situation,
327336
// when the node 'nodes.size()' (i.e. the
328337
// one replacing the removed node 'nid')
329338
// is its own predecessor. We handle that
330339
// situation later.
331340
{
332-
auto &edges=predecessors.at(nid_fns.first);
341+
auto &edges=predecessors.at(nid_fns);
333342
edges.insert(nid);
334343
edges.erase(nodes.size());
335344
}
@@ -340,7 +349,7 @@ taint_propagation_chainst::erase_node(const node_idt nid)
340349
{
341350
{
342351
auto &edges=successors.at(nodes.size());
343-
edges[nid].insert(edges[nodes.size()].begin(), edges[nodes.size()].end());
352+
edges.insert(nid);
344353
edges.erase(nodes.size());
345354
}
346355
{
@@ -378,7 +387,7 @@ void taint_propagation_chainst::erase_dead_branches()
378387
continue;
379388
fwd_reachable.insert(nid);
380389
for(const auto &fns_nid : get_successors_map().at(nid))
381-
work.push_back(fns_nid.first);
390+
work.push_back(fns_nid);
382391
}
383392
}
384393
// Use BFS to find all nodes backward-reachable from sinks.
@@ -514,15 +523,7 @@ std::ostream &to_dot(
514523
ostr << " " << nid << " -> " << chains.get_nodes().size()+1U << ";\n";
515524
for(const auto &nid_edge : chains.get_successors_map())
516525
for(const auto &dstnid_elabel : nid_edge.second)
517-
{
518-
ostr << " " << nid_edge.first << " -> " << dstnid_elabel.first;
519-
ostr << " [label=\"FUNCTIONS {";
520-
if(!dstnid_elabel.second.empty())
521-
ostr << "\\l";
522-
for(const auto &fid : dstnid_elabel.second)
523-
ostr << " " << fid << "\\l";
524-
ostr << "}\\l\"];\n";
525-
}
526+
ostr << " " << nid_edge.first << " -> " << dstnid_elabel << ";\n";
526527

527528
ostr << "}\n";
528529
return ostr;

src/taint-slicer/propagation_chains.h

+6-6
Original file line numberDiff line numberDiff line change
@@ -117,12 +117,9 @@ class taint_propagation_chainst
117117
typedef node_vectort::size_type node_idt;
118118
typedef std::set<node_idt> node_id_sett;
119119

120-
typedef std::set<taint_function_idt> function_ids_sett;
120+
typedef std::set<irep_idt> function_ids_sett;
121121

122-
typedef std::map<
123-
node_idt,
124-
std::map<node_idt, function_ids_sett> >
125-
successors_mapt;
122+
typedef std::map<node_idt, std::set<node_idt> > successors_mapt;
126123
typedef std::map<node_idt, std::set<node_idt> > predecessors_mapt;
127124

128125
/*******************************************************************\
@@ -155,6 +152,7 @@ class taint_propagation_chainst
155152
const node_id_sett &get_sinks() const { return sinks; }
156153
const successors_mapt &get_successors_map() const { return successors; }
157154
const predecessors_mapt &get_predecessors_map() const { return predecessors; }
155+
const function_ids_sett &get_functions() const { return functions; }
158156

159157
private:
160158
taint_propagation_chainst(const taint_propagation_chainst &)=delete;
@@ -182,7 +180,8 @@ class taint_propagation_chainst
182180
const taint_function_idt &fid,
183181
const taint_instruction_idt &iid,
184182
const call_grapht &inverted_call_graph,
185-
const taint_tokens_propagation_grapht &tokens_propagation_graph);
183+
const taint_tokens_propagation_grapht &tokens_propagation_graph,
184+
std::unordered_map<taint_function_idt, function_ids_sett> &cfg_reach_cache);
186185

187186
/*******************************************************************\
188187
@@ -228,6 +227,7 @@ class taint_propagation_chainst
228227
node_id_sett sinks;
229228
successors_mapt successors;
230229
predecessors_mapt predecessors;
230+
function_ids_sett functions;
231231
};
232232

233233
inline const taint_propagation_chainst::successors_mapt::mapped_type &

0 commit comments

Comments
 (0)