@@ -141,6 +141,7 @@ taint_propagation_chainst::taint_propagation_chainst(
141
141
// In breadth-first manner from the sources we build propagation chains toward
142
142
// sinks. We only build successor edges of chains in this breadth-first
143
143
// construnction.
144
+ std::unordered_map<taint_function_idt, function_ids_sett> cfg_reach_cache;
144
145
std::deque<node_idt> bfs_queue (sources.cbegin (),sources.cend ());
145
146
std::unordered_set<nodet> visited;
146
147
while (!bfs_queue.empty ())
@@ -173,7 +174,8 @@ taint_propagation_chainst::taint_propagation_chainst(
173
174
fn_vec.first ,
174
175
iit,
175
176
inverted_call_graph,
176
- tokens_propagation_graph);
177
+ tokens_propagation_graph,
178
+ cfg_reach_cache);
177
179
if (succ_nid!=nodes.size ())
178
180
bfs_queue.push_back (succ_nid);
179
181
}
@@ -190,7 +192,7 @@ taint_propagation_chainst::taint_propagation_chainst(
190
192
// Build predecessors of nodes of chains.
191
193
for (const auto &elem : successors)
192
194
for (const auto &nid_fns : elem.second )
193
- predecessors[nid_fns. first ].insert (elem.first );
195
+ predecessors[nid_fns].insert (elem.first );
194
196
resolve_conditional_rule_applications (
195
197
program,
196
198
numbering,
@@ -208,7 +210,8 @@ taint_propagation_chainst::extend_chain_by_transition(
208
210
const taint_function_idt &fid,
209
211
const taint_instruction_idt &iid,
210
212
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)
212
215
{
213
216
TMPROF_BLOCK ();
214
217
@@ -218,32 +221,38 @@ taint_propagation_chainst::extend_chain_by_transition(
218
221
// in the chain is generated). Otherwise we record the set of intermediate
219
222
// functions (callers and/or callees), through which the paths must go (we
220
223
// save union of the functions from different paths).
221
- function_ids_sett functions;
222
224
{
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;
235
246
std::set_intersection (
236
247
src_fns.cbegin (), src_fns.cend (),
237
248
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 ())
240
251
return nodes.size ();
241
252
std::set_union (
242
253
src_fns.cbegin (), src_fns.cend (),
243
254
dst_fns.cbegin (), dst_fns.cend (),
244
255
std::inserter (functions, functions.cend ()));
245
- functions.erase (nodes.at (nid).get_function_id ());
246
- functions.erase (fid);
247
256
}
248
257
// Now we compute the target instrumentation node.
249
258
node_idt dst_nid;
@@ -263,7 +272,7 @@ taint_propagation_chainst::extend_chain_by_transition(
263
272
}
264
273
// Now we perform the the insertion of the transition to the new node and
265
274
// 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);
267
276
const std::vector<taint_rule_idt> &to_sink_rules=
268
277
tokens_propagation_graph.get_backward_rules_from_token (
269
278
tokens_propagation_graph.get_sink_token ());
@@ -319,17 +328,17 @@ taint_propagation_chainst::erase_node(const node_idt nid)
319
328
// predecessor. We handle that situation later.
320
329
{
321
330
auto &edges=successors.at (pred_nid);
322
- edges[nid] .insert (edges[nodes. size ()]. begin (), edges[nodes. size ()]. end () );
331
+ edges.insert (nid );
323
332
edges.erase (nodes.size ());
324
333
}
325
334
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,
327
336
// when the node 'nodes.size()' (i.e. the
328
337
// one replacing the removed node 'nid')
329
338
// is its own predecessor. We handle that
330
339
// situation later.
331
340
{
332
- auto &edges=predecessors.at (nid_fns. first );
341
+ auto &edges=predecessors.at (nid_fns);
333
342
edges.insert (nid);
334
343
edges.erase (nodes.size ());
335
344
}
@@ -340,7 +349,7 @@ taint_propagation_chainst::erase_node(const node_idt nid)
340
349
{
341
350
{
342
351
auto &edges=successors.at (nodes.size ());
343
- edges[nid] .insert (edges[nodes. size ()]. begin (), edges[nodes. size ()]. end () );
352
+ edges.insert (nid );
344
353
edges.erase (nodes.size ());
345
354
}
346
355
{
@@ -378,7 +387,7 @@ void taint_propagation_chainst::erase_dead_branches()
378
387
continue ;
379
388
fwd_reachable.insert (nid);
380
389
for (const auto &fns_nid : get_successors_map ().at (nid))
381
- work.push_back (fns_nid. first );
390
+ work.push_back (fns_nid);
382
391
}
383
392
}
384
393
// Use BFS to find all nodes backward-reachable from sinks.
@@ -514,15 +523,7 @@ std::ostream &to_dot(
514
523
ostr << " " << nid << " -> " << chains.get_nodes ().size ()+1U << " ;\n " ;
515
524
for (const auto &nid_edge : chains.get_successors_map ())
516
525
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 " ;
526
527
527
528
ostr << " }\n " ;
528
529
return ostr;
0 commit comments