Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 8f2ef94

Browse files
committed
Python: Hook up keyword arguments
1 parent f5244aa commit 8f2ef94

8 files changed

Lines changed: 191 additions & 126 deletions

File tree

python/ql/src/experimental/dataflow/internal/DataFlowPrivate.qll

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,9 @@ abstract class DataFlowCallable extends TDataFlowCallable {
261261

262262
/** Gets the name of this callable. */
263263
abstract string getName();
264+
265+
/** Gets a callable value for this callable, if one exists. */
266+
abstract CallableValue getCallableValue();
264267
}
265268

266269
/** A class representing a callable value. */
@@ -278,6 +281,8 @@ class DataFlowCallableValue extends DataFlowCallable, TCallableValue {
278281
override NameNode getParameter(int n) { result = callable.getParameter(n) }
279282

280283
override string getName() { result = callable.getName() }
284+
285+
override CallableValue getCallableValue() { result = callable }
281286
}
282287

283288
/** A class representing the scope in which a `ModuleVariableNode` appears. */
@@ -295,6 +300,8 @@ class DataFlowModuleScope extends DataFlowCallable, TModule {
295300
override NameNode getParameter(int n) { none() }
296301

297302
override string getName() { result = mod.getName() }
303+
304+
override CallableValue getCallableValue() { none() }
298305
}
299306

300307
/**
@@ -322,14 +329,33 @@ abstract class DataFlowCall extends TDataFlowCall {
322329
/** Get the callable to which this call goes. */
323330
abstract DataFlowCallable getCallable();
324331

325-
/** Get the specified argument to this call. */
332+
/**
333+
* Gets the argument to this call that will be sent
334+
* to the `n`th parameter of the callable.
335+
*/
326336
abstract Node getArg(int n);
327337

328338
/** Get the control flow node representing this call. */
329339
abstract ControlFlowNode getNode();
330340

331341
/** Gets the enclosing callable of this call. */
332342
abstract DataFlowCallable getEnclosingCallable();
343+
344+
/** Gets the location of this dataflow call. */
345+
Location getLocation() { result = this.getNode().getLocation() }
346+
}
347+
348+
ControlFlowNode getArg(CallNode call, CallableValue callable, int n) {
349+
call = callable.getACall() and
350+
(
351+
result = call.getArg(n)
352+
or
353+
exists(Function f, string argName |
354+
f = callable.getScope() and
355+
f.getArgName(n) = argName and
356+
result = call.getArgByName(argName)
357+
)
358+
)
333359
}
334360

335361
/** Represents a call to a callable (currently only callable values). */
@@ -344,7 +370,7 @@ class CallNodeCall extends DataFlowCall, TCallNode {
344370

345371
override string toString() { result = call.toString() }
346372

347-
override Node getArg(int n) { result = TCfgNode(call.getArg(n)) }
373+
override Node getArg(int n) { result = TCfgNode(getArg(call, callable.getCallableValue(), n)) }
348374

349375
override ControlFlowNode getNode() { result = call }
350376

@@ -363,22 +389,19 @@ class ClassCall extends DataFlowCall, TClassCall {
363389
call = c.getACall()
364390
}
365391

392+
private CallableValue getCallableValue() { c.getScope().getInitMethod() = result.getScope() }
393+
366394
override string toString() { result = call.toString() }
367395

368396
override Node getArg(int n) {
369-
n > 0 and result = TCfgNode(call.getArg(n - 1))
397+
n > 0 and result = TCfgNode(getArg(call, this.getCallableValue(), n - 1))
370398
or
371399
n = 0 and result = TSyntheticPreUpdateNode(TCfgNode(call))
372400
}
373401

374402
override ControlFlowNode getNode() { result = call }
375403

376-
override DataFlowCallable getCallable() {
377-
exists(CallableValue callable |
378-
result = TCallableValue(callable) and
379-
c.getScope().getInitMethod() = callable.getScope()
380-
)
381-
}
404+
override DataFlowCallable getCallable() { result = TCallableValue(this.getCallableValue()) }
382405

383406
override DataFlowCallable getEnclosingCallable() { result.getScope() = call.getScope() }
384407
}

python/ql/test/experimental/dataflow/coverage/argumentPassing.py

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@
88
arg1 = "source1"
99
arg2 = "source2"
1010
arg3 = "source3"
11+
arg4 = "source4"
12+
arg5 = "source5"
13+
arg6 = "source6"
14+
arg7 = "source7"
1115

1216

1317
def SINK(x, expected=arg):
@@ -29,6 +33,22 @@ def SINK3(x):
2933
SINK(x, expected=arg3)
3034

3135

36+
def SINK4(x):
37+
SINK(x, expected=arg4)
38+
39+
40+
def SINK5(x):
41+
SINK(x, expected=arg5)
42+
43+
44+
def SINK6(x):
45+
SINK(x, expected=arg6)
46+
47+
48+
def SINK7(x):
49+
SINK(x, expected=arg7)
50+
51+
3252
def argument_passing(
3353
a,
3454
b,
@@ -43,12 +63,15 @@ def argument_passing(
4363
SINK1(a)
4464
SINK2(b)
4565
SINK3(c)
46-
SINK(f)
66+
SINK4(d)
67+
SINK5(e)
68+
SINK6(f)
69+
SINK7(g["g"])
4770

4871

49-
@expects(4)
72+
@expects(7)
5073
def test_argument_passing():
51-
argument_passing(arg1, arg2, arg3, f=arg)
74+
argument_passing(arg1, *(arg2, arg3, arg4), e=arg5, **{"f": arg6, "g": arg7})
5275

5376

5477
def with_pos_only(a, /, b):

python/ql/test/experimental/dataflow/coverage/argumentRouting1.expected

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,17 @@
1-
| argumentPassing.py:51:22:51:25 | ControlFlowNode for arg1 | argumentPassing.py:43:11:43:11 | ControlFlowNode for a |
2-
| argumentPassing.py:61:19:61:22 | ControlFlowNode for arg1 | argumentPassing.py:55:11:55:11 | ControlFlowNode for a |
3-
| argumentPassing.py:62:19:62:22 | ControlFlowNode for arg1 | argumentPassing.py:55:11:55:11 | ControlFlowNode for a |
4-
| argumentPassing.py:63:19:63:22 | ControlFlowNode for arg1 | argumentPassing.py:55:11:55:11 | ControlFlowNode for a |
5-
| argumentPassing.py:74:45:74:48 | ControlFlowNode for arg1 | argumentPassing.py:67:11:67:11 | ControlFlowNode for a |
6-
| argumentPassing.py:75:27:75:30 | ControlFlowNode for arg1 | argumentPassing.py:67:11:67:11 | ControlFlowNode for a |
7-
| argumentPassing.py:76:27:76:30 | ControlFlowNode for arg1 | argumentPassing.py:67:11:67:11 | ControlFlowNode for a |
8-
| argumentPassing.py:88:28:88:31 | ControlFlowNode for arg1 | argumentPassing.py:80:11:80:11 | ControlFlowNode for a |
1+
| argumentPassing.py:74:22:74:25 | ControlFlowNode for arg1 | argumentPassing.py:63:11:63:11 | ControlFlowNode for a |
2+
| argumentPassing.py:84:19:84:22 | ControlFlowNode for arg1 | argumentPassing.py:78:11:78:11 | ControlFlowNode for a |
3+
| argumentPassing.py:85:19:85:22 | ControlFlowNode for arg1 | argumentPassing.py:78:11:78:11 | ControlFlowNode for a |
4+
| argumentPassing.py:86:19:86:22 | ControlFlowNode for arg1 | argumentPassing.py:78:11:78:11 | ControlFlowNode for a |
5+
| argumentPassing.py:97:45:97:48 | ControlFlowNode for arg1 | argumentPassing.py:90:11:90:11 | ControlFlowNode for a |
6+
| argumentPassing.py:98:27:98:30 | ControlFlowNode for arg1 | argumentPassing.py:90:11:90:11 | ControlFlowNode for a |
7+
| argumentPassing.py:99:27:99:30 | ControlFlowNode for arg1 | argumentPassing.py:90:11:90:11 | ControlFlowNode for a |
8+
| argumentPassing.py:111:28:111:31 | ControlFlowNode for arg1 | argumentPassing.py:103:11:103:11 | ControlFlowNode for a |
9+
| argumentPassing.py:133:46:133:49 | ControlFlowNode for arg1 | argumentPassing.py:118:11:118:13 | ControlFlowNode for foo |
10+
| argumentPassing.py:141:14:141:17 | ControlFlowNode for arg1 | argumentPassing.py:139:15:139:15 | ControlFlowNode for a |
11+
| argumentPassing.py:148:19:148:22 | ControlFlowNode for arg1 | argumentPassing.py:146:15:146:15 | ControlFlowNode for a |
12+
| argumentPassing.py:163:13:163:16 | ControlFlowNode for arg1 | argumentPassing.py:161:15:161:15 | ControlFlowNode for a |
13+
| argumentPassing.py:170:16:170:19 | ControlFlowNode for arg1 | argumentPassing.py:168:15:168:15 | ControlFlowNode for a |
14+
| argumentPassing.py:177:15:177:18 | ControlFlowNode for arg1 | argumentPassing.py:175:15:175:15 | ControlFlowNode for a |
915
| classes.py:563:5:563:16 | SSA variable with_getitem | classes.py:557:15:557:18 | ControlFlowNode for self |
1016
| classes.py:578:5:578:16 | SSA variable with_setitem | classes.py:573:15:573:18 | ControlFlowNode for self |
1117
| classes.py:593:5:593:16 | SSA variable with_delitem | classes.py:588:15:588:18 | ControlFlowNode for self |

python/ql/test/experimental/dataflow/coverage/argumentRouting2.expected

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1-
| argumentPassing.py:51:28:51:31 | ControlFlowNode for arg2 | argumentPassing.py:44:11:44:11 | ControlFlowNode for b |
2-
| argumentPassing.py:61:25:61:28 | ControlFlowNode for arg2 | argumentPassing.py:56:11:56:11 | ControlFlowNode for b |
1+
| argumentPassing.py:84:25:84:28 | ControlFlowNode for arg2 | argumentPassing.py:79:11:79:11 | ControlFlowNode for b |
2+
| argumentPassing.py:85:27:85:30 | ControlFlowNode for arg2 | argumentPassing.py:79:11:79:11 | ControlFlowNode for b |
3+
| argumentPassing.py:97:29:97:32 | ControlFlowNode for arg2 | argumentPassing.py:91:11:91:11 | ControlFlowNode for b |
4+
| argumentPassing.py:112:30:112:33 | ControlFlowNode for arg2 | argumentPassing.py:104:11:104:11 | ControlFlowNode for b |
35
| classes.py:565:18:565:21 | ControlFlowNode for arg2 | classes.py:556:15:556:17 | ControlFlowNode for key |
46
| classes.py:581:18:581:21 | ControlFlowNode for arg2 | classes.py:572:15:572:17 | ControlFlowNode for key |
57
| classes.py:595:22:595:25 | ControlFlowNode for arg2 | classes.py:587:15:587:17 | ControlFlowNode for key |
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
| argumentPassing.py:51:34:51:37 | ControlFlowNode for arg3 | argumentPassing.py:45:11:45:11 | ControlFlowNode for c |
1+
| argumentPassing.py:97:37:97:40 | ControlFlowNode for arg3 | argumentPassing.py:92:11:92:11 | ControlFlowNode for c |
22
| classes.py:581:26:581:29 | ControlFlowNode for arg3 | classes.py:571:15:571:19 | ControlFlowNode for value |
Lines changed: 39 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,39 @@
1-
| classes.py:41:16:41:35 | ControlFlowNode for Attribute() | classes.py:41:16:41:35 | ControlFlowNode for Attribute() |
2-
| classes.py:58:17:58:27 | [pre objCreate] ControlFlowNode for With_init() | classes.py:52:18:52:21 | SSA variable self |
3-
| classes.py:264:9:264:24 | ControlFlowNode for set() | classes.py:264:9:264:24 | ControlFlowNode for set() |
4-
| classes.py:269:9:269:30 | ControlFlowNode for frozenset() | classes.py:269:9:269:30 | ControlFlowNode for frozenset() |
5-
| classes.py:274:9:274:28 | ControlFlowNode for dict() | classes.py:274:9:274:28 | ControlFlowNode for dict() |
6-
| classes.py:454:29:454:52 | ControlFlowNode for dict() | classes.py:454:29:454:52 | ControlFlowNode for dict() |
7-
| classes.py:622:5:622:16 | ControlFlowNode for with_getitem | classes.py:612:21:612:24 | SSA variable self |
8-
| classes.py:622:18:622:21 | ControlFlowNode for arg2 | classes.py:612:27:612:29 | SSA variable key |
9-
| classes.py:640:5:640:16 | ControlFlowNode for with_setitem | classes.py:629:21:629:24 | SSA variable self |
10-
| classes.py:640:18:640:21 | ControlFlowNode for arg2 | classes.py:629:27:629:29 | SSA variable key |
11-
| classes.py:640:26:640:29 | ControlFlowNode for arg3 | classes.py:629:32:629:36 | SSA variable value |
12-
| classes.py:656:9:656:20 | ControlFlowNode for with_delitem | classes.py:647:21:647:24 | SSA variable self |
13-
| classes.py:656:22:656:25 | ControlFlowNode for arg2 | classes.py:647:27:647:29 | SSA variable key |
14-
| classes.py:683:16:683:28 | ControlFlowNode for Attribute() | classes.py:683:16:683:28 | ControlFlowNode for Attribute() |
15-
| classes.py:737:5:737:12 | ControlFlowNode for with_add | classes.py:727:17:727:20 | SSA variable self |
16-
| classes.py:737:16:737:19 | ControlFlowNode for arg2 | classes.py:727:23:727:27 | SSA variable other |
17-
| classes.py:754:5:754:12 | ControlFlowNode for with_sub | classes.py:744:17:744:20 | SSA variable self |
18-
| classes.py:754:16:754:19 | ControlFlowNode for arg2 | classes.py:744:23:744:27 | SSA variable other |
19-
| classes.py:771:5:771:12 | ControlFlowNode for with_mul | classes.py:761:17:761:20 | SSA variable self |
20-
| classes.py:771:16:771:19 | ControlFlowNode for arg2 | classes.py:761:23:761:27 | SSA variable other |
21-
| classes.py:788:5:788:15 | ControlFlowNode for with_matmul | classes.py:778:20:778:23 | SSA variable self |
22-
| classes.py:788:19:788:22 | ControlFlowNode for arg2 | classes.py:778:26:778:30 | SSA variable other |
23-
| classes.py:805:5:805:16 | ControlFlowNode for with_truediv | classes.py:795:21:795:24 | SSA variable self |
24-
| classes.py:805:20:805:23 | ControlFlowNode for arg2 | classes.py:795:27:795:31 | SSA variable other |
25-
| classes.py:822:5:822:17 | ControlFlowNode for with_floordiv | classes.py:812:22:812:25 | SSA variable self |
26-
| classes.py:822:22:822:25 | ControlFlowNode for arg2 | classes.py:812:28:812:32 | SSA variable other |
27-
| classes.py:839:5:839:12 | ControlFlowNode for with_mod | classes.py:829:17:829:20 | SSA variable self |
28-
| classes.py:839:16:839:19 | ControlFlowNode for arg2 | classes.py:829:23:829:27 | SSA variable other |
29-
| classes.py:879:5:879:12 | ControlFlowNode for with_pow | classes.py:863:17:863:20 | SSA variable self |
30-
| classes.py:879:17:879:20 | ControlFlowNode for arg2 | classes.py:863:23:863:27 | SSA variable other |
31-
| classes.py:896:5:896:15 | ControlFlowNode for with_lshift | classes.py:886:20:886:23 | SSA variable self |
32-
| classes.py:896:20:896:23 | ControlFlowNode for arg2 | classes.py:886:26:886:30 | SSA variable other |
33-
| classes.py:913:5:913:15 | ControlFlowNode for with_rshift | classes.py:903:20:903:23 | SSA variable self |
34-
| classes.py:913:20:913:23 | ControlFlowNode for arg2 | classes.py:903:26:903:30 | SSA variable other |
35-
| classes.py:930:5:930:12 | ControlFlowNode for with_and | classes.py:920:17:920:20 | SSA variable self |
36-
| classes.py:930:16:930:19 | ControlFlowNode for arg2 | classes.py:920:23:920:27 | SSA variable other |
37-
| classes.py:947:5:947:12 | ControlFlowNode for with_xor | classes.py:937:17:937:20 | SSA variable self |
38-
| classes.py:947:16:947:19 | ControlFlowNode for arg2 | classes.py:937:23:937:27 | SSA variable other |
39-
| classes.py:964:5:964:11 | ControlFlowNode for with_or | classes.py:954:16:954:19 | SSA variable self |
40-
| classes.py:964:15:964:18 | ControlFlowNode for arg2 | classes.py:954:22:954:26 | SSA variable other |
1+
| classes.py:45:16:45:35 | ControlFlowNode for Attribute() | classes.py:45:16:45:35 | ControlFlowNode for Attribute() |
2+
| classes.py:60:17:60:27 | [pre objCreate] ControlFlowNode for With_init() | classes.py:54:18:54:21 | SSA variable self |
3+
| classes.py:242:9:242:24 | ControlFlowNode for set() | classes.py:242:9:242:24 | ControlFlowNode for set() |
4+
| classes.py:247:9:247:30 | ControlFlowNode for frozenset() | classes.py:247:9:247:30 | ControlFlowNode for frozenset() |
5+
| classes.py:252:9:252:28 | ControlFlowNode for dict() | classes.py:252:9:252:28 | ControlFlowNode for dict() |
6+
| classes.py:565:5:565:16 | ControlFlowNode for with_getitem | classes.py:555:21:555:24 | SSA variable self |
7+
| classes.py:565:18:565:21 | ControlFlowNode for arg2 | classes.py:555:27:555:29 | SSA variable key |
8+
| classes.py:581:5:581:16 | ControlFlowNode for with_setitem | classes.py:570:21:570:24 | SSA variable self |
9+
| classes.py:581:18:581:21 | ControlFlowNode for arg2 | classes.py:570:27:570:29 | SSA variable key |
10+
| classes.py:581:26:581:29 | ControlFlowNode for arg3 | classes.py:570:32:570:36 | SSA variable value |
11+
| classes.py:595:9:595:20 | ControlFlowNode for with_delitem | classes.py:586:21:586:24 | SSA variable self |
12+
| classes.py:595:22:595:25 | ControlFlowNode for arg2 | classes.py:586:27:586:29 | SSA variable key |
13+
| classes.py:618:16:618:28 | ControlFlowNode for Attribute() | classes.py:618:16:618:28 | ControlFlowNode for Attribute() |
14+
| classes.py:667:5:667:12 | ControlFlowNode for with_add | classes.py:657:17:657:20 | SSA variable self |
15+
| classes.py:667:16:667:19 | ControlFlowNode for arg2 | classes.py:657:23:657:27 | SSA variable other |
16+
| classes.py:682:5:682:12 | ControlFlowNode for with_sub | classes.py:672:17:672:20 | SSA variable self |
17+
| classes.py:682:16:682:19 | ControlFlowNode for arg2 | classes.py:672:23:672:27 | SSA variable other |
18+
| classes.py:697:5:697:12 | ControlFlowNode for with_mul | classes.py:687:17:687:20 | SSA variable self |
19+
| classes.py:697:16:697:19 | ControlFlowNode for arg2 | classes.py:687:23:687:27 | SSA variable other |
20+
| classes.py:712:5:712:15 | ControlFlowNode for with_matmul | classes.py:702:20:702:23 | SSA variable self |
21+
| classes.py:712:19:712:22 | ControlFlowNode for arg2 | classes.py:702:26:702:30 | SSA variable other |
22+
| classes.py:727:5:727:16 | ControlFlowNode for with_truediv | classes.py:717:21:717:24 | SSA variable self |
23+
| classes.py:727:20:727:23 | ControlFlowNode for arg2 | classes.py:717:27:717:31 | SSA variable other |
24+
| classes.py:742:5:742:17 | ControlFlowNode for with_floordiv | classes.py:732:22:732:25 | SSA variable self |
25+
| classes.py:742:22:742:25 | ControlFlowNode for arg2 | classes.py:732:28:732:32 | SSA variable other |
26+
| classes.py:757:5:757:12 | ControlFlowNode for with_mod | classes.py:747:17:747:20 | SSA variable self |
27+
| classes.py:757:16:757:19 | ControlFlowNode for arg2 | classes.py:747:23:747:27 | SSA variable other |
28+
| classes.py:793:5:793:12 | ControlFlowNode for with_pow | classes.py:777:17:777:20 | SSA variable self |
29+
| classes.py:793:17:793:20 | ControlFlowNode for arg2 | classes.py:777:23:777:27 | SSA variable other |
30+
| classes.py:808:5:808:15 | ControlFlowNode for with_lshift | classes.py:798:20:798:23 | SSA variable self |
31+
| classes.py:808:20:808:23 | ControlFlowNode for arg2 | classes.py:798:26:798:30 | SSA variable other |
32+
| classes.py:823:5:823:15 | ControlFlowNode for with_rshift | classes.py:813:20:813:23 | SSA variable self |
33+
| classes.py:823:20:823:23 | ControlFlowNode for arg2 | classes.py:813:26:813:30 | SSA variable other |
34+
| classes.py:838:5:838:12 | ControlFlowNode for with_and | classes.py:828:17:828:20 | SSA variable self |
35+
| classes.py:838:16:838:19 | ControlFlowNode for arg2 | classes.py:828:23:828:27 | SSA variable other |
36+
| classes.py:853:5:853:12 | ControlFlowNode for with_xor | classes.py:843:17:843:20 | SSA variable self |
37+
| classes.py:853:16:853:19 | ControlFlowNode for arg2 | classes.py:843:23:843:27 | SSA variable other |
38+
| classes.py:868:5:868:11 | ControlFlowNode for with_or | classes.py:858:16:858:19 | SSA variable self |
39+
| classes.py:868:15:868:18 | ControlFlowNode for arg2 | classes.py:858:22:858:26 | SSA variable other |

0 commit comments

Comments
 (0)