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

Skip to content

Commit cd34e23

Browse files
committed
Python points-to: Bring attribute points-to to effective parity with old points-to.
1 parent 2e6c3c9 commit cd34e23

5 files changed

Lines changed: 120 additions & 42 deletions

File tree

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ class FloatObjectInternal extends ConstantObjectInternal, TFloat {
198198

199199
override string toString() {
200200
if this.floatValue() = this.floatValue().floor() then (
201-
result = "float " + this.floatValue().toString() + ".0"
201+
result = "float " + this.floatValue().floor().toString() + ".0"
202202
) else (
203203
result = "float " + this.floatValue().toString()
204204
)

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,18 @@ class SpecificInstanceInternal extends TSpecificInstance, ObjectInternal {
7979
override predicate attribute(string name, ObjectInternal value, CfgOrigin origin) {
8080
PointsToInternal::attributeRequired(this, name) and
8181
instance_getattr(this, Types::getMro(this.getClass()), name, value, origin)
82+
or
83+
exists(EssaVariable self, PythonFunctionObjectInternal init, Context callee |
84+
BaseFlow::reaches_exit(self) and
85+
self.getSourceVariable().(Variable).isSelf() and
86+
self.getScope() = init.getScope() and
87+
exists(CallNode call, Context caller, ClassObjectInternal cls |
88+
this = TSpecificInstance(call, cls, caller) and
89+
callee.fromCall(this.getOrigin(), caller) and
90+
cls.lookup("__init__", init, _)
91+
) and
92+
AttributePointsTo::variableAttributePointsTo(self, callee, name, value, origin)
93+
)
8294
}
8395

8496
override predicate attributesUnknown() { any() }

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

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -366,21 +366,9 @@ module ObjectInternal {
366366
}
367367

368368
ObjectInternal fromBuiltin(Builtin b) {
369-
result = TInt(b.intValue())
370-
or
371-
result = TString(b.strValue())
372-
or
373-
result = TBuiltinClassObject(b)
374-
or
375-
result = TBuiltinFunctionObject(b)
376-
or
377-
result = TBuiltinOpaqueObject(b)
378-
or
379-
result = TBuiltinModuleObject(b)
380-
or
381-
result = TBuiltinMethodObject(b)
382-
or
383-
result = TBuiltinTuple(b)
369+
b = result.getBuiltin() and
370+
not b = Builtin::unknown() and
371+
not b = Builtin::unknownType()
384372
}
385373

386374
ObjectInternal classMethod() {

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -131,8 +131,9 @@ newtype TObject =
131131
PointsToInternal::pointsTo(call.getArg(0), ctx, getter, _)
132132
}
133133
or
134-
TDynamicClass(ControlFlowNode instantiation, ClassObjectInternal metacls, PointsToContext context) {
135-
PointsToInternal::pointsTo(instantiation.(CallNode).getFunction(), context, metacls, _) and
134+
TDynamicClass(CallNode instantiation, ClassObjectInternal metacls, PointsToContext context) {
135+
PointsToInternal::pointsTo(instantiation.getFunction(), context, metacls, _) and
136+
not count(instantiation.getAnArg()) = 1 and
136137
Types::getMro(metacls).contains(TType())
137138
}
138139

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

Lines changed: 101 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ module PointsTo {
126126
deprecated predicate
127127
points_to(ControlFlowNode f, PointsToContext context, Object obj, ClassObject cls, ControlFlowNode origin) {
128128
exists(Value value |
129-
pointsToValue(f, context, value, origin) and
129+
PointsToInternal::pointsTo(f, context, value, origin) and
130130
cls = value.getClass().getSource() |
131131
obj = value.getSource() or
132132
not exists(value.getSource()) and obj = origin
@@ -148,14 +148,6 @@ module PointsTo {
148148
)
149149
}
150150

151-
private predicate pointsToValue(ControlFlowNode f, PointsToContext context, Value value, ControlFlowNode origin) {
152-
PointsToInternal::pointsTo(f, context, value, origin)
153-
or
154-
exists(string name |
155-
AttributePointsTo::attributePointsTo(f.(AttrNode).getObject(name), context, name, value, origin)
156-
)
157-
}
158-
159151
deprecated predicate
160152
ssa_variable_points_to(EssaVariable var, PointsToContext context, Object obj, ClassObject cls, CfgOrigin origin) {
161153
exists(Value value |
@@ -199,6 +191,8 @@ cached module PointsToInternal {
199191
InterModulePointsTo::from_import_points_to(f, context, value, origin)
200192
or
201193
InterProceduralPointsTo::call_points_to(f, context, value, origin)
194+
or
195+
AttributePointsTo::pointsTo(f, context, value, origin)
202196
// To do... More stuff here :)
203197
// or
204198
// f.(CustomPointsToFact).pointsTo(context, value, origin)
@@ -1135,8 +1129,10 @@ module Expressions {
11351129

11361130
private boolean otherComparisonEvaluatesTo(CompareNode comp, PointsToContext context, ControlFlowNode operand, ObjectInternal opvalue) {
11371131
exists(Cmpop op |
1138-
comp.operands(operand, op, _) and
1139-
(op instanceof In or op instanceof NotIn) |
1132+
comp.operands(operand, op, _) or
1133+
comp.operands(_, op, operand)
1134+
|
1135+
(op instanceof In or op instanceof NotIn) and
11401136
PointsToInternal::pointsTo(operand, context, opvalue, _)
11411137
) and result = maybe()
11421138
}
@@ -1694,19 +1690,100 @@ cached module Types {
16941690

16951691
module AttributePointsTo {
16961692

1697-
predicate attributePointsTo(ControlFlowNode f, Context context, string name, ObjectInternal value, ControlFlowNode origin) {
1698-
exists(ObjectInternal defobj, Context prev, AttributeAssignment def, ObjectInternal useobj |
1699-
PointsToInternal::pointsTo(f, context, useobj, _) and
1700-
PointsToInternal::variablePointsTo(def.getInput(), prev, defobj, _) and
1701-
PointsToInternal::pointsTo(def.getValue(), prev, value, origin) and name = def.getName()
1702-
|
1703-
prev.getOuter*().getCall().getBasicBlock().reaches(context.getOuter*().getCall().getBasicBlock()) and
1704-
useobj.(SelfInstanceInternal).getClass() = defobj.(SelfInstanceInternal).getClass()
1705-
or
1706-
def.getScope().getScope*().precedes(f.getScope().getScope*()) and
1707-
useobj.(SelfInstanceInternal).getClass() = defobj.(SelfInstanceInternal).getClass()
1708-
or
1709-
def.getDefiningNode().getBasicBlock().dominates(f.getBasicBlock()) and defobj = useobj
1693+
predicate pointsTo(AttrNode f, Context context, ObjectInternal value, ControlFlowNode origin) {
1694+
exists(EssaVariable var, string name, CfgOrigin orig |
1695+
var.getASourceUse() = f.getObject(name) and
1696+
variableAttributePointsTo(var, context, name, value, orig) and
1697+
origin = orig.asCfgNodeOrHere(f)
1698+
)
1699+
}
1700+
1701+
predicate variableAttributePointsTo(EssaVariable var, Context context, string name, ObjectInternal value, CfgOrigin origin) {
1702+
definitionAttributePointsTo(var.getDefinition(), context, name, value, origin)
1703+
or
1704+
exists(EssaVariable prev |
1705+
var.getDefinition().(PhiFunction).getShortCircuitInput() = prev and
1706+
variableAttributePointsTo(prev, context, name, value, origin)
1707+
)
1708+
}
1709+
1710+
predicate definitionAttributePointsTo(EssaDefinition def, Context context, string name, ObjectInternal value, CfgOrigin origin) {
1711+
variableAttributePointsTo(def.(PhiFunction).getAnInput(), context, name, value, origin)
1712+
or
1713+
piNodeAttributePointsTo(def, context, name, value, origin)
1714+
or
1715+
refinementAttributePointsTo(def, context, name, value, origin)
1716+
or
1717+
selfParameterAttributePointsTo(def, context, name, value, origin)
1718+
or
1719+
selfMethodCallsitePointsTo(def, context, name, value, origin)
1720+
}
1721+
1722+
pragma [noinline]
1723+
private predicate refinementAttributePointsTo(EssaNodeRefinement def, PointsToContext context, string name, ObjectInternal value, CfgOrigin origin) {
1724+
attributeAssignmentAttributePointsTo(def, context, name, value, origin)
1725+
or
1726+
attributeDeleteAttributePointsTo(def, context, name, value, origin)
1727+
or
1728+
uniEdgedPhiAttributePointsTo(def, context, name, value, origin)
1729+
}
1730+
1731+
1732+
/** Attribute deletions have no effect as far as value tracking is concerned. */
1733+
pragma [noinline]
1734+
private predicate attributeAssignmentAttributePointsTo(AttributeAssignment def, PointsToContext context, string name, ObjectInternal value, CfgOrigin origin) {
1735+
def.getName() != name and
1736+
variableAttributePointsTo(def.getInput(), context, name, value, origin)
1737+
or
1738+
def.getName() = name and
1739+
exists(ControlFlowNode cfgnode |
1740+
PointsToInternal::pointsTo(def.getValue(), context, value, cfgnode) and
1741+
origin = CfgOrigin::fromCfgNode(cfgnode)
1742+
)
1743+
}
1744+
1745+
/** Attribute deletions have no effect as far as value tracking is concerned. */
1746+
pragma [noinline]
1747+
private predicate attributeDeleteAttributePointsTo(EssaAttributeDeletion def, PointsToContext context, string name, ObjectInternal value, CfgOrigin origin) {
1748+
def.getName() != name and
1749+
variableAttributePointsTo(def.getInput(), context, name, value, origin)
1750+
}
1751+
1752+
private predicate uniEdgedPhiAttributePointsTo(SingleSuccessorGuard uniphi, PointsToContext context, string name, ObjectInternal value, CfgOrigin origin) {
1753+
variableAttributePointsTo(uniphi.getInput(), context, name, value, origin)
1754+
}
1755+
1756+
private predicate piNodeAttributePointsTo(PyEdgeRefinement pi, PointsToContext context, string name, ObjectInternal value, CfgOrigin origin) {
1757+
variableAttributePointsTo(pi.getInput(), context, name, value, origin)
1758+
}
1759+
1760+
private predicate selfParameterAttributePointsTo(ParameterDefinition def, PointsToContext context, string name, ObjectInternal value, CfgOrigin origin) {
1761+
exists(MethodCallsiteRefinement call, Function func, PointsToContext caller |
1762+
selfMethodCall(call, caller, func, context) and
1763+
def.isSelf() and def.getScope() = func and
1764+
variableAttributePointsTo(call.getInput(), caller, name, value, origin)
1765+
)
1766+
}
1767+
1768+
/** Pass through for `self` for the implicit re-definition of `self` in `self.foo()`. */
1769+
private predicate selfMethodCallsitePointsTo(MethodCallsiteRefinement def, PointsToContext context, string name, ObjectInternal value, CfgOrigin origin) {
1770+
/* The value of self remains the same, only the attributes may change */
1771+
exists(Function func, PointsToContext callee, EssaVariable exit_self |
1772+
selfMethodCall(def, context, func, callee) and
1773+
exit_self.getSourceVariable().(Variable).isSelf() and
1774+
exit_self.getScope() = func and
1775+
BaseFlow::reaches_exit(exit_self) and
1776+
variableAttributePointsTo(exit_self, context, name, value, origin)
1777+
)
1778+
}
1779+
1780+
private predicate selfMethodCall(MethodCallsiteRefinement def, PointsToContext caller, Function func, PointsToContext callee) {
1781+
def.getInput().getSourceVariable().(Variable).isSelf() and
1782+
exists(PythonFunctionObjectInternal method, CallNode call |
1783+
method.getScope() = func and
1784+
call = method.getACall() and
1785+
call = def.getDefiningNode() and
1786+
callee.fromCall(call, caller)
17101787
)
17111788
}
17121789

0 commit comments

Comments
 (0)