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

Skip to content

Commit 76c43b4

Browse files
committed
Python points-to: Improve handling of attributes.
1 parent 992ee2f commit 76c43b4

6 files changed

Lines changed: 63 additions & 26 deletions

File tree

python/ql/src/semmle/python/objects/ObjectInternal.qll

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -402,6 +402,10 @@ module ObjectInternal {
402402
result = TBuiltinClassObject(Builtin::special("StaticMethod"))
403403
}
404404

405+
ObjectInternal boundMethod() {
406+
result = TBuiltinClassObject(Builtin::special("MethodType"))
407+
}
408+
405409
ObjectInternal moduleType() {
406410
result = TBuiltinClassObject(Builtin::special("ModuleType"))
407411
}

python/ql/src/semmle/python/objects/TObject.qll

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,14 @@ predicate call2(CallNode call, ControlFlowNode func, ControlFlowNode arg0, Contr
232232
arg1 = call.getArg(1)
233233
}
234234

235+
predicate call3(CallNode call, ControlFlowNode func, ControlFlowNode arg0, ControlFlowNode arg1, ControlFlowNode arg2) {
236+
not exists(call.getArg(3)) and
237+
func = call.getFunction() and
238+
arg0 = call.getArg(0) and
239+
arg1 = call.getArg(1) and
240+
arg2 = call.getArg(2)
241+
}
242+
235243
bindingset[self, function]
236244
predicate method_binding(AttrNode instantiation, ObjectInternal self, CallableObjectInternal function, PointsToContext context) {
237245
exists(ObjectInternal obj, string name |

python/ql/src/semmle/python/pointsto/Base.qll

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,7 @@ class ArgumentRefinement extends PyNodeRefinement {
378378

379379
ControlFlowNode getArgument() { result = argument }
380380

381+
CallNode getCall() { result = this.getDefiningNode() }
381382
}
382383

383384
/** Deletion of an attribute `del obj.attr`. */

python/ql/src/semmle/python/pointsto/PointsTo.qll

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -872,7 +872,7 @@ module InterProceduralPointsTo {
872872
)
873873
}
874874

875-
predicate selfMethodCall(MethodCallsiteRefinement def, PointsToContext caller, Function func, PointsToContext callee) {
875+
predicate selfMethodCall(SelfCallsiteRefinement def, PointsToContext caller, Function func, PointsToContext callee) {
876876
def.getInput().getSourceVariable().(Variable).isSelf() and
877877
exists(PythonFunctionObjectInternal method, CallNode call |
878878
method.getScope() = func and
@@ -1232,6 +1232,15 @@ module Expressions {
12321232
)
12331233
}
12341234

1235+
pragma [noinline]
1236+
predicate setattr_call(CallNode call, PointsToContext context, ControlFlowNode obj, string name, ObjectInternal val, ControlFlowNode origin) {
1237+
exists(ControlFlowNode arg1, ControlFlowNode arg2 |
1238+
call_to_setattr(call, context, obj, arg1, arg2) and
1239+
PointsToInternal::pointsTo(arg2, context, val, origin) and
1240+
PointsToInternal::pointsToString(arg1, context, name)
1241+
)
1242+
}
1243+
12351244
pragma[noinline]
12361245
private predicate call_to_getattr(ControlFlowNode call, PointsToContext context, ControlFlowNode arg0, ControlFlowNode arg1) {
12371246
exists(ControlFlowNode func |
@@ -1240,6 +1249,14 @@ module Expressions {
12401249
)
12411250
}
12421251

1252+
pragma[noinline]
1253+
private predicate call_to_setattr(ControlFlowNode call, PointsToContext context, ControlFlowNode arg0, ControlFlowNode arg1, ControlFlowNode arg2) {
1254+
exists(ControlFlowNode func |
1255+
call3(call, func, arg0, arg1, arg2) and
1256+
PointsToInternal::pointsTo(func, context, ObjectInternal::builtin("setattr"), _)
1257+
)
1258+
}
1259+
12431260
pragma [noinline]
12441261
private boolean otherComparisonEvaluatesTo(CompareNode comp, PointsToContext context, ControlFlowNode operand, ObjectInternal opvalue) {
12451262
exists(Cmpop op |
@@ -1935,6 +1952,7 @@ cached module Types {
19351952
module AttributePointsTo {
19361953

19371954
predicate pointsTo(AttrNode f, Context context, ObjectInternal value, ControlFlowNode origin) {
1955+
f.isLoad() and
19381956
exists(EssaVariable var, string name, CfgOrigin orig |
19391957
var.getASourceUse() = f.getObject(name) and
19401958
variableAttributePointsTo(var, context, name, value, orig) and
@@ -1961,6 +1979,8 @@ module AttributePointsTo {
19611979
selfParameterAttributePointsTo(def, context, name, value, origin)
19621980
or
19631981
selfMethodCallsitePointsTo(def, context, name, value, origin)
1982+
or
1983+
argumentRefinementPointsTo(def, context, name, value, origin)
19641984
}
19651985

19661986
pragma [noinline]
@@ -2002,22 +2022,41 @@ module AttributePointsTo {
20022022
}
20032023

20042024
private predicate selfParameterAttributePointsTo(ParameterDefinition def, PointsToContext context, string name, ObjectInternal value, CfgOrigin origin) {
2005-
exists(MethodCallsiteRefinement call, Function func, PointsToContext caller |
2025+
exists(SelfCallsiteRefinement call, Function func, PointsToContext caller |
20062026
InterProceduralPointsTo::selfMethodCall(call, caller, func, context) and
20072027
def.isSelf() and def.getScope() = func and
20082028
variableAttributePointsTo(call.getInput(), caller, name, value, origin)
20092029
)
20102030
}
20112031

20122032
/** Pass through for `self` for the implicit re-definition of `self` in `self.foo()`. */
2013-
private predicate selfMethodCallsitePointsTo(MethodCallsiteRefinement def, PointsToContext context, string name, ObjectInternal value, CfgOrigin origin) {
2033+
private predicate selfMethodCallsitePointsTo(SelfCallsiteRefinement def, PointsToContext context, string name, ObjectInternal value, CfgOrigin origin) {
20142034
/* The value of self remains the same, only the attributes may change */
20152035
exists(Function func, PointsToContext callee, EssaVariable exit_self |
20162036
InterProceduralPointsTo::selfMethodCall(def, context, func, callee) and
20172037
exit_self.getSourceVariable().(Variable).isSelf() and
20182038
exit_self.getScope() = func and
20192039
BaseFlow::reaches_exit(exit_self) and
2020-
variableAttributePointsTo(exit_self, context, name, value, origin)
2040+
variableAttributePointsTo(exit_self, callee, name, value, origin)
2041+
)
2042+
}
2043+
2044+
private predicate argumentRefinementPointsTo(ArgumentRefinement def, PointsToContext context, string name, ObjectInternal value, CfgOrigin origin) {
2045+
exists(ObjectInternal callable |
2046+
PointsToInternal::pointsTo(def.getCall().getFunction(), context, callable, _) and
2047+
callable != ObjectInternal::builtin("setattr")
2048+
) and
2049+
variableAttributePointsTo(def.getInput(), context, name, value, origin)
2050+
or
2051+
exists(string othername |
2052+
Expressions::setattr_call(def.getCall(), context, def.getInput().getASourceUse(), othername, _, _) and
2053+
not othername = name
2054+
) and
2055+
variableAttributePointsTo(def.getInput(), context, name, value, origin)
2056+
or
2057+
exists(ControlFlowNode orig |
2058+
Expressions::setattr_call(def.getCall(), context, def.getInput().getASourceUse(), name, value, orig) and
2059+
origin = CfgOrigin::fromCfgNode(orig)
20212060
)
20222061
}
20232062

python/ql/test/library-tests/PointsTo/new/SsaAttr.expected

Lines changed: 3 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@
22
| b_condition.py:43 | v2_3 | x | Pi(v2_2) [true] | int 1 | import |
33
| b_condition.py:47 | v2_4 | x | Pi(v2_2) [false] | int 1 | import |
44
| b_condition.py:47 | v2_5 | x | phi(v2_3, v2_4) | int 1 | import |
5+
| f_finally.py:3 | self_3 | _close | phi(self_1, self_2) | None | runtime |
56
| f_finally.py:3 | self_3 | _closed | phi(self_1, self_2) | bool True | runtime |
67
| f_finally.py:4 | self_1 | _closed | AttributeAssignment '_closed'(self_0) | bool True | runtime |
8+
| f_finally.py:10 | self_2 | _close | AttributeAssignment '_close'(self_1) | None | runtime |
79
| f_finally.py:10 | self_2 | _closed | AttributeAssignment '_close'(self_1) | bool True | runtime |
810
| g_class_init.py:6 | self_1 | y | SelfCallsiteRefinement(self_0) | int 2 | runtime |
911
| g_class_init.py:6 | self_1 | z | SelfCallsiteRefinement(self_0) | int 3 | runtime |
@@ -16,27 +18,10 @@
1618
| g_class_init.py:13 | self_0 | y | ParameterDefinition | int 2 | code/g_class_init.py:11 from code/g_class_init.py:6 from runtime |
1719
| g_class_init.py:14 | self_1 | y | AttributeAssignment 'z'(self_0) | int 2 | code/g_class_init.py:11 from code/g_class_init.py:6 from runtime |
1820
| g_class_init.py:14 | self_1 | z | AttributeAssignment 'z'(self_0) | int 3 | code/g_class_init.py:11 from code/g_class_init.py:6 from runtime |
19-
| g_class_init.py:16 | self_0 | x | ParameterDefinition | int 1 | runtime |
20-
| g_class_init.py:16 | self_0 | y | ParameterDefinition | int 2 | runtime |
21-
| g_class_init.py:16 | self_0 | z | ParameterDefinition | int 3 | runtime |
22-
| g_class_init.py:19 | self_1 | x | Pi(self_0) [true] | int 1 | runtime |
23-
| g_class_init.py:19 | self_1 | y | Pi(self_0) [true] | int 2 | runtime |
24-
| g_class_init.py:19 | self_1 | z | Pi(self_0) [true] | int 3 | runtime |
25-
| g_class_init.py:20 | self_2 | x | Pi(self_0) [false] | int 1 | runtime |
26-
| g_class_init.py:20 | self_2 | z | Pi(self_0) [false] | int 3 | runtime |
27-
| g_class_init.py:20 | self_3 | x | phi(self_1, self_2) | int 1 | runtime |
28-
| g_class_init.py:20 | self_3 | y | phi(self_1, self_2) | int 2 | runtime |
29-
| g_class_init.py:20 | self_3 | z | phi(self_1, self_2) | int 3 | runtime |
3021
| g_class_init.py:46 | self_3 | version | phi(self_1, self_2) | 'v2' | runtime |
3122
| g_class_init.py:46 | self_3 | version | phi(self_1, self_2) | 'v3' | runtime |
3223
| g_class_init.py:48 | self_1 | version | AttributeAssignment 'version'(self_0) | 'v2' | runtime |
3324
| g_class_init.py:50 | self_2 | version | AttributeAssignment 'version'(self_0) | 'v3' | runtime |
34-
| g_class_init.py:52 | self_0 | version | ParameterDefinition | 'v2' | runtime |
35-
| g_class_init.py:52 | self_0 | version | ParameterDefinition | 'v3' | runtime |
36-
| g_class_init.py:52 | self_2 | version | Pi(self_0) [false] | 'v3' | runtime |
37-
| g_class_init.py:52 | self_3 | version | phi(self_1, self_2) | 'v2' | runtime |
38-
| g_class_init.py:52 | self_3 | version | phi(self_1, self_2) | 'v3' | runtime |
39-
| g_class_init.py:54 | self_1 | version | Pi(self_0) [true] | 'v2' | runtime |
4025
| k_getsetattr.py:6 | self_0 | a | ParameterDefinition | float 7.0 | code/k_getsetattr.py:15 from runtime |
4126
| k_getsetattr.py:6 | self_0 | c | ParameterDefinition | int 2 | code/k_getsetattr.py:15 from runtime |
4227
| k_getsetattr.py:7 | self_1 | a | ArgumentRefinement(self_0) | int 0 | code/k_getsetattr.py:15 from runtime |
@@ -76,6 +61,6 @@
7661
| k_getsetattr.py:27 | c2_1 | a | AttributeAssignment 'a'(c2_0) | int 20 | runtime |
7762
| k_getsetattr.py:28 | c2_2 | a | phi(c2_0, c2_1) | int 20 | runtime |
7863
| k_getsetattr.py:31 | c3_1 | a | AttributeAssignment 'a'(c3_0) | int 30 | runtime |
64+
| m_attributes.py:6 | self_1 | a | AttributeAssignment 'a'(self_0) | Unknown value | runtime |
7965
| m_attributes.py:6 | self_1 | a | AttributeAssignment 'a'(self_0) | int 17 | runtime |
8066
| m_attributes.py:6 | self_1 | a | AttributeAssignment 'a'(self_0) | int 100 | code/m_attributes.py:13 from import |
81-
| m_attributes.py:8 | self_0 | a | ParameterDefinition | int 17 | runtime |
Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11

22
import python
33
private import semmle.python.pointsto.PointsTo
4-
private import semmle.python.pointsto.PointsToContext
4+
private import semmle.python.objects.ObjectInternal
55
import Util
66

7-
from EssaVariable var, string name, Object o, PointsToContext ctx
8-
where PointsTo::Test::ssa_variable_named_attribute_points_to(var, ctx, name, o, _, _) and not var.getSourceVariable() instanceof SpecialSsaSourceVariable
7+
from EssaVariable var, string name, ObjectInternal o, Context ctx
8+
where AttributePointsTo::variableAttributePointsTo(var, ctx, name, o, _) and not var.getSourceVariable() instanceof SpecialSsaSourceVariable
99
select
1010
locate(var.getDefinition().getLocation(), "abdfgikm"), var.getRepresentation(),
11-
name, var.getDefinition().getRepresentation(), repr(o), ctx
11+
name, var.getDefinition().getRepresentation(), o, ctx
1212

0 commit comments

Comments
 (0)