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

Skip to content

Commit 31a95ce

Browse files
committed
Python points-to: Use strongly typed version of CfgOrigin.
1 parent 162bf51 commit 31a95ce

7 files changed

Lines changed: 100 additions & 84 deletions

File tree

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

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -82,11 +82,12 @@ class PythonFunctionObjectInternal extends CallableObjectInternal, TPythonFuncti
8282

8383
pragma [noinline]
8484
override predicate callResult(PointsToContext callee, ObjectInternal obj, CfgOrigin origin) {
85-
exists(Function func, ControlFlowNode rval |
85+
exists(Function func, ControlFlowNode rval, ControlFlowNode forigin |
8686
func = this.getScope() and
8787
callee.appliesToScope(func) |
8888
rval = func.getAReturnValueFlowNode() and
89-
PointsToInternal::pointsTo(rval, callee, obj, origin)
89+
PointsToInternal::pointsTo(rval, callee, obj, forigin) and
90+
origin = CfgOrigin::fromCfgNode(forigin)
9091
or
9192
PointsToInternal::reachableBlock(blockReturningNone(func), callee) and
9293
obj = ObjectInternal::none_() and
@@ -98,7 +99,7 @@ class PythonFunctionObjectInternal extends CallableObjectInternal, TPythonFuncti
9899
override predicate callResult(ObjectInternal obj, CfgOrigin origin) {
99100
this.getScope().isProcedure() and
100101
obj = ObjectInternal::none_() and
101-
origin = this.getScope().getEntryNode()
102+
origin = CfgOrigin::fromCfgNode(this.getScope().getEntryNode())
102103
}
103104

104105
override predicate calleeAndOffset(Function scope, int paramOffset) {

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ class BuiltinClassObjectInternal extends ClassObjectInternal, TBuiltinClassObjec
143143
}
144144

145145
override predicate attribute(string name, ObjectInternal value, CfgOrigin origin) {
146-
value = ObjectInternal::fromBuiltin(this.getBuiltin().getMember(name)) and
146+
value = ObjectInternal::fromBuiltin(this.getBuiltin().getMember(name)) and
147147
origin = CfgOrigin::unknown()
148148
}
149149

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -159,21 +159,21 @@ class PackageObjectInternal extends ModuleObjectInternal, TPackageObject {
159159
not exists(EssaVariable var | var.getAUse() = init.getANormalExit() and var.getSourceVariable().getName() = name) and
160160
ModuleAttributes::pointsToAtExit(init, name, ObjectInternal::undefined(), _) and
161161
value = this.submodule(name) and
162-
origin = CfgOrigin::fromModule(value)
162+
origin = CfgOrigin::fromObject(value)
163163
)
164164
or
165165
this.hasNoInitModule() and
166166
exists(ModuleObjectInternal mod |
167167
mod = this.submodule(name) and
168168
value = mod |
169-
origin = CfgOrigin::fromModule(mod)
169+
origin = CfgOrigin::fromObject(mod)
170170
)
171171
}
172172

173173
override predicate attributesUnknown() { none() }
174174

175175
override ControlFlowNode getOrigin() {
176-
none()
176+
result = this.getSourceModule().getEntryNode()
177177
}
178178

179179
}

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,9 +77,9 @@ class ObjectInternal extends TObject {
7777

7878
abstract predicate attributesUnknown();
7979

80-
/** For backwards compatibility shim -- Not all objects have a "source"
80+
/** For backwards compatibility shim -- Not all objects have a "source".
8181
* Objects (except unknown and undefined values) should attempt to return
82-
* exactly one result for either this method`.
82+
* exactly one result for this method.
8383
* */
8484
@py_object getSource() {
8585
result = this.getOrigin()

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

Lines changed: 82 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -8,44 +8,7 @@ private import semmle.python.pointsto.MRO2
88
private import semmle.python.types.Builtins
99

1010
/* Use this version for speed */
11-
library class CfgOrigin extends @py_object {
12-
13-
string toString() {
14-
/* Not to be displayed */
15-
none()
16-
}
17-
18-
/** Get a `ControlFlowNode` from `this` or `here`.
19-
* If `this` is a ControlFlowNode then use that, otherwise fall back on `here`
20-
*/
21-
pragma[inline]
22-
ControlFlowNode asCfgNodeOrHere(ControlFlowNode here) {
23-
result = this
24-
or
25-
not this instanceof ControlFlowNode and result = here
26-
}
27-
28-
ControlFlowNode toCfgNode() {
29-
result = this
30-
}
31-
32-
pragma[inline]
33-
CfgOrigin fix(ControlFlowNode here) {
34-
if this = Builtin::unknown() then
35-
result = here
36-
else
37-
result = this
38-
}
39-
40-
}
41-
42-
/* Use this version for stronger type-checking */
43-
//private newtype TCfgOrigin =
44-
// TUnknownOrigin()
45-
// or
46-
// TCfgOrigin(ControlFlowNode f)
47-
//
48-
//library class CfgOrigin extends TCfgOrigin {
11+
//library class CfgOrigin extends @py_object {
4912
//
5013
// string toString() {
5114
// /* Not to be displayed */
@@ -57,44 +20,92 @@ library class CfgOrigin extends @py_object {
5720
// */
5821
// pragma[inline]
5922
// ControlFlowNode asCfgNodeOrHere(ControlFlowNode here) {
60-
// this = TUnknownOrigin() and result = here
23+
// result = this
6124
// or
62-
// this = TCfgOrigin(result)
25+
// not this instanceof ControlFlowNode and result = here
6326
// }
6427
//
6528
// ControlFlowNode toCfgNode() {
66-
// this = TCfgOrigin(result)
29+
// result = this
6730
// }
6831
//
32+
// pragma[inline]
6933
// CfgOrigin fix(ControlFlowNode here) {
70-
// this = TUnknownOrigin() and result = TCfgOrigin(here)
71-
// or
72-
// not this = TUnknownOrigin() and result = this
34+
// if this = Builtin::unknown() then
35+
// result = here
36+
// else
37+
// result = this
7338
// }
39+
//
7440
//}
7541
//
42+
//module CfgOrigin {
43+
//
44+
// CfgOrigin fromCfgNode(ControlFlowNode f) {
45+
// result = f
46+
// }
47+
//
48+
// CfgOrigin unknown() {
49+
// result = Builtin::unknown()
50+
// }
51+
//
52+
// CfgOrigin fromObject(ObjectInternal obj) {
53+
// obj.isBuiltin() and result = unknown()
54+
// or
55+
// result = obj.getOrigin()
56+
// }
57+
//
58+
//}
7659

60+
/* Use this version for stronger type-checking */
61+
private newtype TCfgOrigin =
62+
TUnknownOrigin()
63+
or
64+
TFlowNodeOrigin(ControlFlowNode f)
7765

78-
module CfgOrigin {
66+
library class CfgOrigin extends TCfgOrigin {
7967

80-
CfgOrigin fromCfgNode(ControlFlowNode f) {
81-
result = f
68+
string toString() {
69+
/* Not to be displayed */
70+
none()
8271
}
8372

84-
CfgOrigin unknown() {
85-
result = Builtin::unknown()
73+
/** Get a `ControlFlowNode` from `this` or `here`.
74+
* If `this` is a ControlFlowNode then use that, otherwise fall back on `here`
75+
*/
76+
pragma[inline]
77+
ControlFlowNode asCfgNodeOrHere(ControlFlowNode here) {
78+
this = TUnknownOrigin() and result = here
79+
or
80+
this = TFlowNodeOrigin(result)
8681
}
8782

88-
CfgOrigin fromModule(ModuleObjectInternal mod) {
89-
mod.isBuiltin() and result = unknown()
83+
ControlFlowNode toCfgNode() {
84+
this = TFlowNodeOrigin(result)
85+
}
86+
87+
CfgOrigin fix(ControlFlowNode here) {
88+
this = TUnknownOrigin() and result = TFlowNodeOrigin(here)
9089
or
91-
result = mod.getSourceModule().getEntryNode()
90+
not this = TUnknownOrigin() and result = this
91+
}
92+
93+
}
94+
95+
module CfgOrigin {
96+
97+
CfgOrigin fromCfgNode(ControlFlowNode f) {
98+
result = TFlowNodeOrigin(f)
99+
}
100+
101+
CfgOrigin unknown() {
102+
result = TUnknownOrigin()
92103
}
93104

94105
CfgOrigin fromObject(ObjectInternal obj) {
95106
obj.isBuiltin() and result = unknown()
96107
or
97-
result = obj.getOrigin()
108+
result = fromCfgNode(obj.getOrigin())
98109
}
99110

100111
}
@@ -106,7 +117,7 @@ module PointsTo {
106117
PointsToInternal::pointsTo(f, context, value, origin)
107118
}
108119

109-
predicate variablePointsTo(EssaVariable var, PointsToContext context, ObjectInternal value, ControlFlowNode origin) {
120+
predicate variablePointsTo(EssaVariable var, PointsToContext context, ObjectInternal value, CfgOrigin origin) {
110121
PointsToInternal::variablePointsTo(var, context, value, origin)
111122
}
112123

@@ -149,8 +160,7 @@ module PointsTo {
149160
exists(Value value |
150161
PointsToInternal::variablePointsTo(var, context, value, origin) and
151162
cls = value.getClass().getSource() |
152-
obj = value.getSource() or
153-
not exists(value.getSource()) and obj = origin
163+
obj = value.getSource()
154164
)
155165
}
156166

@@ -444,17 +454,20 @@ cached module PointsToInternal {
444454
)
445455
}
446456

447-
private predicate self_parameter_points_to(ParameterDefinition def, PointsToContext context, ObjectInternal value, CfgOrigin origin) {
448-
origin = CfgOrigin::fromCfgNode(def.getDefiningNode()) and
457+
private predicate self_parameter_points_to(ParameterDefinition def, PointsToContext context, ObjectInternal value, ControlFlowNode origin) {
458+
origin = def.getDefiningNode() and
449459
value.(SelfInstanceInternal).parameterAndContext(def, context)
450460
}
451461

452462
/** Holds if ESSA edge refinement, `def`, refers to `(value, cls, origin)`. */
453463
private predicate ssa_filter_definition_points_to(PyEdgeRefinement def, PointsToContext context, ObjectInternal value, CfgOrigin origin) {
454-
def.getSense() = ssa_filter_definition_bool(def, context, value, origin)
464+
exists(ControlFlowNode orig |
465+
def.getSense() = ssa_filter_definition_bool(def, context, value, orig) and
466+
origin = CfgOrigin::fromCfgNode(orig)
467+
)
455468
}
456469

457-
private boolean ssa_filter_definition_bool(PyEdgeRefinement def, PointsToContext context, ObjectInternal value, CfgOrigin origin) {
470+
private boolean ssa_filter_definition_bool(PyEdgeRefinement def, PointsToContext context, ObjectInternal value, ControlFlowNode origin) {
458471
result = Conditionals::testEvaluates(def.getTest(), def.getInput().getASourceUse(), context, value, origin)
459472
}
460473

@@ -643,7 +656,7 @@ module InterModulePointsTo {
643656
exists(PackageObjectInternal package |
644657
package.getSourceModule() = def.getDefiningNode().getScope() |
645658
value = package.submodule(def.getSourceVariable().getName()) and
646-
origin = CfgOrigin::fromModule(value).fix(def.getDefiningNode()) and
659+
origin = CfgOrigin::fromObject(value).asCfgNodeOrHere(def.getDefiningNode()) and
647660
context.isImport()
648661
)
649662
}
@@ -748,7 +761,7 @@ module InterProceduralPointsTo {
748761
predicate call_points_to(CallNode f, PointsToContext context, ObjectInternal value, ControlFlowNode origin) {
749762
exists(ObjectInternal func, CfgOrigin resultOrigin |
750763
call_points_to_callee(f, context, func) and
751-
origin = resultOrigin.fix(f)
764+
origin = resultOrigin.asCfgNodeOrHere(f)
752765
|
753766
exists(PointsToContext callee |
754767
callee.fromCall(f, context) and
@@ -816,7 +829,7 @@ module InterProceduralPointsTo {
816829
func = method.getScope() and
817830
def.getScope() = func and
818831
value = method.getSelf() and
819-
origin = CfgOrigin::fromObject(value)
832+
origin = value.getOrigin()
820833
)
821834
}
822835

@@ -1007,11 +1020,11 @@ module Expressions {
10071020
attr.isLoad() and
10081021
exists(string name |
10091022
attr.getObject(name) = obj and
1010-
PointsTo::pointsTo(obj, context, objvalue, _)
1023+
PointsToInternal::pointsTo(obj, context, objvalue, _)
10111024
|
10121025
exists(CfgOrigin orig |
10131026
objvalue.attribute(name, value, orig) and
1014-
origin = orig.fix(attr)
1027+
origin = orig.asCfgNodeOrHere(attr)
10151028
)
10161029
or
10171030
objvalue.attributesUnknown() and
@@ -1022,7 +1035,7 @@ module Expressions {
10221035
predicate subscriptPointsTo(SubscriptNode subscr, PointsToContext context, ObjectInternal value, ControlFlowNode origin, ControlFlowNode obj, ObjectInternal objvalue) {
10231036
subscr.isLoad() and
10241037
obj = subscr.getObject() and
1025-
PointsTo::pointsTo(obj, context, objvalue, _) and
1038+
PointsToInternal::pointsTo(obj, context, objvalue, _) and
10261039
value = ObjectInternal::unknown() and origin = subscr
10271040
}
10281041

@@ -1033,15 +1046,15 @@ module Expressions {
10331046
// TO DO...
10341047
// Track some integer values through `|` and the types of some objects
10351048
operand = b.getAnOperand() and
1036-
PointsTo::pointsTo(operand, context, opvalue, _) and
1049+
PointsToInternal::pointsTo(operand, context, opvalue, _) and
10371050
value = ObjectInternal::unknown() and origin = b
10381051
}
10391052

10401053
predicate unaryPointsTo(UnaryExprNode u, PointsToContext context, ObjectInternal value, ControlFlowNode origin, ControlFlowNode operand, ObjectInternal opvalue) {
10411054
exists(Unaryop op |
10421055
op = u.getNode().getOp() and
10431056
operand = u.getOperand() and
1044-
PointsTo::pointsTo(operand, context, opvalue, _)
1057+
PointsToInternal::pointsTo(operand, context, opvalue, _)
10451058
|
10461059
op instanceof Not and value = ObjectInternal::bool(opvalue.booleanValue().booleanNot())
10471060
or
@@ -1636,7 +1649,7 @@ cached module Types {
16361649

16371650
module AttributePointsTo {
16381651

1639-
predicate attributePointsTo(ControlFlowNode f, Context context, string name, ObjectInternal value, CfgOrigin origin) {
1652+
predicate attributePointsTo(ControlFlowNode f, Context context, string name, ObjectInternal value, ControlFlowNode origin) {
16401653
exists(ObjectInternal obj, Context prev, AttributeAssignment def |
16411654
PointsToInternal::pointsTo(f, context, obj, _) and
16421655
PointsToInternal::variablePointsTo(def.getInput(), prev, obj, _) and

python/ql/src/semmle/python/types/ClassObject.qll

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -134,10 +134,11 @@ class ClassObject extends Object {
134134

135135
/** Whether the named attribute refers to the object, class and origin */
136136
predicate attributeRefersTo(string name, Object obj, ClassObject cls, ControlFlowNode origin) {
137-
exists(Value val |
138-
theClass().attribute(name, val, origin) and
137+
exists(Value val, CfgOrigin valorig |
138+
theClass().attribute(name, val, valorig) and
139139
obj = val.getSource() and
140-
cls = val.getClass().getSource()
140+
cls = val.getClass().getSource() and
141+
origin = valorig.toCfgNode()
141142
)
142143
}
143144

python/ql/src/semmle/python/types/ModuleObject.qll

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,10 @@ abstract class ModuleObject extends Object {
5050
}
5151

5252
predicate attributeRefersTo(string name, Object obj, ControlFlowNode origin) {
53-
exists(Value val |
54-
theModule().(ModuleObjectInternal).attribute(name, val, origin) and
55-
obj = val.getSource()
53+
exists(Value val, CfgOrigin valorig |
54+
theModule().(ModuleObjectInternal).attribute(name, val, valorig) and
55+
obj = val.getSource() and
56+
origin = valorig.toCfgNode()
5657
)
5758
}
5859

0 commit comments

Comments
 (0)