Skip to content

Commit 4b39446

Browse files
author
Daniel Kroening
authored
Merge pull request #1518 from diffblue/taint-for-C
Taint for C
2 parents 25e18c0 + 3dd7f6c commit 4b39446

File tree

15 files changed

+171
-27
lines changed

15 files changed

+171
-27
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#include <stdlib.h>
2+
3+
void my_f(void *) { }
4+
void my_h(void *) { }
5+
void *my_g(void) { return malloc(1); }
6+
7+
void my_function()
8+
{
9+
void *o;
10+
11+
my_f(o); // T1 source
12+
my_h(o); // T1,T2 sink
13+
14+
o=my_g(); // T2 source
15+
my_h(o); // T1,T2 sink
16+
}
Binary file not shown.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
[
2+
{ "id": "my_f", "kind": "source", "where": "parameter1", "taint": "T1", "function": "my_f" },
3+
{ "id": "my_g", "kind": "source", "where": "return_value", "taint": "T2", "function": "my_g" },
4+
{ "id": "my_h1", "kind": "sink", "where": "parameter1", "taint": "T1", "function": "my_h", "message": "There is a T1 flow" },
5+
{ "id": "my_h2", "kind": "sink", "where": "parameter1", "taint": "T2", "function": "my_h", "message": "There is a T2 flow" }
6+
]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
CORE
2+
main.o
3+
--taint taint.json
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^file main.c line 12( function .*)?: There is a T1 flow \(taint rule my_h1\)$
7+
^file main.c line 15( function .*)?: There is a T2 flow \(taint rule my_h2\)$
8+
--
9+
^file main.c line 12( function .*)?: There is a T2 flow \(.*\)$
10+
^file main.c line 15( function .*)?: There is a T1 flow \(.*\)$
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
void my_f(void *) { }
2+
void my_h(void *) { }
3+
4+
void my_function()
5+
{
6+
void *o1;
7+
my_f(o1); // T1 source
8+
9+
void *o2;
10+
o2=o1;
11+
12+
my_h(o2); // T1 sink
13+
}
Binary file not shown.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
[
2+
{ "id": "my_f", "kind": "source", "where": "parameter1", "taint": "T1", "function": "my_f" },
3+
{ "id": "my_h", "kind": "sink", "where": "parameter1", "taint": "T1", "function": "my_h", "message": "There is a T1 flow" }
4+
]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
CORE
2+
main.o
3+
--taint taint.json
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^file main.c line 12( function .*)?: There is a T1 flow \(taint rule my_h\)$
7+
--
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#include <stdlib.h>
2+
3+
void my_f(void *) { }
4+
void my_h(void *) { }
5+
6+
void my_function()
7+
{
8+
struct some_struct
9+
{
10+
void *data;
11+
} whatnot;
12+
13+
my_f(whatnot.data); // T1 source
14+
my_h(whatnot.data); // T1 sink
15+
16+
// via a copy
17+
void *o=whatnot.data;
18+
my_h(o); // T1 sink
19+
20+
// copy entire struct
21+
struct some_struct whatelse;
22+
whatelse=whatnot;
23+
my_h(whatelse.data); // T1 sink
24+
}
Binary file not shown.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
[
2+
{ "id": "my_f", "kind": "source", "where": "parameter1", "taint": "T1", "function": "my_f" },
3+
{ "id": "my_h", "kind": "sink", "where": "parameter1", "taint": "T1", "function": "my_h", "message": "There is a T1 flow" }
4+
]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
CORE
2+
main.o
3+
--taint taint.json
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^file main.c line 14( function .*)?: There is a T1 flow \(taint rule my_h\)$
7+
^file main.c line 18( function .*)?: There is a T1 flow \(taint rule my_h\)$
8+
^file main.c line 23( function .*)?: There is a T1 flow \(taint rule my_h\)$
9+
--

src/analyses/custom_bitvector_analysis.cpp

+57-19
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,19 @@ irep_idt custom_bitvector_domaint::object2id(const exprt &src)
8484
return '*'+id2string(op_id);
8585
}
8686
}
87+
else if(src.id()==ID_member)
88+
{
89+
const auto &m=to_member_expr(src);
90+
const exprt &op=m.compound();
91+
92+
irep_idt op_id=object2id(op);
93+
94+
if(op_id.empty())
95+
return irep_idt();
96+
else
97+
return id2string(op_id)+'.'+
98+
id2string(m.get_component_name());
99+
}
87100
else if(src.id()==ID_typecast)
88101
return object2id(to_typecast_expr(src).op());
89102
else
@@ -209,6 +222,49 @@ std::set<exprt> custom_bitvector_analysist::aliases(
209222
return std::set<exprt>();
210223
}
211224

225+
void custom_bitvector_domaint::assign_struct_rec(
226+
locationt from,
227+
const exprt &lhs,
228+
const exprt &rhs,
229+
custom_bitvector_analysist &cba,
230+
const namespacet &ns)
231+
{
232+
if(ns.follow(lhs.type()).id()==ID_struct)
233+
{
234+
const struct_typet &struct_type=
235+
to_struct_type(ns.follow(lhs.type()));
236+
237+
// assign member-by-member
238+
for(const auto &c : struct_type.components())
239+
{
240+
member_exprt lhs_member(lhs, c),
241+
rhs_member(rhs, c);
242+
assign_struct_rec(from, lhs_member, rhs_member, cba, ns);
243+
}
244+
}
245+
else
246+
{
247+
// may alias other stuff
248+
std::set<exprt> lhs_set=cba.aliases(lhs, from);
249+
250+
vectorst rhs_vectors=get_rhs(rhs);
251+
252+
for(const auto &lhs_alias : lhs_set)
253+
{
254+
assign_lhs(lhs_alias, rhs_vectors);
255+
}
256+
257+
// is it a pointer?
258+
if(lhs.type().id()==ID_pointer)
259+
{
260+
dereference_exprt lhs_deref(lhs);
261+
dereference_exprt rhs_deref(rhs);
262+
vectorst rhs_vectors=get_rhs(rhs_deref);
263+
assign_lhs(lhs_deref, rhs_vectors);
264+
}
265+
}
266+
}
267+
212268
void custom_bitvector_domaint::transform(
213269
locationt from,
214270
locationt to,
@@ -226,25 +282,7 @@ void custom_bitvector_domaint::transform(
226282
case ASSIGN:
227283
{
228284
const code_assignt &code_assign=to_code_assign(instruction.code);
229-
230-
// may alias other stuff
231-
std::set<exprt> lhs_set=cba.aliases(code_assign.lhs(), from);
232-
233-
vectorst rhs_vectors=get_rhs(code_assign.rhs());
234-
235-
for(const auto &lhs : lhs_set)
236-
{
237-
assign_lhs(lhs, rhs_vectors);
238-
}
239-
240-
// is it a pointer?
241-
if(code_assign.lhs().type().id()==ID_pointer)
242-
{
243-
dereference_exprt lhs_deref(code_assign.lhs());
244-
dereference_exprt rhs_deref(code_assign.rhs());
245-
vectorst rhs_vectors=get_rhs(rhs_deref);
246-
assign_lhs(lhs_deref, rhs_vectors);
247-
}
285+
assign_struct_rec(from, code_assign.lhs(), code_assign.rhs(), cba, ns);
248286
}
249287
break;
250288

src/analyses/custom_bitvector_analysis.h

+7
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,13 @@ class custom_bitvector_domaint:public ai_domain_baset
9696

9797
bitst may_bits, must_bits;
9898

99+
void assign_struct_rec(
100+
locationt from,
101+
const exprt &lhs,
102+
const exprt &rhs,
103+
custom_bitvector_analysist &,
104+
const namespacet &);
105+
99106
void assign_lhs(const exprt &, const vectorst &);
100107
void assign_lhs(const irep_idt &, const vectorst &);
101108
vectorst get_rhs(const exprt &) const;

src/goto-analyzer/taint_analysis.cpp

+14-8
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ void taint_analysist::instrument(
6767
{
6868
const goto_programt::instructiont &instruction=*it;
6969

70-
goto_programt tmp;
70+
goto_programt insert_before, insert_after;
7171

7272
switch(instruction.type)
7373
{
@@ -164,15 +164,15 @@ void taint_analysist::instrument(
164164
code_set_may.op0()=where;
165165
code_set_may.op1()=
166166
address_of_exprt(string_constantt(rule.taint));
167-
goto_programt::targett t=tmp.add_instruction();
167+
goto_programt::targett t=insert_after.add_instruction();
168168
t->make_other(code_set_may);
169169
t->source_location=instruction.source_location;
170170
}
171171
break;
172172

173173
case taint_parse_treet::rulet::SINK:
174174
{
175-
goto_programt::targett t=tmp.add_instruction();
175+
goto_programt::targett t=insert_before.add_instruction();
176176
binary_predicate_exprt get_may("get_may");
177177
get_may.op0()=where;
178178
get_may.op1()=address_of_exprt(string_constantt(rule.taint));
@@ -191,7 +191,7 @@ void taint_analysist::instrument(
191191
code_clear_may.op0()=where;
192192
code_clear_may.op1()=
193193
address_of_exprt(string_constantt(rule.taint));
194-
goto_programt::targett t=tmp.add_instruction();
194+
goto_programt::targett t=insert_after.add_instruction();
195195
t->make_other(code_clear_may);
196196
t->source_location=instruction.source_location;
197197
}
@@ -208,11 +208,17 @@ void taint_analysist::instrument(
208208
}
209209
}
210210

211-
if(!tmp.empty())
211+
if(!insert_before.empty())
212212
{
213-
goto_programt::targett next=it;
214-
next++;
215-
goto_function.body.destructive_insert(next, tmp);
213+
goto_function.body.insert_before_swap(it, insert_before);
214+
// advance until we get back to the call
215+
while(!it->is_function_call()) ++it;
216+
}
217+
218+
if(!insert_after.empty())
219+
{
220+
goto_function.body.destructive_insert(
221+
std::next(it), insert_after);
216222
}
217223
}
218224
}

0 commit comments

Comments
 (0)