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

Skip to content

Commit dbf228d

Browse files
committed
Python points-to: Better handling of *args, **kwargs and procedures.
1 parent f5c3242 commit dbf228d

4 files changed

Lines changed: 43 additions & 7 deletions

File tree

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

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,12 +75,25 @@ class PythonFunctionObjectInternal extends CallableObjectInternal, TPythonFuncti
7575
override predicate callResult(PointsToContext callee, ObjectInternal obj, CfgOrigin origin) {
7676
exists(Function func, ControlFlowNode rval |
7777
func = this.getScope() and
78-
callee.appliesToScope(func) and
78+
callee.appliesToScope(func) |
7979
rval = func.getAReturnValueFlowNode() and
8080
PointsTo2::points_to(rval, callee, obj, origin)
81+
or
82+
exists(Return ret |
83+
ret.getScope() = func and
84+
PointsTo2::reachableBlock(ret.getAFlowNode().getBasicBlock(), callee) and
85+
not exists(ret.getValue()) and
86+
obj = ObjectInternal::none_() and
87+
origin = CfgOrigin::unknown()
88+
)
8189
)
8290
}
83-
override predicate callResult(ObjectInternal obj, CfgOrigin origin) { none() }
91+
92+
override predicate callResult(ObjectInternal obj, CfgOrigin origin) {
93+
this.getScope().isProcedure() and
94+
obj = ObjectInternal::none_() and
95+
origin = CfgOrigin::unknown()
96+
}
8497

8598
override predicate calleeAndOffset(Function scope, int paramOffset) {
8699
scope = this.getScope() and paramOffset = 0

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ class NoneObjectInternal extends ObjectInternal, TNone {
140140
}
141141

142142
override Builtin getBuiltin() {
143-
none()
143+
result = Builtin::special("None")
144144
}
145145

146146
override predicate callResult(PointsToContext callee, ObjectInternal obj, CfgOrigin origin) {

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

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,6 @@ module ObjectInternal {
292292
result = TNone()
293293
}
294294

295-
296295
ObjectInternal unknown() {
297296
result = TUnknown()
298297
}

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

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -520,7 +520,7 @@ module InterModulePointsTo {
520520
exists(string name, ModuleObjectInternal mod, CfgOrigin orig |
521521
from_import_imports(f, context, mod, name) and
522522
(mod.getSourceModule() != f.getEnclosingModule() or mod.isBuiltin()) and
523-
mod.attribute(name, value, origin) and
523+
mod.attribute(name, value, orig) and
524524
origin = orig.asCfgNodeOrHere(f)
525525
// TO DO... $ variables.
526526
//mod.getSourceModule() = f.getEnclosingModule() and
@@ -697,8 +697,8 @@ module InterProceduralPointsTo {
697697
named_parameter_points_to(def, context, value, origin)
698698
or
699699
default_parameter_points_to(def, context, value, origin)
700-
// or
701-
// special_parameter_points_to(def, context, value, origin)
700+
or
701+
special_parameter_points_to(def, context, value, origin)
702702
}
703703

704704
/** Helper for `parameter_points_to` */
@@ -745,6 +745,30 @@ module InterProceduralPointsTo {
745745
)
746746
}
747747

748+
/** Helper for parameter_points_to */
749+
pragma [noinline]
750+
private predicate special_parameter_points_to(ParameterDefinition def, PointsToContext context, ObjectInternal value, ControlFlowNode origin) {
751+
context.isRuntime() and
752+
origin = def.getDefiningNode() and
753+
exists(ControlFlowNode param |
754+
param = def.getDefiningNode() |
755+
exists(Function func | func.getVararg() = param.getNode()) and value = TUnknownInstance(ObjectInternal::builtin("tuple"))
756+
or
757+
exists(Function func | func.getKwarg() = param.getNode()) and value = TUnknownInstance(ObjectInternal::builtin("dict"))
758+
)
759+
or
760+
exists(PointsToContext caller, CallNode call, Function f, Parameter p |
761+
context.fromCall(call, caller) and
762+
context.appliesToScope(f) and
763+
f.getAnArg() = p and p = def.getParameter() and
764+
not p.isSelf() and
765+
not exists(call.getArg(p.getPosition())) and
766+
not exists(call.getArgByName(p.getName())) and
767+
(exists(call.getNode().getKwargs()) or exists(call.getNode().getStarargs())) and
768+
value = ObjectInternal::unknown() and origin = def.getDefiningNode()
769+
)
770+
}
771+
748772
/** Holds if the `(argument, caller)` pair matches up with `(param, callee)` pair across call. */
749773
cached predicate callsite_argument_transfer(ControlFlowNode argument, PointsToContext caller, ParameterDefinition param, PointsToContext callee) {
750774
exists(CallNode call, Function func, int n, int offset |

0 commit comments

Comments
 (0)