Skip to content

Commit 1d94f6d

Browse files
committed
Python: Fix several bad join orders.
Performance on `taers232c/GAMADV-X` (which exhibited pathological behaviour in the most recent dist upgrade) went from ~670s to ~313s on `py/hardcoded-credentials`. There are still a few tuple counts in the 10-100 million range, but this commit takes care of all of the ones that numbered in the billions. (A single tuple count in the 100-1000 million range remains, but it appears to be less critical, taking only two seconds to calculate.)
1 parent 5cea452 commit 1d94f6d

File tree

2 files changed

+37
-7
lines changed

2 files changed

+37
-7
lines changed

python/ql/src/semmle/python/essa/Essa.qll

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,16 @@ class EssaVariable extends TEssaDefinition {
5050
* Note that this differs from `EssaVariable.getAUse()`.
5151
*/
5252
ControlFlowNode getASourceUse() {
53+
exists(SsaSourceVariable var |
54+
result = use_for_var(var) and
55+
result = var.getASourceUse()
56+
)
57+
}
58+
59+
pragma[nomagic]
60+
private ControlFlowNode use_for_var(SsaSourceVariable var) {
5361
result = this.getAUse() and
54-
result = this.getSourceVariable().getASourceUse()
62+
var = this.getSourceVariable()
5563
}
5664

5765
/** Gets the scope of this variable. */
@@ -268,11 +276,16 @@ class PhiFunction extends EssaDefinition, TPhiFunction {
268276
not exists(this.inputEdgeRefinement(result))
269277
}
270278

279+
pragma[noinline]
280+
private SsaSourceVariable pred_var(BasicBlock pred) {
281+
result = this.getSourceVariable() and
282+
pred = this.nonPiInput()
283+
}
284+
271285
/** Gets another definition of the same source variable that reaches this definition. */
272286
private EssaDefinition reachingDefinition(BasicBlock pred) {
273287
result.getScope() = this.getScope() and
274-
result.getSourceVariable() = this.getSourceVariable() and
275-
pred = this.nonPiInput() and
288+
result.getSourceVariable() = pred_var(pred) and
276289
result.reachesEndOfBlock(pred)
277290
}
278291

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

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -578,6 +578,13 @@ cached module PointsToInternal {
578578
)
579579
or
580580
/* Undefined variable */
581+
undefined_variable(def, context, value, origin)
582+
or
583+
/* Builtin not defined in outer scope */
584+
builtin_not_in_outer_scope(def, context, value, origin)
585+
}
586+
587+
private predicate undefined_variable(ScopeEntryDefinition def, PointsToContext context, ObjectInternal value, ControlFlowNode origin) {
581588
exists(Scope scope |
582589
not def.getVariable().getName() = "__name__" and
583590
not def.getVariable().isMetaVariable() and
@@ -587,8 +594,9 @@ cached module PointsToInternal {
587594
def.getSourceVariable() instanceof LocalVariable and (context.isImport() or context.isRuntime() or context.isMain())
588595
) and
589596
value = ObjectInternal::undefined() and origin = def.getDefiningNode()
590-
or
591-
/* Builtin not defined in outer scope */
597+
}
598+
599+
private predicate builtin_not_in_outer_scope(ScopeEntryDefinition def, PointsToContext context, ObjectInternal value, ControlFlowNode origin) {
592600
exists(Module mod, GlobalVariable var |
593601
var = def.getSourceVariable() and
594602
mod = def.getScope().getEnclosingModule() and
@@ -1113,8 +1121,17 @@ module InterProceduralPointsTo {
11131121
* Transfer of values from the callsite to the callee, for enclosing variables, but not arguments/parameters. */
11141122
pragma [noinline]
11151123
private predicate callsite_entry_value_transfer(EssaVariable caller_var, PointsToContext caller, ScopeEntryDefinition entry_def, PointsToContext callee) {
1116-
entry_def.getSourceVariable() = caller_var.getSourceVariable() and
1117-
callsite_calls_function(caller_var.getAUse(), caller, entry_def.getScope(), callee, _)
1124+
exists(ControlFlowNode use, SsaSourceVariable var |
1125+
var_and_use(caller_var, use, var) and
1126+
entry_def.getSourceVariable() = var and
1127+
callsite_calls_function(use, caller, entry_def.getScope(), callee, _)
1128+
)
1129+
}
1130+
1131+
pragma[nomagic]
1132+
private predicate var_and_use(EssaVariable caller_var, ControlFlowNode use, SsaSourceVariable var) {
1133+
use = caller_var.getAUse() and
1134+
var = caller_var.getSourceVariable()
11181135
}
11191136

11201137
/** Helper for `scope_entry_value_transfer`. */

0 commit comments

Comments
 (0)