@@ -107,10 +107,13 @@ taint_instrumentation_propst::taint_instrumentation_propst(
107
107
const taint_programt &program,
108
108
const taint_function_idt &_root,
109
109
const std::set<taint_function_idt> &in_functions,
110
- const std::set<taint_function_idt> &in_suppressed)
110
+ const std::set<taint_function_idt> &in_suppressed,
111
+ const bool use_data_flow_insensitive_instrumentation)
111
112
: root(_root)
112
113
, functions(in_functions)
113
114
, suppressed(in_suppressed)
115
+ , use_data_flow_insensitive_version(
116
+ use_data_flow_insensitive_instrumentation)
114
117
{
115
118
// First we compute "valid" nodes of the propagation chaint w.r.t. the root
116
119
// function. We find these nodes by 2 BFSs: one from sources and one from
@@ -141,7 +144,8 @@ taint_instrumentation_propst::taint_instrumentation_propst(
141
144
location_props.push_back (chains.get_nodes ().at (nid));
142
145
}
143
146
144
- build_map_from_typenames_to_tokennames (chains, program);
147
+ if (!use_data_flow_insensitive_instrumentation)
148
+ build_map_from_typenames_to_tokennames (chains, program);
145
149
}
146
150
147
151
@@ -219,7 +223,8 @@ void taint_instrumentation_propst::build_map_from_typenames_to_tokennames(
219
223
void taint_build_instrumentation_props (
220
224
const taint_propagation_chainst &chains,
221
225
const taint_programt &program,
222
- std::vector<taint_instrumentation_propst> &output)
226
+ std::vector<taint_instrumentation_propst> &output,
227
+ const bool use_data_flow_insensitive_instrumentation)
223
228
{
224
229
// First we collect all functions mentioned in the graph of chains.
225
230
std::set<irep_idt> functions;
@@ -257,49 +262,54 @@ void taint_build_instrumentation_props(
257
262
// First we called all callees including those which should be suppressed.
258
263
find_direct_or_indirect_callees_of_function (
259
264
program.get_call_graph (), root, callees);
260
- // Now we compute suppressed functions and erase them from the callees
261
- // computed above. We do so in 3 steps.
262
- // Step 1: We collect functions which definitelly should be suppressed.
263
- // I.e. those corrensponding to applications of transition rules.
264
- for (const auto &node : chains.get_nodes ())
265
+
266
+ if (use_data_flow_insensitive_instrumentation)
265
267
{
266
- if (functions.count (node.get_function_id ())!=0UL )
268
+ // Now we compute suppressed functions and erase them from the callees
269
+ // computed above. We do so in 3 steps.
270
+ // Step 1: We collect functions which definitelly should be suppressed
271
+ // (those corrensponding to applications of transition rules.)
272
+ for (const auto &node : chains.get_nodes ())
267
273
{
268
- goto_programt::instructiont const & I=*node.get_instruction_id ();
269
- assert (I.type ==FUNCTION_CALL);
270
- assert (to_code_function_call (I.code ).function ().id ()==ID_symbol);
271
- const std::string full_function_name=as_string (to_symbol_expr (
272
- to_code_function_call (I.code ).function ()).get_identifier ());
273
- if (callees.count (full_function_name)!=0UL &&
274
- program.get_functions ().function_map .at (full_function_name)
275
- .body_available ())
274
+ if (functions.count (node.get_function_id ())!=0UL )
276
275
{
277
- suppressed.insert (full_function_name);
276
+ goto_programt::instructiont const & I=*node.get_instruction_id ();
277
+ INVARIANT (I.type ==FUNCTION_CALL, " " );
278
+ INVARIANT (to_code_function_call (I.code ).function ().id ()==ID_symbol,
279
+ " It must be a call via function identifier." );
280
+ const std::string full_function_name=as_string (to_symbol_expr (
281
+ to_code_function_call (I.code ).function ()).get_identifier ());
282
+ if (callees.count (full_function_name)!=0UL &&
283
+ program.get_functions ().function_map .at (full_function_name)
284
+ .body_available ())
285
+ {
286
+ suppressed.insert (full_function_name);
287
+ }
278
288
}
279
289
}
280
- }
281
- // Step 2: We collect a potentially suppressed function into a temporary
282
- // collection "suppressions". These function are all those
283
- // call-graph reachable from functions collected in the step 1.
284
- std::unordered_set<irep_idt, dstring_hash> suppressions;
285
- for (const auto &fn : suppressed)
286
- find_direct_or_indirect_callees_of_function (
287
- program.get_call_graph (), fn, suppressions);
288
- // Step 3: We copy from "suppressions" to "suppressed" each function
289
- // reachable from the root without passing through any function
290
- // collected in the step 1.
291
- while (!suppressions.empty ())
292
- {
293
- std::unordered_set<irep_idt, dstring_hash> ignored_functions (
294
- suppressed.cbegin (), suppressed.cend ());
295
- if (!exists_direct_or_indirect_call (
296
- program.get_call_graph (), root, *suppressions.cbegin (),
297
- ignored_functions))
290
+ // Step 2: We collect a potentially suppressed function into a temporary
291
+ // collection "suppressions". These function are all those
292
+ // call-graph reachable from functions collected in the step 1.
293
+ std::unordered_set<irep_idt, dstring_hash> suppressions;
294
+ for (const auto &fn : suppressed)
295
+ find_direct_or_indirect_callees_of_function (
296
+ program.get_call_graph (), fn, suppressions);
297
+ // Step 3: We copy from "suppressions" to "suppressed" each function
298
+ // reachable from the root without passing through any function
299
+ // collected in the step 1.
300
+ while (!suppressions.empty ())
298
301
{
299
- suppressed.insert (as_string (*suppressions.cbegin ()));
300
- callees.erase (*suppressions.cbegin ());
302
+ std::unordered_set<irep_idt, dstring_hash> ignored_functions (
303
+ suppressed.cbegin (), suppressed.cend ());
304
+ if (!exists_direct_or_indirect_call (
305
+ program.get_call_graph (), root, *suppressions.cbegin (),
306
+ ignored_functions))
307
+ {
308
+ suppressed.insert (as_string (*suppressions.cbegin ()));
309
+ callees.erase (*suppressions.cbegin ());
310
+ }
311
+ suppressions.erase (suppressions.cbegin ());
301
312
}
302
- suppressions.erase (suppressions.cbegin ());
303
313
}
304
314
}
305
315
// We are only interested in callees with body defined (it makes no sense
@@ -319,7 +329,8 @@ void taint_build_instrumentation_props(
319
329
program,
320
330
as_string (root),
321
331
available_functions,
322
- suppressed
332
+ suppressed,
333
+ use_data_flow_insensitive_instrumentation
323
334
};
324
335
if (!props.get_sources ().empty () && !props.get_sinks ().empty ())
325
336
output.push_back (props);
@@ -328,6 +339,8 @@ void taint_build_instrumentation_props(
328
339
329
340
void dump_as_json (const taint_instrumentation_propst &props, json_objectt &out)
330
341
{
342
+ out[" data_flow_insensitive_instrumentation_applied" ]=jsont::json_boolean (
343
+ props.data_flow_insensitive_version_applied ());
331
344
{
332
345
json_arrayt out_types;
333
346
for (const auto &elem : props.get_datatypes ())
0 commit comments