Skip to content

Commit 33135e9

Browse files
authored
Python: Add magic to named_argument_transfer
This predicate was materialised as a _big_, _cached_ relation: ``` (169s) Tuple counts for PointsTo::InterProceduralPointsTo::named_argument_transfer#ffff#join_rhs/4@38ce07 after 53.4s: 25212 ~4% {3} r1 = SCAN Function::Function::getArgByName_dispred#fff OUTPUT In.1, In.0 'arg1', In.2 'arg2' 159751200 ~0% {4} r2 = JOIN r1 WITH Flow::CallNode::getArgByName_dispred#fff_102#join_rhs ON FIRST 1 OUTPUT Rhs.1 'arg0', Lhs.1 'arg1', Lhs.2 'arg2', Rhs.2 'arg3' return r2 ``` ... However it's only used in a single place (where it is immediately joined with the points-to relation to relate the caller and argument), none of these joins were ever larger than 2000 tuples. This made it pretty clear that we could gain something by pushing in that points-to join as a bit of manual magic. However, doing so didn't actually fix anything, since the join-orderer then decided to join `func.getArgByName(name)` with `call.getArgByName(name)` on `name` as the first thing (which caused a join of the same size as above). Unbinding didn't work, since `name` would then be an unbound `string`, so instead I factored out relating the function, parameter, and name thereof into its own predicate. (I could also have done this with the call, but I would expect there to be more calls than function definitions in general.) Overall, this resulted in going from ``` (709s) Definitions.ql-7:PointsTo::InterProceduralPointsTo::named_argument_transfer#ffff#join_rhs ......... 53.5s Definitions.ql-7:Instances::InstanceObject::initializer_dispred#fbf ............................... 35.3s (456 evaluations with max 136ms in Instances::InstanceObject::initializer_dispred#fbf/3@i110#0508e8) Definitions.ql-10:DefinitionTracking::jump_to_defn_attribute#fbf .................................. 27s (100 evaluations with max 12.8s in DefinitionTracking::jump_to_defn_attribute#fbf/3@i1#fc1f7x) Definitions.ql-7:PointsTo::PointsToInternal::pointsTo#ffff ........................................ 16.1s (681 evaluations with max 2.5s in PointsTo::PointsToInternal::pointsTo#ffff/4@i4#0508eg) Definitions.ql-7:Constants::ConstantObjectInternal::attribute#ffff ................................ 13.4s (505 evaluations with max 50ms in Constants::ConstantObjectInternal::attribute#ffff/4@i153#0508e5) Definitions.ql-10:DefinitionTracking::assignment_jump_to_defn_attribute#fbf ....................... 12.4s (99 evaluations with max 11.8s in DefinitionTracking::assignment_jump_to_defn_attribute#fbf/3@i2#fc1f 7z) ... ``` to ``` (668s) Definitions.ql-7:Instances::InstanceObject::initializer_dispred#fbf ................... 35.4s (456 evaluations with max 140ms in Instances::InstanceObject::initializer_dispred#fbf/3@i110#bf4328) Definitions.ql-10:DefinitionTracking::jump_to_defn_attribute#fbf ...................... 27.4s (100 evaluations with max 13.3s in DefinitionTracking::jump_to_defn_attribute#fbf/3@i1#679d7x) Definitions.ql-7:PointsTo::PointsToInternal::pointsTo#ffff ............................ 16.1s (681 evaluations with max 2.5s in PointsTo::PointsToInternal::pointsTo#ffff/4@i4#bf432g) Definitions.ql-7:Constants::ConstantObjectInternal::attribute#ffff .................... 14.4s (505 evaluations with max 51ms in Constants::ConstantObjectInternal::attribute#ffff/4@i140#bf4325) Definitions.ql-10:DefinitionTracking::assignment_jump_to_defn_attribute#fbf ........... 12.3s (99 evaluations with max 11.7s in DefinitionTracking::assignment_jump_to_defn_attribute#fbf/3@i2#679d 7z) ... ```
1 parent e2f79d8 commit 33135e9

File tree

1 file changed

+7
-1
lines changed

1 file changed

+7
-1
lines changed

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

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1195,16 +1195,22 @@ module InterProceduralPointsTo {
11951195
ControlFlowNode argument, PointsToContext caller, ParameterDefinition param,
11961196
PointsToContext callee
11971197
) {
1198+
PointsToInternal::pointsTo(argument, caller, _, _) and
11981199
exists(CallNode call, Function func, int offset |
11991200
callsite_calls_function(call, caller, func, callee, offset)
12001201
|
12011202
exists(string name |
12021203
argument = call.getArgByName(name) and
1203-
param.getParameter() = func.getArgByName(name)
1204+
function_parameter_name(func, param, name)
12041205
)
12051206
)
12061207
}
12071208

1209+
pragma[nomagic]
1210+
private predicate function_parameter_name(Function func, ParameterDefinition param, string name) {
1211+
param.getParameter() = func.getArgByName(name)
1212+
}
1213+
12081214
/**
12091215
* Holds if the `call` with context `caller` calls the function `scope` in context `callee`
12101216
* and the offset from argument to parameter is `parameter_offset`

0 commit comments

Comments
 (0)