Skip to content

Commit 33dedd4

Browse files
authored
Merge pull request #182 from bcaller/simplifydefinitions
Simplify trigger file for sink argument propagation
2 parents 79d39d8 + 23c186f commit 33dedd4

File tree

4 files changed

+33
-36
lines changed

4 files changed

+33
-36
lines changed

pyt/vulnerabilities/trigger_definitions_parser.py

+16-11
Original file line numberDiff line numberDiff line change
@@ -16,33 +16,38 @@
1616
class Sink:
1717
def __init__(
1818
self, trigger, *,
19-
unlisted_args_propagate=True, unlisted_kwargs_propagate=True,
20-
arg_list=None, kwarg_list=None,
21-
sanitisers=None
19+
unlisted_args_propagate=True,
20+
arg_dict=None,
21+
sanitisers=None,
2222
):
2323
self._trigger = trigger
2424
self.sanitisers = sanitisers or []
2525
self.arg_list_propagates = not unlisted_args_propagate
26-
self.kwarg_list_propagates = not unlisted_kwargs_propagate
2726

2827
if trigger[-1] != '(':
29-
if self.arg_list_propagates or self.kwarg_list_propagates or arg_list or kwarg_list:
28+
if self.arg_list_propagates or arg_dict:
3029
raise ValueError("Propagation options specified, but trigger word isn't a function call")
3130

32-
self.arg_list = set(arg_list or ())
33-
self.kwarg_list = set(kwarg_list or ())
31+
arg_dict = {} if arg_dict is None else arg_dict
32+
self.arg_position_to_kwarg = {
33+
position: name for name, position in arg_dict.items() if position is not None
34+
}
35+
self.kwarg_list = set(arg_dict.keys())
3436

3537
def arg_propagates(self, index):
36-
in_list = index in self.arg_list
37-
return self.arg_list_propagates == in_list
38+
kwarg = self.get_kwarg_from_position(index)
39+
return self.kwarg_propagates(kwarg)
3840

3941
def kwarg_propagates(self, keyword):
4042
in_list = keyword in self.kwarg_list
41-
return self.kwarg_list_propagates == in_list
43+
return self.arg_list_propagates == in_list
44+
45+
def get_kwarg_from_position(self, index):
46+
return self.arg_position_to_kwarg.get(index)
4247

4348
@property
4449
def all_arguments_propagate_taint(self):
45-
if self.arg_list or self.kwarg_list:
50+
if self.kwarg_list:
4651
return False
4752
return True
4853

pyt/vulnerabilities/vulnerabilities.py

+9-11
Original file line numberDiff line numberDiff line change
@@ -243,29 +243,27 @@ def get_sink_args(cfg_node):
243243
def get_sink_args_which_propagate(sink, ast_node):
244244
sink_args_with_positions = CallVisitor.get_call_visit_results(sink.trigger.call, ast_node)
245245
sink_args = []
246+
kwargs_present = set()
246247

247248
for i, vars in enumerate(sink_args_with_positions.args):
248-
if sink.trigger.arg_propagates(i):
249+
kwarg = sink.trigger.get_kwarg_from_position(i)
250+
if kwarg:
251+
kwargs_present.add(kwarg)
252+
if sink.trigger.kwarg_propagates(kwarg):
249253
sink_args.extend(vars)
250254

251-
if (
252-
# Either any unspecified arg propagates
253-
not sink.trigger.arg_list_propagates or
254-
# or there are some propagating args which weren't passed positionally
255-
any(1 for position in sink.trigger.arg_list if position >= len(sink_args_with_positions.args))
256-
):
257-
sink_args.extend(sink_args_with_positions.unknown_args)
258-
259255
for keyword, vars in sink_args_with_positions.kwargs.items():
256+
kwargs_present.add(keyword)
260257
if sink.trigger.kwarg_propagates(keyword):
261258
sink_args.extend(vars)
262259

263260
if (
264261
# Either any unspecified kwarg propagates
265-
not sink.trigger.kwarg_list_propagates or
262+
not sink.trigger.arg_list_propagates or
266263
# or there are some propagating kwargs which have not been passed by keyword
267-
sink.trigger.kwarg_list - set(sink_args_with_positions.kwargs.keys())
264+
sink.trigger.kwarg_list - kwargs_present
268265
):
266+
sink_args.extend(sink_args_with_positions.unknown_args)
269267
sink_args.extend(sink_args_with_positions.unknown_kwargs)
270268

271269
return sink_args

pyt/vulnerability_definitions/test_positions.pyt

+7-14
Original file line numberDiff line numberDiff line change
@@ -7,22 +7,15 @@
77
"normal(": {},
88
"execute(": {
99
"unlisted_args_propagate": false,
10-
"arg_list": [
11-
0
12-
],
13-
"unlisted_kwargs_propagate": false,
14-
"kwarg_list": [
15-
"text"
16-
]
10+
"arg_dict": {
11+
"text": 0
12+
}
1713
},
1814
"run(": {
19-
"kwarg_list": [
20-
"non_propagating"
21-
],
22-
"arg_list": [
23-
2,
24-
3
25-
]
15+
"arg_dict": {
16+
"non_propagating": 2,
17+
"something_else": 3
18+
}
2619
}
2720
}
2821
}

tests/vulnerabilities/vulnerabilities_test.py

+1
Original file line numberDiff line numberDiff line change
@@ -589,6 +589,7 @@ def check(fixture, vulnerable):
589589
'execute(x, name=TAINT)',
590590
'execute(x, *TAINT)',
591591
'execute(text=x, **TAINT)',
592+
'execute(x, **TAINT)',
592593
'dont_run(TAINT)',
593594
)
594595
vuln_fixtures = (

0 commit comments

Comments
 (0)