Python points-to: Handle varargs in callee.

This commit is contained in:
Mark Shannon
2019-06-03 12:00:59 +01:00
parent a6da4996a7
commit 468975b0e5
10 changed files with 191 additions and 10 deletions

View File

@@ -227,6 +227,10 @@ class Call extends Call_ {
result = this.getKwargs().(Dict).getAKey().(StrConst).getText()
}
int getPositionalArgumentCount() {
count(this.getStarargs()) < 2 and
result = count(this.getAPositionalArg())
}
}
/** A conditional expression such as, `body if test else orelse` */

View File

@@ -39,7 +39,9 @@ abstract class TupleObjectInternal extends SequenceObjectInternal {
}
private string contents(int n) {
n = this.length() and result = ""
n < 4 and n = this.length() and result = ""
or
n = 4 and n < this.length() and result = "... " + (this.length()-4).toString() + " more"
or
result = this.getItem(n).toString() + ", " + this.contents(n+1)
}
@@ -145,6 +147,34 @@ class PythonTupleObjectInternal extends TPythonTuple, TupleObjectInternal {
}
class VarargsTupleObjectInternal extends TVarargsTuple, TupleObjectInternal {
override predicate introducedAt(ControlFlowNode node, PointsToContext context) {
none()
}
override Builtin getBuiltin() {
none()
}
override ControlFlowNode getOrigin() {
none()
}
override ObjectInternal getItem(int n) {
exists(CallNode call, PointsToContext context, int offset, int length |
this = TVarargsTuple(call, context, offset, length) and
n < length and
PointsToInternal::pointsTo(call.getArg(offset+n), context, result, _)
)
}
override int length() {
this = TVarargsTuple(_, _, _, result)
}
}
/** The `sys.version_info` object. We treat this specially to prevent premature pruning and
* false positives when we are unsure of the actual version of Python that the code is expecting.
*/

View File

@@ -179,6 +179,11 @@ cached newtype TObject =
context.appliesTo(origin)
}
or
/* Varargs tuple */
TVarargsTuple(CallNode call, PointsToContext context, int offset, int length) {
InterProceduralPointsTo::varargs_tuple(call, _, context, _, offset, length)
}
or
/* `type` */
TType()
or

View File

@@ -899,17 +899,38 @@ module InterProceduralPointsTo {
pragma [noinline]
private predicate special_parameter_points_to(ParameterDefinition def, PointsToContext context, ObjectInternal value, ControlFlowNode origin) {
special_parameter_value(def, value) and
(
context.isRuntime()
or
exists(PointsToContext caller, CallNode call |
context.fromCall(call, caller) and
context.appliesToScope(def.getScope()) and
not exists(call.getArg(def.getParameter().getPosition())) and
not exists(call.getArgByName(def.getParameter().getName()))
)
context.isRuntime() and
origin = def.getDefiningNode()
or
exists(CallNode call, Function scope, PointsToContext caller, int offset, int length |
varargs_tuple(call, scope, caller, context, offset, length) and
value = TVarargsTuple(call, caller, offset, length) and
def.getScope() = scope
) and
origin = def.getDefiningNode()
or
exists(Function scope |
varargs_empty_tuple(scope, context) and
value.(BuiltinTupleObjectInternal).length() = 0 and
def.getScope() = scope
) and
origin = def.getDefiningNode()
}
predicate varargs_tuple(CallNode call, Function scope, PointsToContext caller, PointsToContext callee, int startOffset, int length) {
exists(int parameter_offset |
callsite_calls_function(call, caller, scope, callee, parameter_offset) and
startOffset = scope.getPositionalParameterCount() - parameter_offset and
length = call.getNode().getPositionalArgumentCount() - startOffset and
length > 0
)
}
predicate varargs_empty_tuple(Function scope, PointsToContext callee) {
exists(CallNode call, PointsToContext caller, int parameter_offset |
callsite_calls_function(call, caller, scope, callee, parameter_offset) and
scope.getPositionalParameterCount() - parameter_offset >= call.getNode().getPositionalArgumentCount()
)
}
/** Helper predicate for special_parameter_points_to */