mirror of
https://github.com/github/codeql.git
synced 2025-12-17 17:23:36 +01:00
Python points-to: Better handling of *args, **kwargs and procedures.
This commit is contained in:
@@ -75,12 +75,25 @@ class PythonFunctionObjectInternal extends CallableObjectInternal, TPythonFuncti
|
||||
override predicate callResult(PointsToContext callee, ObjectInternal obj, CfgOrigin origin) {
|
||||
exists(Function func, ControlFlowNode rval |
|
||||
func = this.getScope() and
|
||||
callee.appliesToScope(func) and
|
||||
callee.appliesToScope(func) |
|
||||
rval = func.getAReturnValueFlowNode() and
|
||||
PointsTo2::points_to(rval, callee, obj, origin)
|
||||
or
|
||||
exists(Return ret |
|
||||
ret.getScope() = func and
|
||||
PointsTo2::reachableBlock(ret.getAFlowNode().getBasicBlock(), callee) and
|
||||
not exists(ret.getValue()) and
|
||||
obj = ObjectInternal::none_() and
|
||||
origin = CfgOrigin::unknown()
|
||||
)
|
||||
)
|
||||
}
|
||||
override predicate callResult(ObjectInternal obj, CfgOrigin origin) { none() }
|
||||
|
||||
override predicate callResult(ObjectInternal obj, CfgOrigin origin) {
|
||||
this.getScope().isProcedure() and
|
||||
obj = ObjectInternal::none_() and
|
||||
origin = CfgOrigin::unknown()
|
||||
}
|
||||
|
||||
override predicate calleeAndOffset(Function scope, int paramOffset) {
|
||||
scope = this.getScope() and paramOffset = 0
|
||||
|
||||
@@ -140,7 +140,7 @@ class NoneObjectInternal extends ObjectInternal, TNone {
|
||||
}
|
||||
|
||||
override Builtin getBuiltin() {
|
||||
none()
|
||||
result = Builtin::special("None")
|
||||
}
|
||||
|
||||
override predicate callResult(PointsToContext callee, ObjectInternal obj, CfgOrigin origin) {
|
||||
|
||||
@@ -292,7 +292,6 @@ module ObjectInternal {
|
||||
result = TNone()
|
||||
}
|
||||
|
||||
|
||||
ObjectInternal unknown() {
|
||||
result = TUnknown()
|
||||
}
|
||||
|
||||
@@ -520,7 +520,7 @@ module InterModulePointsTo {
|
||||
exists(string name, ModuleObjectInternal mod, CfgOrigin orig |
|
||||
from_import_imports(f, context, mod, name) and
|
||||
(mod.getSourceModule() != f.getEnclosingModule() or mod.isBuiltin()) and
|
||||
mod.attribute(name, value, origin) and
|
||||
mod.attribute(name, value, orig) and
|
||||
origin = orig.asCfgNodeOrHere(f)
|
||||
// TO DO... $ variables.
|
||||
//mod.getSourceModule() = f.getEnclosingModule() and
|
||||
@@ -697,8 +697,8 @@ module InterProceduralPointsTo {
|
||||
named_parameter_points_to(def, context, value, origin)
|
||||
or
|
||||
default_parameter_points_to(def, context, value, origin)
|
||||
// or
|
||||
// special_parameter_points_to(def, context, value, origin)
|
||||
or
|
||||
special_parameter_points_to(def, context, value, origin)
|
||||
}
|
||||
|
||||
/** Helper for `parameter_points_to` */
|
||||
@@ -745,6 +745,30 @@ module InterProceduralPointsTo {
|
||||
)
|
||||
}
|
||||
|
||||
/** Helper for parameter_points_to */
|
||||
pragma [noinline]
|
||||
private predicate special_parameter_points_to(ParameterDefinition def, PointsToContext context, ObjectInternal value, ControlFlowNode origin) {
|
||||
context.isRuntime() and
|
||||
origin = def.getDefiningNode() and
|
||||
exists(ControlFlowNode param |
|
||||
param = def.getDefiningNode() |
|
||||
exists(Function func | func.getVararg() = param.getNode()) and value = TUnknownInstance(ObjectInternal::builtin("tuple"))
|
||||
or
|
||||
exists(Function func | func.getKwarg() = param.getNode()) and value = TUnknownInstance(ObjectInternal::builtin("dict"))
|
||||
)
|
||||
or
|
||||
exists(PointsToContext caller, CallNode call, Function f, Parameter p |
|
||||
context.fromCall(call, caller) and
|
||||
context.appliesToScope(f) and
|
||||
f.getAnArg() = p and p = def.getParameter() and
|
||||
not p.isSelf() and
|
||||
not exists(call.getArg(p.getPosition())) and
|
||||
not exists(call.getArgByName(p.getName())) and
|
||||
(exists(call.getNode().getKwargs()) or exists(call.getNode().getStarargs())) and
|
||||
value = ObjectInternal::unknown() and origin = def.getDefiningNode()
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if the `(argument, caller)` pair matches up with `(param, callee)` pair across call. */
|
||||
cached predicate callsite_argument_transfer(ControlFlowNode argument, PointsToContext caller, ParameterDefinition param, PointsToContext callee) {
|
||||
exists(CallNode call, Function func, int n, int offset |
|
||||
|
||||
Reference in New Issue
Block a user