Skip to content

Commit ff23f8e

Browse files
authored
Merge pull request #9855 from tausbn/python-fix-bad-scope_entry_transfer-join
Python: Fix bad join in scope entry transfer
2 parents 5259025 + 87960b6 commit ff23f8e

File tree

1 file changed

+41
-18
lines changed
  • python/ql/lib/semmle/python/pointsto

1 file changed

+41
-18
lines changed

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

Lines changed: 41 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,41 @@ predicate builtin_name_points_to(string name, Object value, ClassObject cls) {
273273
value = Object::builtin(name) and cls.asBuiltin() = value.asBuiltin().getClass()
274274
}
275275

276+
pragma[nomagic]
277+
private predicate essa_var_scope(SsaSourceVariable var, Scope pred_scope, EssaVariable pred_var) {
278+
BaseFlow::reaches_exit(pred_var) and
279+
pred_var.getScope() = pred_scope and
280+
var = pred_var.getSourceVariable()
281+
}
282+
283+
pragma[nomagic]
284+
private predicate scope_entry_def_scope(
285+
SsaSourceVariable var, Scope succ_scope, ScopeEntryDefinition succ_def
286+
) {
287+
var = succ_def.getSourceVariable() and
288+
succ_def.getScope() = succ_scope
289+
}
290+
291+
pragma[nomagic]
292+
private predicate step_through_init(Scope succ_scope, Scope pred_scope, Scope init) {
293+
init.getName() = "__init__" and
294+
init.precedes(succ_scope) and
295+
pred_scope.precedes(init)
296+
}
297+
298+
pragma[nomagic]
299+
private predicate scope_entry_value_transfer_through_init(
300+
EssaVariable pred_var, Scope pred_scope, ScopeEntryDefinition succ_def, Scope succ_scope
301+
) {
302+
exists(SsaSourceVariable var, Scope init |
303+
var instanceof GlobalVariable and
304+
essa_var_scope(var, pragma[only_bind_into](pred_scope), pred_var) and
305+
scope_entry_def_scope(var, succ_scope, succ_def) and
306+
step_through_init(succ_scope, pragma[only_bind_into](pred_scope), init) and
307+
not var.(Variable).getAStore().getScope() = init
308+
)
309+
}
310+
276311
module BaseFlow {
277312
predicate reaches_exit(EssaVariable var) { var.getAUse() = var.getScope().getANormalExit() }
278313

@@ -283,27 +318,15 @@ module BaseFlow {
283318
) {
284319
Stages::DataFlow::ref() and
285320
exists(SsaSourceVariable var |
286-
reaches_exit(pred_var) and
287-
pred_var.getScope() = pred_scope and
288-
var = pred_var.getSourceVariable() and
289-
var = succ_def.getSourceVariable() and
290-
succ_def.getScope() = succ_scope
321+
essa_var_scope(var, pred_scope, pred_var) and
322+
scope_entry_def_scope(var, succ_scope, succ_def)
291323
|
292324
pred_scope.precedes(succ_scope)
293-
or
294-
/*
295-
* If an `__init__` method does not modify the global variable, then
296-
* we can skip it and take the value directly from the module.
297-
*/
298-
299-
exists(Scope init |
300-
init.getName() = "__init__" and
301-
init.precedes(succ_scope) and
302-
pred_scope.precedes(init) and
303-
not var.(Variable).getAStore().getScope() = init and
304-
var instanceof GlobalVariable
305-
)
306325
)
326+
or
327+
// If an `__init__` method does not modify the global variable, then
328+
// we can skip it and take the value directly from the module.
329+
scope_entry_value_transfer_through_init(pred_var, pred_scope, succ_def, succ_scope)
307330
}
308331
}
309332

0 commit comments

Comments
 (0)